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

Rename to model_selection, GridSearchCV and LineSearchCV #58

Merged
merged 6 commits into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 46 additions & 46 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
BSD 3-Clause License

sparse-lm Copyright (c) 2022, The Regents of the University of California, through
Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
from the U.S. Dept. of Energy) and the University of California, Berkeley.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

(1) Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

(3) Neither the name of the University of California, Lawrence Berkeley
National Laboratory, U.S. Dept. of Energy, University of California,
Berkeley nor the names of its contributors may be used to endorse or
promote products derived from this software without specific prior written
permission.


THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

You are under no obligation whatsoever to provide any bug fixes, patches,
or upgrades to the features, functionality or performance of the source
code ("Enhancements") to anyone; however, if you choose to make your
Enhancements available either publicly, or directly to Lawrence Berkeley
National Laboratory, without imposing a separate written license agreement
for such Enhancements, then you hereby grant the following license: a
non-exclusive, royalty-free perpetual license to install, use, modify,
prepare derivative works, incorporate into other computer software,
distribute, and sublicense such enhancements or derivative works thereof,
in binary and source code form.
::

sparse-lm Copyright (c) 2022, The Regents of the University of California, through
Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
from the U.S. Dept. of Energy) and the University of California, Berkeley.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

(1) Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

(3) Neither the name of the University of California, Lawrence Berkeley
National Laboratory, U.S. Dept. of Energy, University of California,
Berkeley nor the names of its contributors may be used to endorse or
promote products derived from this software without specific prior written
permission.


THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

You are under no obligation whatsoever to provide any bug fixes, patches,
or upgrades to the features, functionality or performance of the source
code ("Enhancements") to anyone; however, if you choose to make your
Enhancements available either publicly, or directly to Lawrence Berkeley
National Laboratory, without imposing a separate written license agreement
for such Enhancements, then you hereby grant the following license: a
non-exclusive, royalty-free perpetual license to install, use, modify,
prepare derivative works, incorporate into other computer software,
distribute, and sublicense such enhancements or derivative works thereof,
in binary and source code form.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ Sparse Linear Regression Models
> Use at your own risk!

**sparse-lm** includes several regularized regression estimators that are absent in the
[`sklearn.linear_model`](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.linear_model)
module. The estimators in **sparse-lm** are designed to fit right into
`sklearn.linear_model` module. The estimators in **sparse-lm** are designed to fit right into
[scikit-lean](https://scikit-learn.org/stable/index.html) by inheriting from their base
`LinearModel`. But the underlying optimization problem is expressed and solved by
leveraging [cvxpy](https://www.cvxpy.org/).
Expand All @@ -35,7 +34,9 @@ From pypi:

Usage
-----
If you already use **scikit-learn**, using **sparse-lm** will be very easy
If you already use **scikit-learn**, using **sparse-lm** will be very easy. Just use any
model like you would any linear model in **scikit-learn**:

```python
import numpy as np
from sklearn.datasets import make_regression
Expand Down
56 changes: 28 additions & 28 deletions sparselm/optimizer.py → sparselm/model_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from sklearn.base import clone, is_classifier
from sklearn.metrics import check_scoring
from sklearn.metrics._scorer import _check_multimetric_scoring
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import GridSearchCV as _GridSearchCV
from sklearn.model_selection._search import BaseSearchCV
from sklearn.model_selection._split import check_cv
from sklearn.model_selection._validation import (
Expand All @@ -26,10 +26,10 @@
from sklearn.utils.validation import _check_fit_params, indexable


class GridSearch(GridSearchCV):
class GridSearchCV(_GridSearchCV):
"""Exhaustive search over specified parameter values for an estimator.

Same as GridSearchCV but we allow one standard error rule on all
Same as GridSearchCV but allows to use one standard error rule on all
non-negative numerical hyper-parameters, in order to get a
robust sparce estimation. Same documentation as scikit-learn's
GridSearchCV.
Expand Down Expand Up @@ -59,20 +59,20 @@ def __init__(
"""Initialize CVSearch tool.

Args:
estimator(Estimator):
estimator (Estimator):
A object of that type is instantiated for each grid point.
This is assumed to implement the scikit-learn estimator interface.
Either estimator needs to provide a ``score`` function,
or ``scoring`` must be passed.
param_grid(dict or list[dict]):
param_grid (dict or list[dict]):
Dictionary representing grid of hyper-parameters with their names
as keys and possible values. If given as a list of multiple dicts,
will search on multiple grids in parallel.
opt_selection_method(str, default="max_score"):
opt_selection_method (str, default="max_score"):
The method to select optimal hyper params. Default to "max_score", which
means to maximize the score. Can also choose "one_std_score", which means
to apply one standard error rule on scores.
scoring(str, callable, list, tuple or dict, default="neg_root_mean_squared_error"):
scoring (str, callable, list, tuple or dict, default="neg_root_mean_squared_error"):
Strategy to evaluate the performance of the cross-validated model on
the test set.
If `scoring` represents a single score, one can use:
Expand All @@ -87,12 +87,12 @@ def __init__(
Note: In sparse-lm, using "neg_root_mean_squared_error" is default
because in cluster expansion it is more conventional to analyze and present
errors in the root-mean-square error format compared to the r2_score.
n_jobs(int, default=None):
n_jobs (int, default=None):
Number of jobs to run in parallel.
``None`` means 1 unless in a :obj:`joblib.parallel_backend` context.
``-1`` means using all processors. See :term:`Glossary <n_jobs>`
for more details.
refit(bool, str, or callable, default=True)
refit (bool, str, or callable, default=True)
Refit an estimator using the best found parameters on the whole
dataset.
For multiple metric evaluation, this needs to be a `str` denoting the
Expand All @@ -113,7 +113,7 @@ def __init__(
scorer.
See ``scoring`` parameter to know more about multiple metric
evaluation.
cv(int, cross-validation generator or an iterable, default=None):
cv (int, cross-validation generator or an iterable, default=None):
Determines the cross-validation splitting strategy.
Possible inputs for cv are:
- None, to use the default 5-fold cross validation,
Expand All @@ -126,14 +126,14 @@ def __init__(
with `shuffle=False` so the splits will be the same across calls.
Refer :ref:`User Guide <cross_validation>` for the various
cross-validation strategies that can be used here.
verbose(int, default=0):
verbose (int, default=0):
Controls the verbosity: the higher, the more messages.
- >1 : the computation time for each fold and parameter candidate is
displayed;
- >2 : the score is also displayed;
- >3 : the fold and candidate parameter indexes are also displayed
together with the starting time of the computation.
pre_dispatch(int, or str, default='2*n_jobs'):
pre_dispatch (int, or str, default='2*n_jobs'):
Controls the number of jobs that get dispatched during parallel
execution. Reducing this number can be useful to avoid an
explosion of memory consumption when more jobs get dispatched
Expand All @@ -146,12 +146,12 @@ def __init__(
spawned
- A str, giving an expression as a function of n_jobs,
as in '2*n_jobs'
error_score('raise' or numeric, default=np.nan):
error_score ('raise' or numeric, default=np.nan):
Value to assign to the score if an error occurs in estimator fitting.
If set to 'raise', the error is raised. If a numeric value is given,
FitFailedWarning is raised. This parameter does not affect the refit
step, which will always raise the error.
return_train_score(bool, default=False):
return_train_score (bool, default=False):
If ``False``, the ``cv_results_`` attribute will not include training
scores.
Computing training scores is used to get insights on how different
Expand Down Expand Up @@ -406,7 +406,7 @@ def evaluate_candidates(candidate_params, cv=None, more_results=None):
return self


class LineSearch(BaseSearchCV):
class LineSearchCV(BaseSearchCV):
"""Implements line search.

In line search, we do 1 dimensional grid searches on each hyper-param up
Expand All @@ -433,17 +433,17 @@ def __init__(
"""Initialize a LineSearch.

Args:
estimator(Estimator):
estimator (Estimator):
A object of that type is instantiated for each grid point.
This is assumed to implement the scikit-learn estimator interface.
Either estimator needs to provide a ``score`` function,
or ``scoring`` must be passed.
param_grid(list[tuple]):
param_grid (list[tuple]):
List of tuples with parameters names (`str`) as first element
and lists of parameter settings to try as the second element.
In LineSearch, the hyper-params given first will be searched first
in a cycle. Multiple grids search is NOT supported!
opt_selection_method(list(str) or str, default="max_score"):
opt_selection_method (list(str) or str, default="max_score"):
The method to select optimal hyper params. Default to "max_score", which
means to maximize score score. Can also choose "one_std_score", which means
to apply one standard error rule on score scores.
Expand All @@ -452,13 +452,13 @@ def __init__(
the param_grid. For example, a good practice when using L2L0 estimator
shall be opt_selection_method = ["one_std_score", "max_score"] for "alpha"
and "l0_ratio", respectively.
n_iter(int, default=None):
n_iter (int, default=None):
Number of iterations to perform. One iteration means a 1D search on
one hyper-param, and we scan one hyper-param at a time in the order of
param_grid.
n_iter must be at least as large as the number of hyper-params. Default
is 2 * number of hyper-params.
scoring(str, callable, list, tuple or dict, default="neg_root_mean_squared_error"):
scoring (str, callable, list, tuple or dict, default="neg_root_mean_squared_error"):
Strategy to evaluate the performance of the cross-validated model on
the test set.
If `scoring` represents a single score, one can use:
Expand All @@ -473,12 +473,12 @@ def __init__(
Note: In sparse-lm, using "neg_root_mean_squared_error" is default
because in cluster expansion it is more conventional to analyze and present
errors in the root-mean-square error format compared to the r2_score.
n_jobs(int, default=None):
n_jobs (int, default=None):
Number of jobs to run in parallel.
``None`` means 1 unless in a :obj:`joblib.parallel_backend` context.
``-1`` means using all processors. See :term:`Glossary <n_jobs>`
for more details.
refit(bool, str, or callable, default=True)
refit (bool, str, or callable, default=True)
Refit an estimator using the best found parameters on the whole
dataset.
For multiple metric evaluation, this needs to be a `str` denoting the
Expand All @@ -499,7 +499,7 @@ def __init__(
scorer.
See ``scoring`` parameter to know more about multiple metric
evaluation.
cv(int, cross-validation generator or an iterable, default=None):
cv (int, cross-validation generator or an iterable, default=None):
Determines the cross-validation splitting strategy.
Possible inputs for cv are:
- None, to use the default 5-fold cross validation,
Expand All @@ -512,14 +512,14 @@ def __init__(
with `shuffle=False` so the splits will be the same across calls.
Refer :ref:`User Guide <cross_validation>` for the various
cross-validation strategies that can be used here.
verbose(int, default=0):
verbose (int, default=0):
Controls the verbosity: the higher, the more messages.
- >1 : the computation time for each fold and parameter candidate is
displayed;
- >2 : the score is also displayed;
- >3 : the fold and candidate parameter indexes are also displayed
together with the starting time of the computation.
pre_dispatch(int, or str, default='2*n_jobs'):
pre_dispatch (int, or str, default='2*n_jobs'):
Controls the number of jobs that get dispatched during parallel
execution. Reducing this number can be useful to avoid an
explosion of memory consumption when more jobs get dispatched
Expand All @@ -532,12 +532,12 @@ def __init__(
spawned
- A str, giving an expression as a function of n_jobs,
as in '2*n_jobs'
error_score('raise' or numeric, default=np.nan):
error_score ('raise' or numeric, default=np.nan):
Value to assign to the score if an error occurs in estimator fitting.
If set to 'raise', the error is raised. If a numeric value is given,
FitFailedWarning is raised. This parameter does not affect the refit
step, which will always raise the error.
return_train_score(bool, default=False):
return_train_score (bool, default=False):
If ``False``, the ``cv_results_`` attribute will not include training
scores.
Computing training scores is used to get insights on how different
Expand Down Expand Up @@ -636,7 +636,7 @@ def fit(self, X, y=None, *, groups=None, **fit_params):
):
param_line[name] = [last_value] if pid != param_id else values

grid_search = GridSearch(
grid_search = GridSearchCV(
estimator=self.estimator,
param_grid=param_line,
opt_selection_method=self.opt_selection_methods[param_id],
Expand Down
6 changes: 3 additions & 3 deletions tests/test_optimizers.py → tests/test_model_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import pytest

from sparselm.model.miqp._regularized_l0 import L1L0, L2L0
from sparselm.optimizer import GridSearch, LineSearch
from sparselm.model_selection import GridSearchCV, LineSearchCV

ALL_CRITERION = ["max_score", "one_std_score"]
# Currently we will only test on mixedL0
Expand Down Expand Up @@ -88,7 +88,7 @@ def test_mixed_l0_wts(random_model, mixed_l2l0_est, random_weights):

@pytest.fixture(scope="module", params=ALL_CRITERION)
def grid_search(estimator, param_grid, request):
grid_searcher = GridSearch(
grid_searcher = GridSearchCV(
estimator, param_grid, opt_selection_method=request.param
)
return grid_searcher
Expand All @@ -98,7 +98,7 @@ def grid_search(estimator, param_grid, request):
def line_search(estimator, param_grid, request):
# Multi-grids not supported in line search mode.
param_grid_lines = sorted((key, values) for key, values in param_grid[0].items())
line_searcher = LineSearch(
line_searcher = LineSearchCV(
estimator, param_grid_lines, opt_selection_method=request.param, n_iter=3
)
return line_searcher
Expand Down