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

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions doc/whats_new/v0.21.rst
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,15 @@ Support for Python 3.4 and below has been officially dropped.
affects all ensemble methods using decision trees.
:issue:`12344` by :user:`Adrin Jalali <adrinjalali>`.

:mod:`sklearn.mixture`
......................

- |Fix| Fixed a bug in :class:`mixture.BaseMixture` and therefore on estimators
based on it, i.e. :class:`mixture.GaussianMixture` and
:class:`mixture.BayesianGaussianMixture`, where ``fit_predict`` and
``fit.predict`` were not equivalent. :issue:`13142` by
:user:`Jérémie du Boisberranger <jeremiedbb>`.


Multiple modules
................
Expand Down
10 changes: 5 additions & 5 deletions sklearn/mixture/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,6 @@ def fit_predict(self, X, y=None):
best_params = self._get_parameters()
best_n_iter = n_iter

# Always do a final e-step to guarantee that the labels returned by
# fit_predict(X) are always consistent with fit(X).predict(X)
# for any value of max_iter and tol (and any random_state).
_, log_resp = self._e_step(X)

if not self.converged_:
warnings.warn('Initialization %d did not converge. '
'Try different init parameters, '
Expand All @@ -273,6 +268,11 @@ def fit_predict(self, X, y=None):
self.n_iter_ = best_n_iter
self.lower_bound_ = max_lower_bound

# Always do a final e-step to guarantee that the labels returned by
# fit_predict(X) are always consistent with fit(X).predict(X)
# for any value of max_iter and tol (and any random_state).
_, log_resp = self._e_step(X)

return log_resp.argmax(axis=1)

def _e_step(self, X):
Expand Down
9 changes: 9 additions & 0 deletions sklearn/mixture/tests/test_bayesian_mixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,15 @@ def test_bayesian_mixture_fit_predict(seed, max_iter, tol):
assert_array_equal(Y_pred1, Y_pred2)


def test_bayesian_mixture_fit_predict_n_init():
# Check that fit_predict is equivalent to fit.predict, when n_init > 1
X = np.random.RandomState(0).randn(1000, 5)
gm = BayesianGaussianMixture(n_components=5, n_init=10, random_state=0)
y_pred1 = gm.fit_predict(X)
y_pred2 = gm.predict(X)
assert_array_equal(y_pred1, y_pred2)


def test_bayesian_mixture_predict_predict_proba():
# this is the same test as test_gaussian_mixture_predict_predict_proba()
rng = np.random.RandomState(0)
Expand Down
9 changes: 9 additions & 0 deletions sklearn/mixture/tests/test_gaussian_mixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,15 @@ def test_gaussian_mixture_fit_predict(seed, max_iter, tol):
assert_greater(adjusted_rand_score(Y, Y_pred2), .95)


def test_gaussian_mixture_fit_predict_n_init():
# Check that fit_predict is equivalent to fit.predict, when n_init > 1
X = np.random.RandomState(0).randn(1000, 5)
gm = GaussianMixture(n_components=5, n_init=5, random_state=0)
y_pred1 = gm.fit_predict(X)
y_pred2 = gm.predict(X)
assert_array_equal(y_pred1, y_pred2)


def test_gaussian_mixture_fit():
# recover the ground truth
rng = np.random.RandomState(0)
Expand Down