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

Skip to content

Adding explained variances to sparse pca #11527

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

Conversation

jrmlhermitte
Copy link

Adding explained variances for sparse PCA during a sprint.

I am unfamiliar with Sparse PCA. Based on conversation with @amueller

Reference Issues/PRs

Issue #11512

The variance computed from sparse PCA should match regular PCA. Printed variances here should match.

What does this implement/fix? Explain your changes.

Any other comments?

@amueller
Copy link
Member

thanks :) You wanted someone else to pick this up now, right?

@jrmlhermitte
Copy link
Author

The variances don't match. It's worth reading in more detail. See the gist I've linked above for comparing
variances. Can someone else help?

variances:

Non sparse variance:[18.840183  11.071763   6.3046103  3.954582   2.8560433  2.4977083]
Sparse variance:[2.506263e-03 0.000000e+00          nan 1.401298e-45 0.000000e+00
          nan]

thanks!

@jrmlhermitte
Copy link
Author

ill give it another try. the variances should be easy...

@jrmlhermitte jrmlhermitte force-pushed the sparse_pca_variance branch from 63ea0b0 to 7c36760 Compare July 16, 2018 19:12
@jrmlhermitte
Copy link
Author

Added:

  • added a test to compare the resultant variance from normal PCA with sparse PCA (for orthogonal axes)
  • added def get_explained_variance(self, components, X): member of SparsePCA which computes the variance from principle components not assumed to be orthogonal
  • added a variance=False flat to fit for SparsePCA and SparsePCAMiniBatch. If True, will compute the variance and save to self.explained_variance_

Note:

  • Actual test on non-orthogonal axes was not done. It could be useful to compare this with a result computed with another function.

# subtract the previous projections
for j in range(i):
vecp = components[j].copy()
vec -= np.dot(unit_vecs[j], vec)*unit_vecs[j]
Copy link
Author

Choose a reason for hiding this comment

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

note, we dot the vec with the vec from the previous iteration (the projections should only get smaller and smaller)

@GaelVaroquaux
Copy link
Member

Sparse PCA actually has a horrible bug.

#11585 fixes it. I don't know how it will interact with this PR.

@jrmlhermitte
Copy link
Author

should be okay i think. The function computes Y from X - X.mean(axis=0) using the components, and computes the variance from this, corrected for non-orthogonal vectors supplied by components.

The test currently doesn't fit using sparse PCA. It takes in components computed from regular PCA and verifies that the variances match.

So long as the components are right, then this will be okay.
@amueller does that sound correct?

@@ -98,7 +98,7 @@ def __init__(self, n_components=None, alpha=1, ridge_alpha=0.01,
self.verbose = verbose
self.random_state = random_state

def fit(self, X, y=None):
def fit(self, X, y=None, variance=False):
Copy link
Member

@jeremiedbb jeremiedbb Jul 18, 2018

Choose a reason for hiding this comment

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

The fit method should not have any other param than X and y (and sometimes sample_weight). You have to make it a class attribute I guess.

edit: my bad, it can. However not in this case. It can only when the parameter's value depends on the data, meaning it can't be set before fitting. Here it should be a class attribute.

Copy link
Author

Choose a reason for hiding this comment

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

ok sounds good, moved to __init__

@@ -109,6 +109,9 @@ def fit(self, X, y=None):

y : Ignored

variance : bool, optional
If true, compute the explained variance

Copy link
Member

Choose a reason for hiding this comment

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

remove, see previous

Copy link
Author

Choose a reason for hiding this comment

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

moved this over to __init__ (for both)

@@ -135,6 +138,9 @@ def fit(self, X, y=None):
)
self.components_ = Vt.T
self.error_ = E
if variance:
self.explained_variance_ = \
self.get_explained_variance(self.components_, X)
Copy link
Member

Choose a reason for hiding this comment

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

if self.variance

I would name it with_explained_variance, although it's a bit long. But if it's a class attribute it should have a more informative name

Copy link
Author

Choose a reason for hiding this comment

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

I renamed to self.explained_variance_

'''
# requires the mean to be subtracted
X = X - np.mean(X, axis=0)
# the number of samples
Copy link
Member

Choose a reason for hiding this comment

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

this might not be necessary after #11585 is merged.

Copy link
Author

Choose a reason for hiding this comment

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

Sounds good. I'll leave as is for now and rebase on that PR when merged (looks more important than this one right?)

Copy link
Member

Choose a reason for hiding this comment

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

It will probably be merged berfore. You can adapt you PR when it's done. Sounds good.

@@ -185,6 +191,63 @@ def transform(self, X, ridge_alpha='deprecated'):
U /= s
return U

def get_explained_variance(self, components, X):
'''
Copy link
Member

Choose a reason for hiding this comment

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

Do we want this function to be used from outside ?
otherwise I think it should be private: _get_explained_variance

still in the optics to be a private function, you don't need to pass components to the function. You can directly access self.components_ inside the function.

Copy link
Author

Choose a reason for hiding this comment

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

renamed thanks!

n_components = components.shape[0]
unit_vecs = components.copy()
unit_vecs = unit_vecs/np.linalg.norm(components, axis=1)[:, np.newaxis]

Copy link
Member

Choose a reason for hiding this comment

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

if #11585 is merged, components will be already normalized.
However there will be a deprecation cycle for that, so for a few releases you'll have to check if the attribute introduced in that PR, normalize, is false before computing it

Copy link
Author

Choose a reason for hiding this comment

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

ok, i think id rather wait and rebase, in case anything else changes, can you ping when done? (or feel free to take over if i take too long to respond!)

Copy link
Author

Choose a reason for hiding this comment

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

I checked for normalize_components and if False, subtract mean and warn. Would that work?
thanks!

# we subtract the variance from components in the direction of previous
# axes
# the projection corrected vectors
proj_corrected_vecs = np.zeros_like(components)
Copy link
Member

Choose a reason for hiding this comment

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

too much verbose. I think you can remove first and last lines

Copy link
Author

Choose a reason for hiding this comment

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

removed verbosity to all lines mentioned

# just the diagonal of the covariance of X projected to the new
# (component subtracted) basis
# Y in the new basis
Y = np.tensordot(X, proj_corrected_vecs.T, axes=(1, 0))
Copy link
Member

Choose a reason for hiding this comment

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

same, too much verbose

@@ -265,7 +328,7 @@ def __init__(self, n_components=None, alpha=1, ridge_alpha=0.01,
self.batch_size = batch_size
self.shuffle = shuffle

def fit(self, X, y=None):
def fit(self, X, y=None, variance=False):
Copy link
Member

Choose a reason for hiding this comment

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

same comments as in SparsePCA

@jeremiedbb
Copy link
Member

You also have to add explained_variance_ in the class docstring in attributes, and document it.

@@ -77,6 +77,12 @@ class SparsePCA(BaseEstimator, TransformerMixin):
n_iter_ : int
Number of iterations run.

variance : bool, optional
If true, compute the explained variance

Copy link
Member

Choose a reason for hiding this comment

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

sorry for the miss leading. variance should be a parameter (I tend to use the word attribute for both as in C++...)

@@ -135,6 +143,9 @@ def fit(self, X, y=None):
)
self.components_ = Vt.T
self.error_ = E
if self.variance:
self.explained_variance_ = \
self._get_explained_variance(self.components_, X)
Copy link
Member

Choose a reason for hiding this comment

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

self._get_explained_variance(X)

if self.variance:
self.explained_variance_ = \
self._get_explained_variance(self.components_, X)

Copy link
Member

Choose a reason for hiding this comment

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

self._get_explained_variance(X)

explained_variance = pca.explained_variance_
spca_lars.components_ = components
explained_variance_sparse = spca_lars.explained_variance_

Copy link
Member

Choose a reason for hiding this comment

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

hum, I misunderstood what you're doing.
You just want to assert that your function ̀_get_explained_variance returns the same result as in PCA if given same X and same components, right ?
Maybe you can add a comment before line 96 explaining that.

And I guess you have to do explained_variance_sparse = spca_lars._get_explained_variance_(Y)

Is it possible to make a test checking that the explained_variance_ computed with the components fitted by SparsePCA are correct ? maybe something like comparing explained_variance_ between PCA and SparsePCA with sparsity=0 ?

Copy link
Author

Choose a reason for hiding this comment

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

oops yes, it should be a function call. I also changed Y to X. i copied and pasted form a previous test. it could have been Y because maybe it was copied from another test that compared two feature vectors?

@jeremiedbb
Copy link
Member

Also, you forgot to add variance in the init of MiniBatchSparsePCA. It should be in the super statement.

@jeremiedbb
Copy link
Member

lgtm. Now I think we should wait #11585 to be merged.

@@ -135,6 +143,8 @@ def fit(self, X, y=None):
)
self.components_ = Vt.T
self.error_ = E
if self.variance:
self.explained_variance_ = self._get_explained_variance(X)
Copy link
Member

Choose a reason for hiding this comment

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

sorry one more thing. You should add

else:
    self.explained_variance_ = None

otherwise you'd get an attribute error if calling estimator.explained_variance afterwards.

and you can add a test which checks that when variance is False, explained_variance_ is not computed.

Copy link
Author

Choose a reason for hiding this comment

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

added thanks! one random question, i see in your PR, you added to "doc/whats_new/v0.20.rst"
should I be adding the same to a similar file? (and which?)

Copy link
Member

Choose a reason for hiding this comment

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

Yes you'll have to add it in the what's new. But I don't know if your PR will be in the 0.20 release. Let it as is for now and we'll fill the right what's new as soon as we know.

@@ -77,6 +80,9 @@ class SparsePCA(BaseEstimator, TransformerMixin):
n_iter_ : int
Number of iterations run.

explained_variance_ : array, [n_components]
The explained variance versus component

Copy link
Member

Choose a reason for hiding this comment

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

add that it's only computed if variance is set to true

@kimrants
Copy link

When is this expected to be released? :)
Thanks!

@jeremiedbb
Copy link
Member

We are waiting for another PR to be merged first.
Also it's not been reviewed by core devs yet.

So I can't tell but it will probably not be in the 0.20 release.

@jrmlhermitte jrmlhermitte force-pushed the sparse_pca_variance branch from bbd6cc1 to d6ff98c Compare July 21, 2018 14:28
@jrmlhermitte
Copy link
Author

I rebased and force pushed (but kept a local copy of my branch before rebase in case anything went wrong). Let me know what you think thanks!

if not self.normalize_components:
X = X - np.mean(X, axis=0)
warnings.warn("normalize_components=False is a "
"backward-compatible setting that implements a "
Copy link
Member

Choose a reason for hiding this comment

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

I wouldn't raise a warning here. The reason is that if someone calls SparsePCA with normalize_components=False, he will already get a warning in fit. No need for duplicate warning.

Instead, you could comment that this test should be removed in version 0.22.

Copy link
Author

Choose a reason for hiding this comment

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

sounds good! removed

n_components = components.shape[0]
unit_vecs = components.copy()
unit_vecs = unit_vecs/np.linalg.norm(components, axis=1)[:, np.newaxis]

Copy link
Member

Choose a reason for hiding this comment

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

Correct me if I'm wrong but you should also normalize the components here, depending on normalize_components.

Copy link
Author

Choose a reason for hiding this comment

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

no, and this is tricky now. i will elaborate in a comment further below

@@ -105,8 +112,9 @@ class SparsePCA(BaseEstimator, TransformerMixin):
def __init__(self, n_components=None, alpha=1, ridge_alpha=0.01,
max_iter=1000, tol=1e-8, method='lars', n_jobs=1, U_init=None,
V_init=None, verbose=False, random_state=None,
normalize_components=False):
normalize_components=False, variance=False):
Copy link
Member

Choose a reason for hiding this comment

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

I'm wondering if we could make it True by default. Is _get_explained_variance computation intensive ? I mean versus SparsePCA.fit.

Also, I think variance is not enough informative. We could think of a better name. If I recall your first idea was with_variance. I think it's better than this one. Maybe core reviewers will have a better opinion on that.

Copy link
Author

Choose a reason for hiding this comment

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

made to True, I agree it makes sense

----------
X : 2D np.ndarray
The feature vector. Must be shape m x n where m is the number
of samples and n is the dimension of the incoming feature
Copy link
Member

Choose a reason for hiding this comment

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

Here I think the common accepted way is

X : ndarray, shape (n_samples, n_features)

Copy link
Author

Choose a reason for hiding this comment

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

done for all i can find, thanks!

@@ -81,6 +81,9 @@ class SparsePCA(BaseEstimator, TransformerMixin):
backward compatibility. It would be set to ``True`` from 0.22
onwards.

variance : bool, optional
If true, this will compute the explained variance versus component.

Copy link
Member

Choose a reason for hiding this comment

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

Please state the default value
variance : boolean, optional (default=False)

Copy link
Author

Choose a reason for hiding this comment

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

done thanks!

@@ -300,6 +365,9 @@ class MiniBatchSparsePCA(SparsePCA):
backward compatibility. It would be set to ``True`` from 0.22
onwards.

variance : bool, optional
If true, this will compute the explained variance versus component.

Copy link
Member

Choose a reason for hiding this comment

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

default=

@@ -96,6 +99,10 @@ class SparsePCA(BaseEstimator, TransformerMixin):
Per-feature empirical mean, estimated from the training set.
Equal to ``X.mean(axis=0)``.

explained_variance_ : array, [n_components]
The explained variance versus component
Copy link
Member

Choose a reason for hiding this comment

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

array, shape (n_components,)

@@ -312,6 +380,10 @@ class MiniBatchSparsePCA(SparsePCA):
Per-feature empirical mean, estimated from the training set.
Equal to ``X.mean(axis=0)``.

explained_variance_ : array, [n_components]
The explained variance versus component.
Copy link
Member

Choose a reason for hiding this comment

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

array, shape (n_components,)

@jeremiedbb
Copy link
Member

jeremiedbb commented Jul 23, 2018

also it might be a good idea to test that explained_variance is the same whether normalize_components is True or False.

@jeremiedbb
Copy link
Member

tests are failing because now warnings are raised as errors.
you can add
@pytest.mark.filterwarnings('ignore: msg')
where msg is a part of the warning message you want to catch. Here it could be 'normalize_components'

@jrmlhermitte
Copy link
Author

jrmlhermitte commented Jul 24, 2018

Thanks @jeremiedbb for the input. I have made the changes, but I have a few questions:

  • The latest PR now normalizes the components. In normalizing the components, you lose the possibility to retrieve the variance. Is this a convention adopted by regular PCA? It doesn't seem to normalize them by default but I could be wrong. Anyway, this requires that the variance be computed internally before the components are normalized. (i.e. there is an ordering to when the functions should be called) I guess this should be fine since what computes the variance is a private function.
  • The normalize_components flag also does mean subtraction. Seems like PCA just did this by default though so it should do the same. This just requires being careful with writing the test (had to mean subtract the features before computing the variance)

@jeremiedbb
Copy link
Member

In normalizing the components, you lose the possibility to retrieve the variance.

I don't understand what you mean. When you compute the explained variance, you begin with normalizing the components.

It doesn't seem to normalize them by default but I could be wrong.

Actually I think it does. In PCA, the components are computed using svd, which returns a unitary matrix.

Anyway, this requires that the variance be computed internally before the components are normalized.

Indeed, so I think you should call _get_explained_variance right after the component's normalization.

self.n_components = n_components
self._compute_variance = compute_variance
Copy link
Member

Choose a reason for hiding this comment

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

why the underscore ? this is not private.

@jrmlhermitte
Copy link
Author

@jeremiedbb thanks. One way to compute the variance is to extract the diagonal of Y dot Y.T. This matrix is the matrix of components and it cannot be normalized.
in _get_explained_variance, the components are normalized just to subtract the projections from each component. Note that both the unit_vecs (which are normalized components) and the components matrices are used in this calculation (where components has not been normalized yet)

In SVD, I think it doesn't matter because we use the S matrix to compute the variance. Note that we don't have such an equivalent here.

This is explained on p 273 here.
An alternative to this approach is to perform QR decomposition. I could replace this for loop with that. I need to double check and test though later. Would that maybe be cleaner?

@jeremiedbb
Copy link
Member

Thanks for the clarification. I missed that you needed both components and the corresponding unit vectors. So I think it's fine as it is.

I guess this should be fine since what computes the variance is a private function.

Agreed

@jrmlhermitte
Copy link
Author

Great thanks! Do we need to ping anyone else to look at it now?

@@ -361,6 +434,7 @@ def fit(self, X, y=None):
"compatibility mode will be removed in 0.22.",
DeprecationWarning)

self.n_samples = X.shape[0]
Copy link
Member

Choose a reason for hiding this comment

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

Where does that come from ?
you don't seem to use it anywhere.

Copy link
Author

Choose a reason for hiding this comment

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

oops yes this is vestigial code from a previous attempt

@jeremiedbb
Copy link
Member

Sure !
you need to make the tests green first. Reviewers are reluctant when tests are red :)
(my last comment should make them green)

@jrmlhermitte
Copy link
Author

ok thanks! submitted change, waiting..

@jeremiedbb
Copy link
Member

Looks good !

@GaelVaroquaux @agramfort @glemaitre you might be interested in reviewing this, since you were recently involved in SparsePCA :)
(if not could you tag this as needs review ?)

@@ -81,9 +81,12 @@ class SparsePCA(BaseEstimator, TransformerMixin):
backward compatibility. It would be set to ``True`` from 0.22
onwards.

compute_variance : bool, optional (default=True)
If true, this will compute the explained variance versus component.
Copy link
Member

Choose a reason for hiding this comment

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

versus -> per

Copy link
Author

Choose a reason for hiding this comment

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

thanks, changed

Per-feature empirical mean, estimated from the training set.
Equal to ``X.mean(axis=0)``.

explained_variance_ : array, shape (n_components, )
The explained variance versus component
Copy link
Member

Choose a reason for hiding this comment

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

Versus -> per.
End the line with a full stop, please

Copy link
Author

Choose a reason for hiding this comment

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

you mean "."? Sorry not familiar with the word, thanks!

@@ -231,6 +245,57 @@ def transform(self, X, ridge_alpha='deprecated'):

return U

def _get_explained_variance(self, X):
'''
Get the explained variance from the principal components of the
Copy link
Member

Choose a reason for hiding this comment

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

Descent please

Copy link
Author

Choose a reason for hiding this comment

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

ah yes, line too long, following doctstring convention of makinga new line with extra description, thanks

@@ -231,6 +245,57 @@ def transform(self, X, ridge_alpha='deprecated'):

return U

def _get_explained_variance(self, X):
Copy link
Member

Choose a reason for hiding this comment

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

This seems to be a generalised approach? Perhaps pull this out into a module-level function taking X and components

Copy link
Author

Choose a reason for hiding this comment

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

yes, it should work for PCA as well (although not tested)
made a module, for discussion

n_samples = X.shape[0]
n_components = components.shape[0]
unit_vecs = components.copy()
components_norm = \
Copy link
Member

Choose a reason for hiding this comment

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

We tend to avoid this kind of line continuation and prefer breaking after a comma within parentheses

Copy link
Author

Choose a reason for hiding this comment

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

removed these awkward indents, thanks!

@pytest.mark.parametrize("norm_comp", [False, True])
def test_fit_transform_variance(norm_comp):
'''
This function asserts that the variance computed by SparsePCA is the
Copy link
Member

Choose a reason for hiding this comment

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

We use comments rather than docstrings in tests (although mostly for historical reasons)

Copy link
Author

Choose a reason for hiding this comment

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

changed to comments, thanks!

@@ -300,18 +365,25 @@ class MiniBatchSparsePCA(SparsePCA):
backward compatibility. It would be set to ``True`` from 0.22
onwards.

compute_variance : bool, optional (default=True)
Copy link
Member

Choose a reason for hiding this comment

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

Do we need this to be a parameter? How costly is it relative to the sparse PCA?

Copy link
Author

Choose a reason for hiding this comment

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

i don't think it is, it's just vectorized products. it could be costly, when maybe running this in a loop though. i have removed it for now. we can perhaps add this in in a future issue if someone is discontent?

@jrmlhermitte
Copy link
Author

@jeremiedbb what about the release notes, should I add some now?

@jeremiedbb
Copy link
Member

Well there is no what's new for the 0.21 yet and I'm really not sure it will be reviewed (and approved) before the release.

You might have to let it as is until the release and then ping some guys for the review once they have a bit more time...

@jrmlhermitte
Copy link
Author

ok sounds good thanks!

@jrmlhermitte
Copy link
Author

rebased. just checking in

Copy link
Member

@jnothman jnothman left a comment

Choose a reason for hiding this comment

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

Not a full review

explained_variance = pca.explained_variance_

# force the components in spca_lars to be the same as in pca
spca_lars.components_ = pca.components_
Copy link
Contributor

Choose a reason for hiding this comment

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

How about a string version of that test that first applies QR-decomposition on spca_lars.components_ and then computes and compares the explained variances against PCA's output?

Copy link
Author

@jrmlhermitte jrmlhermitte Mar 2, 2019

Choose a reason for hiding this comment

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

I assume by that you mean something like this:

# Force matrix to be orthogonal. sparse PCA must then be the same as PCA.
   X_orthogonal, R = np.linalg.qr(X)
   spca_lars.fit(X_orthogonal)
   pca.fit(X_orthogonal)

   explained_variance = pca.explained_variance_
   explained_variance_sparse = _get_explained_variance(
      X_orthogonal, spca_lars.components_)

I would have assumed this to work but it does not. I will not add it. I don't have time to update it (I'm working in a completely different field). I suggest to either:

  • make correction here
  • add commit to this PR
  • we can close it and someone else continue it
  • make an issue to add this test

What do you think? I apologize for my latency. It is very hard for me to step into the open source world right now.
If i have free time I'll try to review and think about this later.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep, this goes into the direction I had in mind. Would be a nice option for a more careful test if feasible.

@jrmlhermitte jrmlhermitte force-pushed the sparse_pca_variance branch from 8af1aaf to 583e910 Compare March 2, 2019 18:28

References
----------
[1] Journal of Computational and Graphical Statistics, Volume 15, Number 2,
Copy link
Member

Choose a reason for hiding this comment

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

I think the rst syntax is .. [1]

@jrmlhermitte jrmlhermitte force-pushed the sparse_pca_variance branch from 8c81f47 to 84d7206 Compare March 2, 2019 20:03
@jrmlhermitte jrmlhermitte force-pushed the sparse_pca_variance branch from 84d7206 to 0d80178 Compare June 19, 2019 22:00
@jrmlhermitte
Copy link
Author

@adrinjalali I took a look and it looks like it needed to be rebased. looks like some things changed along the way.
Can we finish this or close this? This is growing stale. thanks

@glemaitre glemaitre self-requested a review June 20, 2019 14:23
@cmarmo
Copy link
Contributor

cmarmo commented Jan 14, 2020

Can we finish this or close this? This is growing stale. thanks

@jrmlhermitte , it's up to you.... :) ... but it seems to me that with already one approval it is worth to finish it. Would you try to resolve conflicts and sync to master?
If you really feel that you haven't the time to work on it, we can put it in the sprint list: branching from your PR as your work will not get lost.

@cmarmo cmarmo added the Superseded PR has been replace by a newer PR label Jul 10, 2020
@ogrisel
Copy link
Member

ogrisel commented Aug 11, 2020

This was taken over by #16255 which was closed because the concept of component-wise explained variance is not well defined when the components are not orthogonal.

@ogrisel ogrisel closed this Aug 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
module:decomposition Superseded PR has been replace by a newer PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants