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

ENH add Huber datafit #14

Merged
merged 24 commits into from Jul 13, 2022
Merged

Conversation

EnLAI111
Copy link
Contributor

@EnLAI111 EnLAI111 commented May 4, 2022

When calling the function construct_grad(X, y, w, Xw, datafit, ws), I get the follow error.

This error may have been caused by the following argument(s):
- argument 4: Cannot determine Numba type of <class '__main__.Huber'>

So maybe there are bugs in the class Huber somewhere, but I can't figure out where.

@PABannier
Copy link
Collaborator

Hello @EnLAI111 , you need to decorate your Huber datafit with @jitclass decorator and specify the data type of your class attributes. Look at Quadratic for an example!

skglm/datafits/Huber.py Outdated Show resolved Hide resolved
skglm/datafits/Huber.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@mathurinm mathurinm left a comment

Choose a reason for hiding this comment

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

Thanks a lot for the PR @EnLAI111 ! I did a first pass of comments, don't hesitate to ping me if something is not explicit enough or if you need feedback.

skglm/datafits/Huber.py Outdated Show resolved Hide resolved
skglm/datafits/Huber.py Outdated Show resolved Hide resolved
skglm/datafits/Huber.py Outdated Show resolved Hide resolved
skglm/datafits/Huber.py Outdated Show resolved Hide resolved
n_features = X.shape[1]
self.lipschitz = np.zeros(n_features, dtype=X.dtype)
for j in range(n_features):
self.lipschitz[j] = (np.where(np.abs(y) < self.delta,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think the lipschitz constant should just be norm(X_j) ** 2?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I would have said norm(X_j) ** 2 / delta.

This makes me think on how do we want to solve this optimization problem?
If we want to use algorithms like in http://proceedings.mlr.press/v84/massias18a/massias18a.pdf and in https://arxiv.org/pdf/1902.02509.pdf, I think we will need a custom _cd_epoch function

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sure for delta ? https://github.com/scikit-learn-contrib/skglm/pull/14/files#diff-518236c0559dd6839714e8c437731d42952421ed7fed1319945a7d9bbe9f315eR20

There is no optimization over delta so far so no need for this solver, but if we need to optimize over this variable a dedicated solver will be needed

Copy link
Collaborator

Choose a reason for hiding this comment

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

ok I see, there is no delta for this parametrization!

skglm/datafits/Huber.py Outdated Show resolved Hide resolved
@EnLAI111
Copy link
Contributor Author

EnLAI111 commented May 4, 2022

Thanks a lot for the PR @EnLAI111 ! I did a first pass of comments, don't hesitate to ping me if something is not explicit enough or if you need feedback.

Thanks for the comments and suggestion! I have fixed the problems. Now with WeightedL1 there is no more posted errors of if __name__ == '__main__' execution.

skglm/datafits/huber.py Outdated Show resolved Hide resolved
skglm/datafits/huber.py Outdated Show resolved Hide resolved
skglm/datafits/huber.py Outdated Show resolved Hide resolved
skglm/datafits/huber.py Outdated Show resolved Hide resolved
@tomMoral
Copy link

tomMoral commented May 4, 2022

Hello @EnLAI111 , you need to decorate your Huber datafit with @jitclass decorator and specify the data type of your class attributes. Look at Quadratic for an example!

Note that this is not explicit in the doc. When reading it, I though it would be automatized by some jit_factaory you have (which was surprising indeed ^^)
image

Adding the spec_quadratic in the example and explicitely mentionning the need for a jitclass (with a check in the subsequent class) would help I think.

@PABannier
Copy link
Collaborator

To finalize this PR, unit tests should be added. Initially I wanted to compare it to sklearn's HuberRegressor but it turns out sklearn optimizes an additional parameter sigma. Any ideas on the unit tests we could write? @mathurinm @QB3

@Klopfe
Copy link
Collaborator

Klopfe commented Jun 21, 2022

To finalize this PR, unit tests should be added. Initially I wanted to compare it to sklearn's HuberRegressor but it turns out sklearn optimizes an additional parameter sigma. Any ideas on the unit tests we could write? @mathurinm @QB3

if we just want to test the convergence, we could use cvxpy to solve the optimization problem and check if the betas are the same. What do you think?

@mathurinm
Copy link
Collaborator

@Klopfe using cvxpy would introduce heavy dependency, instead we can fit a sklearn Huber regressor, find its scale, and then fit our model with delta = clf.scale_ * clf.epsilon.

I have pushed a script that does it. Beware that sklearn uses squared L2 regularization, and that the penalty is not scaled by 1/2 (their docstring is not very clear). I had to use more samples than features otherwise it fits perfectly and scale goes to 0

We don't have a way to handle unpenalized problems so I have used WeightedL1 with 0 weights. For future works...

@tomMoral
Copy link

another solution could be to use scipy.optimize to solve the problem ?

@mathurinm
Copy link
Collaborator

It's what HuberRegressor does already, so why rewrite this code ?

@mathurinm mathurinm changed the title add Huber datafits ENH add Huber datafit Jul 13, 2022
@mathurinm
Copy link
Collaborator

Did my pass, merge when green if LGTY @QB3 @PABannier

@QB3 QB3 merged commit f5e8154 into scikit-learn-contrib:main Jul 13, 2022
@mathurinm
Copy link
Collaborator

Thanks @EnLAI111 !

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.

None yet

6 participants