Skip to content

[MRG] Uniformize num_dims and add it for LMNN #193

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

Merged
merged 14 commits into from
Jun 7, 2019

Conversation

wdevazelhes
Copy link
Member

@wdevazelhes wdevazelhes commented Apr 18, 2019

This solves #167 partially (only gives a num_dims argument to LMNN and ensures that the check is done uniformly between the algorithms)

@wdevazelhes
Copy link
Member Author

wdevazelhes commented Apr 18, 2019

Note: For LMNN, if we have shogun, it will do a pca if asked so, but I couldn't find how the dimension of pca is chosen, so for now I didn't change anything... Also, maybe we'll not have to bother as soon as we have solved #124, because maybe we will chose that the 'pca' option triggers a scikit-learn PCA in both shogun/not shogun cases...

@bellet
Copy link
Member

bellet commented Apr 18, 2019

Have you checked what is the pca option of Shogun for? It could be simply a preprocessing applied to the dataset, not an initialization of the algorithm. In which case we will set this option to false when solving #125

@wdevazelhes
Copy link
Member Author

Have you checked what is the pca option of Shogun for? It could be simply a preprocessing applied to the dataset, not an initialization of the algorithm. In which case we will set this option to false when solving #125

Yes, according to this page: http://shogun.ml/notebook/latest/LMNN.html, (in cell 5), they say PCA is used to find the initial matrix

@bellet
Copy link
Member

bellet commented Apr 18, 2019

Have you checked what is the pca option of Shogun for? It could be simply a preprocessing applied to the dataset, not an initialization of the algorithm. In which case we will set this option to false when solving #125

Yes, according to this page: http://shogun.ml/notebook/latest/LMNN.html, (in cell 5), they say PCA is used to find the initial matrix

Indeed. Looking at this, I do not think they reduce the dimension anyway:
https://shogun-list.shogun-toolbox.narkive.com/n6B3o0Mf/shogun-lmnn-pca-error
But I agree it will be safer to perform the PCA initialization ourselves and pass it to Shogun's train's method

"""Checks that num_dims is less that n_features and deal with the None
case"""
if num_dims is None:
dim = n_features
Copy link
Contributor

Choose a reason for hiding this comment

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

As a style nitpick, I prefer early-return for cases like this:

if num_dims is None:
  return n_features
if 0 < num_dims <= n_features:
  return num_dims
raise ValueError(...)

Copy link
Member Author

@wdevazelhes wdevazelhes Apr 19, 2019

Choose a reason for hiding this comment

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

That's better I agree, done



def _check_num_dims(n_features, num_dims):
"""Checks that num_dims is less that n_features and deal with the None
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: "less than"

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, done

dim = n_features
else:
if not 0 < num_dims <= n_features:
raise ValueError('Invalid num_dims, must be in [1, %d]' % n_features)
Copy link
Contributor

Choose a reason for hiding this comment

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

Some existing code would only warn if num_dims > n_features. I think it's probably better to error out here, but we should keep in mind that this is technically a back-compat break.

Copy link
Member Author

Choose a reason for hiding this comment

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

That's true, maybe adding it in the changelog is enough ? Something like "for all the algorithms that have a parameter num_dims, it will now be checked to be between 1 and n_features, with n_features the number of dimensions of the input space" ?

Copy link
Member Author

Choose a reason for hiding this comment

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

I just added it to the release draft

@wdevazelhes
Copy link
Member Author

Also, I kept the name num_dims for now, but in scikit-learn's NCA we went for n_components, which respects more scikit-learn's conventions. It would be good to change the name wouldn't it ? If so I'll add deprecation warning for it

@bellet
Copy link
Member

bellet commented Apr 23, 2019

I agree that n_components would be more intuitive, +1 for changing this before the 0.5.0 release with deprecation warning

@wdevazelhes
Copy link
Member Author

wdevazelhes commented May 3, 2019

I investigated the travis fail and there seems to be an issue with some shapes mismatch for LMNN when doing dimensionality reduction. There seems to be a problem with the gradient: Looking into this line the gradient seems to be of the shape of an outer product of Xs (when it should be of the shape of L):

https://github.com/metric-learn/metric-learn/blob/d4badc8adc0a8ce6689dd9a95e89181efaf5ee24/metric_learn/lmnn.py#L196

Looking at the PR on LMNN in scikit-learn, there might be a dot product with L missing:
https://github.com/scikit-learn/scikit-learn/pull/8602/files#diff2914dd42441ed8b594e69b2fe04d23f5R762

I'll look into it

William de Vazelhes added 6 commits May 29, 2019 16:45
if np.sign(res_1[0,0]) != np.sign(res_2[0,0]):
res_2 *= -1
assert_array_almost_equal(res_1, res_2)
assert_array_almost_equal(abs(res_1), abs(res_2))
Copy link
Member Author

Choose a reason for hiding this comment

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

The tests were failing because of a sign error, I think it's because of the eigenvalue decomposition in LFDA, that can lead to different signs in the output. I did this modif because I thought that any sign switching of any column still keeps the result valid am I right (any symmetry wrt some of the axis are still valid right?) (Not just a global sign switching as before)? But maybe I should rather try to change the code to make LFDA deterministic ? What do you think @perimosocordiae @bellet ?

Copy link
Member Author

Choose a reason for hiding this comment

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

I just raised an issue for that (#211), I guess maybe let's do like that for now and later fix this non deterministic problem ?

Copy link
Contributor

Choose a reason for hiding this comment

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

The sign switch is expected, as each eigenvector may be negated independently of the others. The result is valid in the sense that the underlying optimization problem is still solved, and distances in the transformed space are equivalent. Individual points in the transformed space won't always be the same, though.

I don't think it's worth trying to enforce a deterministic result, but I could probably be persuaded otherwise.

Copy link
Member

Choose a reason for hiding this comment

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

Let's discuss it in the issue you opened

@wdevazelhes
Copy link
Member Author

If you agree with my last modifs (see comment #193 (review)), we should be ready to merge

@wdevazelhes wdevazelhes requested a review from bellet June 5, 2019 13:38
@wdevazelhes wdevazelhes changed the title [WIP] Uniformize num_dims and add it for LMNN [MRG] Uniformize num_dims and add it for LMNN Jun 5, 2019
@wdevazelhes wdevazelhes requested a review from nvauquie June 7, 2019 08:03
Copy link
Member

@bellet bellet left a comment

Choose a reason for hiding this comment

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

LGTM. Merging

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants