Repository: scikit-learn/scikit-learn
File: sklearn/gaussian_process/tests/test_gpr.py (Python)

Code before:
    assert np.all(
        (np.abs(lml_gradient) < 1e-4)
        | (gpr.kernel_.theta == gpr.kernel_.bounds[:, 0])
        | (gpr.kernel_.theta == gpr.kernel_.bounds[:, 1])
    )


@pytest.mark.parametrize("kernel", non_fixed_kernels)
def test_solution_inside_bounds(kernel):
    # Test that hyperparameter-optimization remains in bounds#
    gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y)

    bounds = gpr.kernel_.bounds
    max_ = np.finfo(gpr.kernel_.theta.dtype).max
    tiny = 1e-10
    bounds[~np.isfinite(bounds[:, 1]), 1] = max_

    assert_array_less(bounds[:, 0], gpr.kernel_.theta + tiny)
    assert_array_less(gpr.kernel_.theta, bounds[:, 1] + tiny)


@pytest.mark.skipif(
    sp_version < parse_version("1.15.0"),
    reason="scipy.derivative requires version 1.15.0 or more",
)
@pytest.mark.xfail(raises=AssertionError)
@pytest.mark.parametrize("kernel", non_fixed_kernels)
def test_lml_gradient(kernel):
    # Clone the kernel object prior to mutating it to avoid any side effects between
    # GP tests:
    kernel = clone(kernel)
    # Compare analytic and numeric gradient of log marginal likelihood.
    gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y)

    length_scales = np.logspace(-3, 3, 100)

    def evaluate_grad_at_length_scales(length_scales):
        length_scale_param_name = next(
            name for name in kernel.get_params() if name.endswith("length_scale")
        )
        result = []
        for i, length_scale in enumerate(length_scales.flatten()):
            kernel.set_params(**{length_scale_param_name: length_scale})
            if type(kernel) in [Product, Sum] or len(kernel.theta) == 1:
                result.append(gpr.log_marginal_likelihood(kernel.theta))

            else:
                result.append(
                    [gpr.log_marginal_likelihood([theta]) for theta in kernel.theta]
                )
        if length_scales.ndim == 1:

Review comment (bug):
```suggestion
@pytest.mark.xfail(
    raises=AssertionError,
    reason="https://github.com/scikit-learn/scikit-learn/issues/31366",
)
```

Code after:

@pytest.mark.parametrize("kernel", non_fixed_kernels)
def test_solution_inside_bounds(kernel):
    # Test that hyperparameter-optimization remains in bounds#
    gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y)

    bounds = gpr.kernel_.bounds
    max_ = np.finfo(gpr.kernel_.theta.dtype).max
    tiny = 1e-10
    bounds[~np.isfinite(bounds[:, 1]), 1] = max_

    assert_array_less(bounds[:, 0], gpr.kernel_.theta + tiny)
    assert_array_less(gpr.kernel_.theta, bounds[:, 1] + tiny)


@pytest.mark.xfail(
    raises=AssertionError,
    reason="https://github.com/scikit-learn/scikit-learn/issues/31366",
)
@pytest.mark.parametrize("kernel", non_fixed_kernels)
@pytest.mark.parametrize("length_scale", np.logspace(-3, 3, 13))
def test_lml_gradient(kernel, length_scale):
    # Clone the kernel object prior to mutating it to avoid any side effects between
    # GP tests:
    kernel = clone(kernel)
    length_scale_param_name = next(
        name for name in kernel.get_params() if name.endswith("length_scale")
    )
    kernel.set_params(**{length_scale_param_name: length_scale})

    # Compare analytic and numeric gradient of log marginal likelihood.
    gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y)
    _, lml_gradient = gpr.log_marginal_likelihood(kernel.theta, eval_gradient=True)
    epsilon = 1e-9
    lml_gradient_approx = approx_fprime(
        kernel.theta.copy(),
        lambda theta: gpr.log_marginal_likelihood(theta, False),
        epsilon=epsilon,
    )
    assert_allclose(lml_gradient, lml_gradient_approx, rtol=1e-4, atol=epsilon * 100)


@pytest.mark.parametrize("kernel", kernels)
def test_prior(kernel):
    # Test that GP prior has mean 0 and identical variances.
    gpr = GaussianProcessRegressor(kernel=kernel)

    y_mean, y_cov = gpr.predict(X, return_cov=True)

    assert_almost_equal(y_mean, 0, 5)
    if len(gpr.kernel.theta) > 1: