Skip to content

Prevent division by zero in GPR when y_train is constant #18388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
9 changes: 7 additions & 2 deletions sklearn/gaussian_process/_gpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,15 @@ def fit(self, X, y):
if self.normalize_y:
self._y_train_mean = np.mean(y, axis=0)
self._y_train_std = np.std(y, axis=0)

# Assign a standard deviation of one to constant
# targets for avoiding division by zero errors
if np.iterable(self._y_train_std):
self._y_train_std[self._y_train_std == 0] = 1
else:
self._y_train_std = (
self._y_train_std if self._y_train_std != 0 else 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please use as done _handle_zeros_in_scale in #19361 instead?

# Remove mean and make unit variance
y = (y - self._y_train_mean) / self._y_train_std

else:
self._y_train_mean = np.zeros(1)
self._y_train_std = 1
Expand Down
14 changes: 14 additions & 0 deletions sklearn/gaussian_process/tests/test_gpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,3 +536,17 @@ def test_bound_check_fixed_hyperparameter():
periodicity_bounds="fixed") # seasonal component
kernel = k1 + k2
GaussianProcessRegressor(kernel=kernel).fit(X, y)


@pytest.mark.parametrize('kernel', kernels)
def test_constant_target(kernel):
# Test for constant target(s), the private _y_train_std attribute has
# a standard deviation of 1 instead of 0
gpr = GaussianProcessRegressor(kernel=kernel, normalize_y=True)
# create a constant targets of 2
y = np.full((1, X.shape[0]), 2).ravel()
expected_std = np.full((1, X.shape[0]), 1).ravel()
gpr.fit(X, y)
_y_train_std = gpr._y_train_std

assert_array_equal(_y_train_std, expected_std)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please expand the test and call predict on the fitted model as done in #19361 and give credit to @sobkevich in the changelog.