[go: up one dir, main page]

Skip to content

Commit

Permalink
deprecate Xred and W in inverse_transforms
Browse files Browse the repository at this point in the history
  • Loading branch information
adrinjalali committed Jun 8, 2023
1 parent 253e1af commit addf76e
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 6 deletions.
25 changes: 22 additions & 3 deletions sklearn/cluster/_feature_agglomeration.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# Author: V. Michel, A. Gramfort
# License: BSD 3 clause

import warnings
import numpy as np

from ..base import TransformerMixin
Expand Down Expand Up @@ -54,22 +55,40 @@ def transform(self, X):
nX = np.array(nX).T
return nX

def inverse_transform(self, Xred):
def inverse_transform(self, Xt=None, Xred=None):
"""
Inverse the transformation and return a vector of size `n_features`.
Parameters
----------
Xred : array-like of shape (n_samples, n_clusters) or (n_clusters,)
Xt : array-like of shape (n_samples, n_clusters) or (n_clusters,)
The values to be assigned to each cluster of samples.
Xred : deprecated
Use `Xt` instead.
.. deprecated:: 1.3
Returns
-------
X : ndarray of shape (n_samples, n_features) or (n_features,)
A vector of size `n_samples` with the values of `Xred` assigned to
each of the cluster of samples.
"""
if Xt is None and Xred is None:
raise TypeError("Missing required positional argument: Xt")

if Xred is not None and Xt is not None:
raise ValueError("Please provide only `Xt`, and not `Xred`.")

if Xred is not None:
warnings.warn(
"Input argument `Xred` renamed to `Xt` and will be removed in v1.5.",
FutureWarning,
)
Xt = Xred

check_is_fitted(self)

unil, inverse = np.unique(self.labels_, return_inverse=True)
return Xred[..., inverse]
return Xt[..., inverse]
32 changes: 32 additions & 0 deletions sklearn/cluster/tests/test_feature_agglomeration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
Tests for sklearn.cluster._feature_agglomeration
"""
# Authors: Sergul Aydore 2017
import warnings
import numpy as np

from numpy.testing import assert_array_equal
import pytest
from sklearn.cluster import FeatureAgglomeration
from sklearn.utils._testing import assert_array_almost_equal
from sklearn.datasets import make_blobs
Expand Down Expand Up @@ -53,3 +55,33 @@ def test_feature_agglomeration_feature_names_out():
assert_array_equal(
[f"featureagglomeration{i}" for i in range(n_clusters)], names_out
)


def test_inverse_transform_Xred_deprecation():
X = np.array([0, 0, 1]).reshape(1, 3) # (n_samples, n_features)

est = FeatureAgglomeration(n_clusters=1, pooling_func=np.mean)
est.fit(X)
Xt = est.transform(X)

with pytest.raises(TypeError, match="Missing required positional argument"):
est.inverse_transform()

with pytest.raises(ValueError, match="Please provide only"):
est.inverse_transform(Xt=Xt, Xred=Xt)

with warnings.catch_warnings(record=True) as w:
est.inverse_transform(Xt)

assert len(w) == 0

# This try / catch is to make sure passing -Werror::FutureWarning doesn't
# make this test to raise / fail.
try:
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("ignore")
est.inverse_transform(Xred=Xt)

assert len(w) == 1
except Exception:
pass
24 changes: 21 additions & 3 deletions sklearn/decomposition/_nmf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1245,23 +1245,41 @@ def fit(self, X, y=None, **params):
self.fit_transform(X, **params)
return self

def inverse_transform(self, W):
def inverse_transform(self, Xt=None, W=None):
"""Transform data back to its original space.
.. versionadded:: 0.18
Parameters
----------
W : {ndarray, sparse matrix} of shape (n_samples, n_components)
Xt : {ndarray, sparse matrix} of shape (n_samples, n_components)
Transformed data matrix.
W : deprecated
Use `Xt` instead.
.. deprecated:: 1.3
Returns
-------
X : {ndarray, sparse matrix} of shape (n_samples, n_features)
Returns a data matrix of the original shape.
"""
if Xt is None and W is None:
raise TypeError("Missing required positional argument: Xt")

if W is not None and Xt is not None:
raise ValueError("Please provide only `Xt`, and not `W`.")

if W is not None:
warnings.warn(
"Input argument `W` renamed to `Xt` and will be removed in v1.5.",
FutureWarning,
)
Xt = W

check_is_fitted(self)
return W @ self.components_
return Xt @ self.components_

@property
def _n_features_out(self):
Expand Down
35 changes: 35 additions & 0 deletions sklearn/decomposition/tests/test_nmf.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import re
import sys
from io import StringIO
import warnings

import numpy as np
import scipy.sparse as sp
Expand Down Expand Up @@ -906,3 +907,37 @@ def test_minibatch_nmf_verbose():
nmf.fit(A)
finally:
sys.stdout = old_stdout


def test_NMF_inverse_transform_W_deprecation():
rng = np.random.mtrand.RandomState(42)
A = np.abs(rng.randn(6, 5))
est = NMF(
n_components=3,
init="random",
random_state=0,
tol=1e-6,
)
Xt = est.fit_transform(A)

with pytest.raises(TypeError, match="Missing required positional argument"):
est.inverse_transform()

with pytest.raises(ValueError, match="Please provide only"):
est.inverse_transform(Xt=Xt, W=Xt)

with warnings.catch_warnings(record=True) as w:
est.inverse_transform(Xt)

assert len(w) == 0

# This try / catch is to make sure passing -Werror::FutureWarning doesn't
# make this test to raise / fail.
try:
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("ignore")
est.inverse_transform(W=Xt)

assert len(w) == 1
except Exception:
pass

0 comments on commit addf76e

Please sign in to comment.