-
-
Notifications
You must be signed in to change notification settings - Fork 26k
[MRG+2] Make CD use fused types #6913
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
Conversation
do you expect to merge just this or is it wip? |
@agramfort Yeah I am thinking of merging just these as a start point. |
I'm not sure what value there is in merging it separately to something we can benchmark. For instance, you've fused So I think we want to review this as a whole. |
Thanks @jnothman @agramfort . |
0bab8d3
to
bb6ec9b
Compare
***Updated 7/7
Here is my test script: import
8000
span> numpy as np
from sklearn.linear_model.coordinate_descent import ElasticNet
from sys import argv
@profile
def fit_est():
clf.fit(X, y)
np.random.seed(5)
X = np.random.rand(2000000, 40)
X = np.float32(X)
y = np.random.rand(2000000)
y = np.float32(y)
T = np.random.rand(5, 40)
T = np.float32(T)
clf = ElasticNet(alpha=1e-7, l1_ratio=1.0, precompute=False)
fit_est()
pred = clf.predict(T)
print pred |
8f79269
to
61a7938
Compare
|
||
# np.dot(R.T, y) | ||
gap += (alpha * l1_norm - const * ddot( | ||
if floating is double: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you absolutely certain we can't do this with fused types? What prohibits it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This algorithm uses lots of C pointer such as <DOUBLE*>
, we can't do <floating*>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're saying Cython disallows fused type pointers, or typecasts? Is that incapability documented?
Could we use typecasts if we were working with typed memoryviews?
Could you use the line-based memory profiling to see where that sharp increase in memory consumption is coming in? |
Sorry, that was silly; only appropriate if the bad memory usage is in Python code. |
fit_intercept and not np.allclose(X_offset, np.zeros(n_features)) or | ||
normalize and not np.allclose(X_scale, np.ones(n_features))): | ||
fit_intercept and not np.allclose(X_offset, np.zeros(n_features)) | ||
or normalize and not np.allclose(X_scale, np.ones(n_features))): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see why this is an improvement, or why it's in this PR.
92e2aad
to
82f6f9c
Compare
Hello @jnothman & @MechCoder , thanks alot-alot-alot-alot for your patience and comments. I've updated the PR description (including new memory profiling results), code, and addressed comments you gave before. The remaining to-do tasks in my opinion are also listed in the main description of this PR. |
I've added the tests and the user warning for potential non-convergence error when fitting However, the CI looks weird, any idea? |
e784ecd
to
132d9fb
Compare
@jnothman done! |
132d9fb
to
82fdf09
Compare
Have you forgotten to push those last changes? whats_new does not appear updated, nor the warning. |
@@ -474,7 +474,8 @@ def enet_path(X, y, l1_ratio=0.5, eps=1e-3, n_alphas=100, alphas=None, | |||
warnings.warn('Objective did not converge.' + | |||
' You might want' + | |||
' to increase the number of iterations.' + | |||
' Fitting data with alpha near zero, e.g., 1e-8,' + | |||
' Fitting float32 data with alpha near zero,' + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But this is only relevant if the data is float32, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I think fitting with a really small alpha, e.g., 1e-20, even float64 data may not converge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, so make the warning as relevant and useful as possible to a user that triggers it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So is simply remove the float32 enough 😛?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really, because alpha=1e-8 isn't ordinarily too small for normalized float64. Either remove reference to the alpha value or check appropriate conditions for the message, then it will be much more meaningful message. Also "alpha near zero" would usually be "very small alpha".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to admit that I'm not very sure about all the factors that will cause convergence issue, and thus not dare to determine a specific reference value.
Or we can remove reference to the alpha value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove any specific value. Just say near zero
On 25 August 2016 at 23:34, Yen notifications@github.com wrote:
In sklearn/linear_model/coordinate_descent.py
#6913 (comment)
:@@ -474,7 +474,8 @@ def enet_path(X, y, l1_ratio=0.5, eps=1e-3, n_alphas=100, alphas=None,
warnings.warn('Objective did not converge.' +
' You might want' +
' to increase the number of iterations.' +
' Fitting data with alpha near zero, e.g., 1e-8,' +
' Fitting float32 data with alpha near zero,' +
I have to admit that I'm not very sure about all the factors that will
cause convergence issue, and thus not dare to determine a specific
reference value.Or we can remove reference to the alpha value?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/scikit-learn/scikit-learn/pull/6913/files/82fdf0962e3c7b0965b54ca137a56ab6d01fc226..c032d3b5820b53fb0717008435a44245cdb746f1#r76242986,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEz65p1hO8jA-O7s1Ka5BIexYN_p7qlks5qjZnKgaJpZM4I6SId
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done!
c032d3b
to
d5e73ae
Compare
d5e73ae
to
611b412
Compare
@@ -470,7 +473,10 @@ def enet_path(X, y, l1_ratio=0.5, eps=1e-3, n_alphas=100, alphas=None, | |||
if dual_gap_ > eps_: | |||
warnings.warn('Objective did not converge.' + | |||
' You might want' + | |||
' to increase the number of iterations', | |||
' to increase the number of iterations.' + | |||
' Fitting data with alpha near zero,' + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did we not agree to add this message only when alpha
is less than some heuristic value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems hard to determine a heuristic value 😭
There are too many factors.
Your benchmarks in the description of the Pull Request suggests non-trivial speed gains. Do the speed gains also still hold? |
@MechCoder yes! |
Awesome! Merging with master and thanks a lot for your perseverance. |
😭😭 😭 🍻🍻🍻 |
It should be worth adding a note to |
Hurrah! Thanks @fabianp for rescuing this. And to @MechCoder for inviting that saviour. And to @yenchenlin for winning. |
And to you the dark knight? :p |
Just a heads up that I'm a little concerned that these changes to Lasso changed its behaviour (for float64 data). It seems to have resulted in a test failure at #6717 (comment). For the dummy data I've tried so far, behaviour isn't changed, so this needs more verification. |
…learn#6913) ElasticNet and Lasso no longer implicitly convert float32 dtype input to float64 internally. * Make helper functions in cd use fused types * Import cblas float functions * Make enet_coordinate_descent support fused types * Make dense case work * Refactor format * Remove redundant change * Add cblas files * Avoid redundant code * Remove redundant c files and import * Recover unnecessary change * Update comment * Make coef_ type consistent * Test float32 input * Add user warning when fitting float32 data with small alpha * Fix bug * Change variable to floating type * Make cd sparse support fused types * Make CD support fused types when data is sparse * Add referenced src files * Avoid duplicated code * Avoid type casting * Fix indentation in test * Avoid type casting in sparse implementation * Fix indentation * Fix duplicated intialization code * Follow PEP8 * Raise tmp precision to double * Add 64 bit computer check * Fix test * Add constraint * PEP 8 * Make saxpy have the same structure as daxpy Hopefully this fixes the problems outlined in PR scikit-learn#6913 * Remove wrong hardware test * Remove dsdot * Remove redundant asarray * Add test for fit_intercept * Make _preprocess_data support other dtypes * Add concrete value * Workaround * Fix error msg * Move declarartion * Remove redundant comment * Add tests * Test normalize * Delete warning * Fix comment * Add error msg * Add error msg * Add what's new * Fix error msg
According to #5464, current implementation of ElasticNet and Lasso in scikit-learn constrain the input to be
np.float64
, which is a waste of space.This PR try to make CD algorithms support fused types when fitting
np.float32
dense data and therefore reduce redundant data copy.np.float32
**UPDATE 7/7
Here is the memory profiling results when fitting
np.float32
data:**UPDATE 7/12
Here is the memory profiling results when fitting sparse
np.float32
data: