def test_predict():
    # predict with homogeneous kernel
    y_pred_poly = _poly_predict(X, P, lams, kernel='poly', degree=3)
    K = homogeneous_kernel(X, P, degree=3)
    y_pred = np.dot(K, lams)
    assert_array_almost_equal(y_pred_poly, y_pred,
                              err_msg="Homogeneous prediction incorrect.")

    # predict with homogeneous kernel
    y_pred_poly = _poly_predict(X, P, lams, kernel='anova', degree=3)
    K = anova_kernel(X, P, degree=3)
    y_pred = np.dot(K, lams)
    assert_array_almost_equal(y_pred_poly, y_pred,
                              err_msg="ANOVA prediction incorrect.")
def check_classification_losses(loss, degree):
    y = np.sign(_poly_predict(X, P, lams, kernel="anova", degree=degree))
    clf = FactorizationMachineClassifier(degree=degree, loss=loss, beta=1e-3,
                                         fit_lower=None, fit_linear=False,
                                         tol=1e-3, random_state=0)
    clf.fit(X, y)
    assert_equal(1.0, clf.score(X, y))
def test_predict():
    # predict with homogeneous kernel
    y_pred_poly = _poly_predict(X, P, lams, kernel='poly', degree=3)
    K = homogeneous_kernel(X, P, degree=3)
    y_pred = np.dot(K, lams)
    assert_array_almost_equal(y_pred_poly,
                              y_pred,
                              err_msg="Homogeneous prediction incorrect.")

    # predict with homogeneous kernel
    y_pred_poly = _poly_predict(X, P, lams, kernel='anova', degree=3)
    K = anova_kernel(X, P, degree=3)
    y_pred = np.dot(K, lams)
    assert_array_almost_equal(y_pred_poly,
                              y_pred,
                              err_msg="ANOVA prediction incorrect.")
def test_augment():
    """Test that augmenting the data increases the dimension as expected"""
    y = _poly_predict(X, P, lams, kernel="anova", degree=3)
    fm = FactorizationMachineRegressor(degree=3, fit_lower='augment',
                                       fit_linear=True, tol=0.1)
    fm.fit(X, y)
    assert_equal(n_features + 1, fm.P_.shape[2],
                 msg="Augmenting is wrong with explicit linear term.")

    fm.set_params(fit_linear=False)
    fm.fit(X, y)
    assert_equal(n_features + 2, fm.P_.shape[2],
                 msg="Augmenting is wrong with augmented linear term.")
def check_fit(degree):
    y = _poly_predict(X, P, lams, kernel="anova", degree=degree)

    est = FactorizationMachineRegressor(degree=degree, n_components=5,
                                        fit_linear=False, fit_lower=None,
                                        max_iter=15000, beta=1e-6, tol=1e-3,
                                        random_state=0)
    est.fit(X, y)
    y_pred = est.predict(X)
    err = mean_squared_error(y, y_pred)

    assert_less_equal(
        err,
        1e-6,
        msg="Error {} too big for degree {}.".format(err, degree))
def check_improve(degree):
    y = _poly_predict(X, P, lams, kernel="anova", degree=degree)

    est = FactorizationMachineRegressor(degree=degree, n_components=5,
                                        fit_lower=None, fit_linear=False,
                                        beta=0.0001, max_iter=5, tol=0,
                                        random_state=0)
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        y_pred_5 = est.fit(X, y).predict(X)
        est.set_params(max_iter=10)
        y_pred_10 = est.fit(X, y).predict(X)

    assert_less_equal(mean_squared_error(y, y_pred_10),
                      mean_squared_error(y, y_pred_5),
                      msg="More iterations do not improve fit.")
def check_same_as_slow(degree):
    y = _poly_predict(X, P, lams, kernel="anova", degree=degree)

    reg = FactorizationMachineRegressor(degree=degree, n_components=5,
                                        fit_lower=None, fit_linear=False,
                                        beta=1, warm_start=False, tol=1e-3,
                                        max_iter=5, random_state=0)

    with warnings.catch_warnings():
        warnings.simplefilter('ignore')
        reg.fit(X, y)

        P_fit_slow = cd_direct_slow(X, y, lams=reg.lams_, degree=degree,
                                    n_components=5, beta=1, n_iter=5,
                                    tol=1e-3, random_state=0)

    assert_array_almost_equal(reg.P_[0, :, :], P_fit_slow, decimal=4)
def test_random_starts():
    noisy_y = _poly_predict(X, P, lams, kernel="anova", degree=2)
    noisy_y += 5. * rng.randn(noisy_y.shape[0])
    X_train, X_test = X[:10], X[10:]
    y_train, y_test = noisy_y[:10], noisy_y[10:]

    scores = []
    # init_lambdas='ones' is important to reduce variance here
    reg = FactorizationMachineRegressor(degree=2, n_components=n_components,
                                        beta=5, fit_lower=None,
                                        fit_linear=False, max_iter=2000,
                                        init_lambdas='ones', tol=0.001)
    for k in range(10):
        reg.set_params(random_state=k)
        y_pred = reg.fit(X_train, y_train).predict(X_test)
        scores.append(mean_squared_error(y_test, y_pred))

    assert_less_equal(np.std(scores), 0.001)
def check_same_as_slow(degree):

    # XXX: test fails under windows 32bit, presumably numerical issues.
    if ctypes.sizeof(ctypes.c_voidp) < 8:
        raise SkipTest("Numerical inconsistencies on Win32")

    y = _poly_predict(X, P, lams, kernel="anova", degree=degree)

    reg = FactorizationMachineRegressor(degree=degree, n_components=5,
                                        fit_lower=None, fit_linear=False,
                                        beta=1e-8, warm_start=False, tol=1e-3,
                                        max_iter=10, random_state=0)

    with warnings.catch_warnings():
        warnings.simplefilter('ignore')
        reg.fit(X, y)

        P_fit_slow = cd_direct_slow(X, y, lams=reg.lams_, degree=degree,
                                    n_components=5, beta=1e-8, n_iter=10,
                                    tol=1e-3, random_state=0)

    assert_array_almost_equal(reg.P_[0, :, :], P_fit_slow, decimal=4)
def check_overfit(degree):
    noisy_y = _poly_predict(X, P, lams, kernel="anova", degree=degree)
    noisy_y += 5. * rng.randn(noisy_y.shape[0])
    X_train, X_test = X[:10], X[10:]
    y_train, y_test = noisy_y[:10], noisy_y[10:]

    # weak regularization, should overfit
    est = FactorizationMachineRegressor(degree=degree, n_components=5,
                                        fit_linear=False, fit_lower=None,
                                        beta=1e-4, tol=0.01, random_state=0)
    y_train_pred_weak = est.fit(X_train, y_train).predict(X_train)
    y_test_pred_weak = est.predict(X_test)

    est.set_params(beta=10)  # high value of beta -> strong regularization
    y_train_pred_strong = est.fit(X_train, y_train).predict(X_train)
    y_test_pred_strong = est.predict(X_test)

    assert_less_equal(mean_squared_error(y_train, y_train_pred_weak),
                      mean_squared_error(y_train, y_train_pred_strong),
                      msg="Training error does not get worse with regul.")

    assert_less_equal(mean_squared_error(y_test, y_test_pred_strong),
                      mean_squared_error(y_test, y_test_pred_weak),
                      msg="Test error does not get better with regul.")
def check_warm_start(degree):
    y = _poly_predict(X, P, lams, kernel="anova", degree=degree)
    # Result should be the same if:
    # (a) running 10 iterations
    clf_10 = FactorizationMachineRegressor(degree=degree, n_components=5,
                                           fit_lower=None, fit_linear=False,
                                           max_iter=10, warm_start=False,
                                           random_state=0)
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        clf_10.fit(X, y)

    # (b) running 5 iterations and 5 more
    clf_5_5 = FactorizationMachineRegressor(degree=degree, n_components=5,
                                            fit_lower=None, fit_linear=False,
                                            max_iter=5, warm_start=True,
                                            random_state=0)
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        clf_5_5.fit(X, y)
        P_fit = clf_5_5.P_.copy()
        lams_fit = clf_5_5.lams_.copy()
        clf_5_5.fit(X, y)

    # (c) running 5 iterations when starting from previous point.
    clf_5 = FactorizationMachineRegressor(degree=degree, n_components=5,
                                          fit_lower=None, fit_linear=False,
                                          max_iter=5, warm_start=True,
                                          random_state=0)
    clf_5.P_ = P_fit
    clf_5.lams_ = lams_fit
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        clf_5.fit(X, y)

    assert_array_almost_equal(clf_10.P_, clf_5_5.P_)
    assert_array_almost_equal(clf_10.P_, clf_5.P_)

    # Prediction results should also be the same if:
    # (note: could not get this test to work for the exact P_.)

    noisy_y = _poly_predict(X, P, lams, kernel="anova", degree=2)
    noisy_y += rng.randn(noisy_y.shape[0])
    X_train, X_test = X[:10], X[10:]
    y_train, y_test = noisy_y[:10], noisy_y[10:]

    beta_low = 0.5
    beta = 0.1
    beta_hi = 1
    ref = FactorizationMachineRegressor(degree=degree, n_components=5,
                                        fit_linear=False, fit_lower=None,
                                        beta=beta, max_iter=20000,
                                        random_state=0)
    ref.fit(X_train, y_train)
    y_pred_ref = ref.predict(X_test)

    # (a) starting from lower beta, increasing and refitting
    from_low = FactorizationMachineRegressor(degree=degree, n_components=5,
                                             fit_lower=None, fit_linear=False,
                                             beta=beta_low, warm_start=True,
                                             random_state=0)
    from_low.fit(X_train, y_train)
    from_low.set_params(beta=beta)
    from_low.fit(X_train, y_train)
    y_pred_low = from_low.predict(X_test)

    # (b) starting from higher beta, decreasing and refitting
    from_hi = FactorizationMachineRegressor(degree=degree, n_components=5,
                                            fit_lower=None, fit_linear=False,
                                            beta=beta_hi, warm_start=True,
                                            random_state=0)
    from_hi.fit(X_train, y_train)
    from_hi.set_params(beta=beta)
    from_hi.fit(X_train, y_train)
    y_pred_hi = from_hi.predict(X_test)

    assert_array_almost_equal(y_pred_low, y_pred_ref, decimal=4)
    assert_array_almost_equal(y_pred_hi, y_pred_ref, decimal=4)
def test_convergence_warning():
    y = _poly_predict(X, P, lams, kernel="anova", degree=3)

    est = FactorizationMachineRegressor(degree=3, beta=1e-8, max_iter=1,
                                        random_state=0)
    assert_warns_message(UserWarning, "converge", est.fit, X, y)