-
-
Notifications
You must be signed in to change notification settings - Fork 26k
[NOMRG] new warmstart API for GBDTs #15105
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
Changes from all commits
e8f45c5
9eb8dd0
d7cb8be
50f5214
134d4f1
7ea6e9e
c00cab5
fdccca8
e84ecbc
f605a4d
1f7167d
b77fe73
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,6 +132,19 @@ def __init__(self, steps, memory=None, verbose=False): | |
self.verbose = verbose | ||
self._validate_steps() | ||
|
||
@property | ||
def _warmstartable_parameters(self): | ||
# This property exposes the _warmstartable_parameters attribute, e.g. | ||
# ['+last_step_name__param'] | ||
# We consider that only the last step can be warm-started. The first | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to make this design choice? I may have asked this question before, but don't remember your logic behind it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A pipeline is either:
It's safe to assume that transformers are not warm-startable. Maybe in the future one of them will be?? We can worry about that when that happens. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could have a word embedding transformer as a step, which very often is warm started. We may not have that inside sklearn, but the pipeline's API should support it, I think. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree we should leave the possibility open, and make the code future-proof. This is one of the reasons why But I don't think we should implement support for that, we have no use-case ATM. Concretely, supporting warm-start for transformers right now is writing code that isn't used (that would require updating the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. Yeah fair. |
||
# steps are transformers that cannot be warm-started. | ||
out = [] | ||
step_name, est = self.steps[-1] | ||
for param in getattr(est, '_warmstartable_parameters', []): | ||
sign, param_name = param[0], param[1:] | ||
out.append(sign + step_name + '__' + param_name) | ||
return out | ||
|
||
def get_params(self, deep=True): | ||
"""Get parameters for this estimator. | ||
|
||
|
@@ -318,7 +331,7 @@ def _fit(self, X, y=None, **fit_params): | |
return X, {} | ||
return X, fit_params_steps[self.steps[-1][0]] | ||
|
||
def fit(self, X, y=None, **fit_params): | ||
def fit(self, X, y=None, warm_start_with=None, **fit_params): | ||
"""Fit the model | ||
|
||
Fit all the transforms one after the other and transform the | ||
|
@@ -339,6 +352,9 @@ def fit(self, X, y=None, **fit_params): | |
each parameter name is prefixed such that parameter ``p`` for step | ||
``s`` has key ``s__p``. | ||
|
||
warm_start_with : dict, default=None | ||
Indicate which parameter to warm-start, with its new value. | ||
|
||
Returns | ||
------- | ||
self : Pipeline | ||
|
@@ -348,7 +364,20 @@ def fit(self, X, y=None, **fit_params): | |
with _print_elapsed_time('Pipeline', | ||
self._log_message(len(self.steps) - 1)): | ||
if self._final_estimator != 'passthrough': | ||
self._final_estimator.fit(Xt, y, **fit_params) | ||
if self._check_warm_start_with(warm_start_with): | ||
# convert {laststep__param: val} into just {param: val} | ||
# Could be a util in the base class | ||
warm_start_with_final = { | ||
name.split('__')[1]: val | ||
for name, val in warm_start_with.items() | ||
} | ||
|
||
self._final_estimator.fit( | ||
Xt, y, warm_start_with=warm_start_with_final, | ||
**fit_params) | ||
else: | ||
self._final_estimator.fit(Xt, y, **fit_params) | ||
|
||
return self | ||
|
||
def fit_transform(self, X, y=None, **fit_params): | ||
|
Uh oh!
There was an error while loading. Please reload this page.