Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bb36379

Browse files
committed
FIX always expose best_loss_, validation_scores_, and best_validation_score
1 parent 5af75b9 commit bb36379

File tree

3 files changed

+62
-7
lines changed

3 files changed

+62
-7
lines changed

doc/whats_new/v1.2.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,17 @@ Changelog
496496
:class:`neighbors.RadiusNeighborsTransformer`.
497497
:pr:`24075` by :user:`Valentin Laurent <Valentin-Laurent>`.
498498

499+
:mod:`sklearn.neural_network`
500+
.............................
501+
502+
- |Fix| :class:`neural_network.MLPClassifier` and
503+
:class:`neural_network.MLPRegressor` always exposes the parameters `best_loss_`,
504+
`validation_scores_`, and `best_validation_score_`. `best_loss_` is set to
505+
`None` when `early_stopping=True`, while `validation_scores_` and
506+
`best_validation_score_` are set to `None` when `early_stopping=False`.
507+
`validation_scores_` also changed from a Python list to a Numpy array.
508+
:pr:`xxx` by :user:`Guillaume Lemaitre <glemaitre>`.
509+
499510
:mod:`sklearn.pipeline`
500511
.......................
501512

sklearn/neural_network/_multilayer_perceptron.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,11 @@ def _initialize(self, y, layer_units, dtype):
391391
if self.early_stopping:
392392
self.validation_scores_ = []
393393
self.best_validation_score_ = -np.inf
394+
self.best_loss_ = None
394395
else:
395396
self.best_loss_ = np.inf
397+
self.validation_scores_ = None
398+
self.best_validation_score_ = None
396399

397400
def _init_coef(self, fan_in, fan_out, dtype):
398401
# Use the initialization method recommended by
@@ -686,6 +689,7 @@ def _fit_stochastic(
686689
# restore best weights
687690
self.coefs_ = self._best_coefs
688691
self.intercepts_ = self._best_intercepts
692+
self.validation_scores_ = np.array(self.validation_scores_)
689693

690694
def _update_no_improvement_count(self, early_stopping, X_val, y_val):
691695
if early_stopping:
@@ -919,12 +923,24 @@ class MLPClassifier(ClassifierMixin, BaseMultilayerPerceptron):
919923
loss_ : float
920924
The current loss computed with the loss function.
921925
922-
best_loss_ : float
926+
best_loss_ : float or None
923927
The minimum loss reached by the solver throughout fitting.
928+
If `early_stopping=True`, this attribute is set ot `None`. Refer to
929+
the fitted attribute `best_validation_score_` instead.
924930
925931
loss_curve_ : list of shape (`n_iter_`,)
926932
The ith element in the list represents the loss at the ith iteration.
927933
934+
validation_scores_ : ndarray of shape (n_iter_,) or None
935+
The score at each iteration on a held-out validation set. The score
936+
reported is the accuracy score. Only available if `early_stopping=True`,
937+
otherwise the attribute is set to `None`.
938+
939+
best_validation_score_ : float or None
940+
The best validation score (i.e. accuracy score) that triggered the
941+
early stopping. Only available if `early_stopping=True`, otherwise the
942+
attribute is set to `None`.
943+
928944
t_ : int
929945
The number of training samples seen by the solver during fitting.
930946
@@ -1388,11 +1404,23 @@ class MLPRegressor(RegressorMixin, BaseMultilayerPerceptron):
13881404
13891405
best_loss_ : float
13901406
The minimum loss reached by the solver throughout fitting.
1407+
If `early_stopping=True`, this attribute is set ot `None`. Refer to
1408+
the fitted attribute `best_validation_score_` instead.
13911409
13921410
loss_curve_ : list of shape (`n_iter_`,)
13931411
Loss value evaluated at the end of each training step.
13941412
The ith element in the list represents the loss at the ith iteration.
13951413
1414+
validation_scores_ : ndarray of shape (n_iter_,) or None
1415+
The score at each iteration on a held-out validation set. The score
1416+
reported is the R2 score. Only available if `early_stopping=True`,
1417+
otherwise the attribute is set to `None`.
1418+
1419+
best_validation_score_ : float or None
1420+
The best validation score (i.e. R2 score) that triggered the
1421+
early stopping. Only available if `early_stopping=True`, otherwise the
1422+
attribute is set to `None`.
1423+
13961424
t_ : int
13971425
The number of training samples seen by the solver during fitting.
13981426
Mathematically equals `n_iters * X.shape[0]`, it means

sklearn/neural_network/tests/test_mlp.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -668,20 +668,36 @@ def test_verbose_sgd():
668668
assert "Iteration" in output.getvalue()
669669

670670

671-
def test_early_stopping():
671+
@pytest.mark.parametrize("MLPEstimator", [MLPClassifier, MLPRegressor])
672+
def test_early_stopping(MLPEstimator):
672673
X = X_digits_binary[:100]
673674
y = y_digits_binary[:100]
674675
tol = 0.2
675-
clf = MLPClassifier(tol=tol, max_iter=3000, solver="sgd", early_stopping=True)
676-
clf.fit(X, y)
677-
assert clf.max_iter > clf.n_iter_
676+
mlp_estimator = MLPEstimator(
677+
tol=tol, max_iter=3000, solver="sgd", early_stopping=True
678+
)
679+
mlp_estimator.fit(X, y)
680+
assert mlp_estimator.max_iter > mlp_estimator.n_iter_
678681

679-
valid_scores = clf.validation_scores_
680-
best_valid_score = clf.best_validation_score_
682+
assert mlp_estimator.best_loss_ is None
683+
assert isinstance(mlp_estimator.validation_scores_, np.ndarray)
684+
685+
valid_scores = mlp_estimator.validation_scores_
686+
best_valid_score = mlp_estimator.best_validation_score_
681687
assert max(valid_scores) == best_valid_score
682688
assert best_valid_score + tol > valid_scores[-2]
683689
assert best_valid_score + tol > valid_scores[-1]
684690

691+
# check that the attributes `validation_scores_` and `best_validation_score_`
692+
# are set to None when `early_stopping=False`
693+
mlp_estimator = MLPEstimator(
694+
tol=tol, max_iter=3000, solver="sgd", early_stopping=False
695+
)
696+
mlp_estimator.fit(X, y)
697+
assert mlp_estimator.validation_scores_ is None
698+
assert mlp_estimator.best_validation_score_ is None
699+
assert mlp_estimator.best_loss_ is not None
700+
685701

686702
def test_adaptive_learning_rate():
687703
X = [[3, 2], [1, 6]]

0 commit comments

Comments
 (0)