Skip to content
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

MDS #205

Merged
merged 21 commits into from
Nov 15, 2023
Merged

MDS #205

merged 21 commits into from
Nov 15, 2023

Conversation

msluszniak
Copy link
Contributor

Closes #163

Currently, because we call isotonic regression inside defn I changed an implementation of isotonic regression so it would be able to runing MDS. Ofc, commenting whole sections of code is temporal solution and I'm wondering what we should do with it.

@msluszniak msluszniak marked this pull request as draft November 3, 2023 18:15
@josevalim
Copy link
Contributor

Do we need to preprocess? Because if we need to preprocess, then the best approach is likely to give the result of IsotonicRegression as an input to MDS.

@msluszniak
Copy link
Contributor Author

The preprocessing is generally needed for points that have the same x coordinate, so in real cases there are probably not much of these cases. The problem with passing results of IsotonicRegression is that this function is called multiple times inside while loop

@josevalim
Copy link
Contributor

So I think we can isotonic regression fit and then run the linear regression ourselves?

@msluszniak
Copy link
Contributor Author

I think I don't understand the concept

@josevalim
Copy link
Contributor

What I mean is that you defined a defn special_preprocess in IsotonicRegression that does what you need. :)

@msluszniak
Copy link
Contributor Author

Yeah, that's probably the best idea

@msluszniak msluszniak marked this pull request as ready for review November 7, 2023 19:45
@msluszniak
Copy link
Contributor Author

I don't know why the test results here are so strange. I mean, I know that when I invoke x() and key() directly inside the EXLA.jit_apply then I will achieve the same results as here, but they aren't reasonable (in contradiction to what I achieved locally calling x and key before)

@josevalim
Copy link
Contributor

@msluszniak what exactly is strange about it?

@msluszniak
Copy link
Contributor Author

For example, when I choose a smaller epsilon :eps (even veeery small) the result does not change in this setup as if there was a perfect convergence after only 5 or 6 steps, which is rather impossible

@msluszniak
Copy link
Contributor Author

msluszniak commented Nov 7, 2023

Locally, the response for smaller epsilon was as expected: much more iterations and smaller stress loss. And they correspond to what sklearn implemenation returns.

@josevalim
Copy link
Contributor

@msluszniak I see. In this case I can't help much, it seems to be related to the algorithm. :( maybe print_value can help debug.

@msluszniak
Copy link
Contributor Author

Yeap, there is definitely something wrong with smacof procedure since it's mathematically proven that the stress shouldn't increase but currently sometime it does for bigger number of samples

@msluszniak
Copy link
Contributor Author

Actually I debug the Sklearn implementation and there is the same behaviour here, so maybe there is nothing wrong here 😅
image

@msluszniak
Copy link
Contributor Author

Ok, I found a problem. The problem was in pairwise distance. For a function that calculates pairwise distance on a single tensor, there was only a check for negative values (that occures sometimes because of numerical instability). However, there is also a check needed for positive values on the main diagonal. Ideally, there should be only zeros, but because of numerical instability sometimes there are positive values that in my specific case cause that loss explode to huge values

@msluszniak
Copy link
Contributor Author

@josevalim why on one CI two test fails and on the other three? And why do even these tests fail? 😅

@josevalim
Copy link
Contributor

@msluszniak for what is worth, it is very common to have precision differences across machines and compiler versions. You will have to either increase the tolerance of the matrix comparison or test based on a property (I don't know if there is such a property for MDS).

@msluszniak
Copy link
Contributor Author

Ok, I understand. Unfortunately, there is no such property in MDS. This algorithm is very sensitive to any numerical changes, and the final result will be completely different (but also correct, only embedded in different space). I guess that we may flag these tests as @to_skip or something like that because I think it's good to have them just in case.

@josevalim
Copy link
Contributor

So how do you know MDS is correct? :D

@msluszniak
Copy link
Contributor Author

Actually, via visualization and empirical check. Even Sklearn has barely any tests for MDS https://github.com/scikit-learn/scikit-learn/blob/093e0cf14aff026cca6097e8c42f83b735d26358/sklearn/manifold/tests/test_mds.py. We can check the stress majorization procedure like they do, but that's all

@josevalim
Copy link
Contributor

Sounds like I plan to me.

@msluszniak
Copy link
Contributor Author

I think it's ready to go

@josevalim josevalim merged commit dacf106 into elixir-nx:main Nov 15, 2023
2 checks passed
@josevalim
Copy link
Contributor

💚 💙 💜 💛 ❤️

@msluszniak msluszniak deleted the mds branch July 12, 2024 08:58
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.

Add MDS
2 participants