From b6748ee328f346a242c27ca4d2d59ec1935fc1f5 Mon Sep 17 00:00:00 2001 From: Samuel Vaiter Date: Mon, 3 Jul 2023 14:42:22 +0200 Subject: [PATCH 1/8] DCT inpainting dataset + small fix for PGD --- datasets/dct_inpainting.py | 61 ++++++++++++++++++++++++++++++++++++++ solvers/python_pgd.py | 6 +++- 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 datasets/dct_inpainting.py diff --git a/datasets/dct_inpainting.py b/datasets/dct_inpainting.py new file mode 100644 index 00000000..f5d67323 --- /dev/null +++ b/datasets/dct_inpainting.py @@ -0,0 +1,61 @@ +from benchopt import BaseDataset +from benchopt import safe_import_context + + +with safe_import_context() as import_ctx: + from scipy.fftpack import dctn, idctn + from scipy.datasets import ascent + from scipy.sparse.linalg import LinearOperator + import numpy as np + + +class Dataset(BaseDataset): + name = "dct_inpainting" + + def __init__(self, random_state=27): + self.random_state = random_state + self.X, self.y = None, None + + @staticmethod + def _load_image(noise_level=0.01, random_state=27): + rng = np.random.RandomState(random_state) + + y = ascent().astype(np.float64) / 255.0 + y += noise_level * rng.normal(0, 1.0, size=y.shape) + + return y + + def get_data(self): + if self.X is None or self.y is None: + y = self._load_image(noise_level=0.1, random_state=self.random_state) + (pw, ph) = y.shape + + rng = np.random.RandomState(self.random_state) + mask = rng.binomial(1, 0.9, pw * ph).astype(bool) + + y = y.flatten() + y[mask] = 0.0 + + def _fwd_operator(u): + dct_coeffs = idctn(u.reshape((pw, ph)), norm="ortho").reshape( + (pw * ph,) + ) + dct_coeffs[mask] = 0.0 + return dct_coeffs + + def _rfwd_operator(x): + masked_coeffs = x.copy() + masked_coeffs[mask] = 0.0 + idct_coeffs = dctn( + masked_coeffs.reshape((pw, ph)), norm="ortho" + ).reshape((pw * ph,)) + return idct_coeffs + + _fwd_scipy_operator = LinearOperator( + (pw * ph, pw * ph), + matvec=_fwd_operator, + rmatvec=_rfwd_operator, + ) + + self.X, self.y = _fwd_scipy_operator, y + return dict(X=self.X, y=self.y) diff --git a/solvers/python_pgd.py b/solvers/python_pgd.py index 81f600b2..963fd24d 100644 --- a/solvers/python_pgd.py +++ b/solvers/python_pgd.py @@ -3,6 +3,8 @@ with safe_import_context() as import_ctx: import numpy as np from scipy import sparse + from scipy.linalg.interpolative import estimate_spectral_norm + from scipy.sparse.linalg import LinearOperator class Solver(BaseSolver): @@ -63,7 +65,9 @@ def get_result(self): return self.w def compute_lipschitz_constant(self): - if not sparse.issparse(self.X): + if isinstance(self.X, LinearOperator): + L = estimate_spectral_norm(self.X) ** 2 + elif not sparse.issparse(self.X): L = np.linalg.norm(self.X, ord=2) ** 2 else: L = sparse.linalg.svds(self.X, k=1)[1][0] ** 2 From 9e033c85538f7d90d70e0cbd9bd945e3f905949a Mon Sep 17 00:00:00 2001 From: Samuel Vaiter Date: Mon, 3 Jul 2023 15:13:34 +0200 Subject: [PATCH 2/8] Update solvers to skip when implicit operator are not supported --- solvers/blitz.py | 4 ++++ solvers/cd.py | 3 +++ solvers/celer.py | 7 +++++++ solvers/cuml.py | 7 +++++++ solvers/cyanure.py | 7 +++++++ solvers/glmnet.py | 7 +++++++ solvers/glum.py | 7 +++++++ solvers/irls.py | 4 ++++ solvers/julia_pgd.py | 4 ++++ solvers/l_bfgs_b.py | 3 +++ solvers/lars.py | 7 +++++++ solvers/lightning.py | 3 +++ solvers/modopt_fista.py | 7 ++++++- solvers/modopt_pogm.py | 6 +++++- solvers/noncvx_pro.py | 5 ++++- solvers/r_pgd.py | 3 +++ solvers/skglm.py | 3 +++ solvers/sklearn.py | 7 +++++++ solvers/snapml.py | 4 ++++ solvers/spams.py | 4 ++++ 20 files changed, 99 insertions(+), 3 deletions(-) diff --git a/solvers/blitz.py b/solvers/blitz.py index 8e94e07f..ca22623d 100644 --- a/solvers/blitz.py +++ b/solvers/blitz.py @@ -3,6 +3,7 @@ with safe_import_context() as import_ctx: + from scipy.sparse.linalg import LinearOperator import blitzl1 @@ -24,6 +25,9 @@ def skip(self, X, y, lmbd, fit_intercept): if fit_intercept: return True, f"{self.name} does not handle fit_intercept" + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + return False, None def set_objective(self, X, y, lmbd, fit_intercept): diff --git a/solvers/cd.py b/solvers/cd.py index 289a2170..658c1c48 100644 --- a/solvers/cd.py +++ b/solvers/cd.py @@ -3,6 +3,7 @@ with safe_import_context() as import_ctx: import numpy as np + from scipy.sparse.linalg import LinearOperator from scipy import sparse from numba import njit @@ -40,6 +41,8 @@ def skip(self, X, y, lmbd, fit_intercept): # XXX - not implemented but this should be quite easy if fit_intercept: return True, f"{self.name} does not handle fit_intercept" + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" return False, None diff --git a/solvers/celer.py b/solvers/celer.py index 0704fc3e..83f55d1b 100644 --- a/solvers/celer.py +++ b/solvers/celer.py @@ -6,6 +6,7 @@ with safe_import_context() as import_ctx: import numpy as np + from scipy.sparse.linalg import LinearOperator from celer import Lasso from sklearn.exceptions import ConvergenceWarning @@ -22,6 +23,12 @@ class Solver(BaseSolver): 'vol. 80, pp. 3321-3330 (2018)' ] + def skip(self, X, y, lmbd, fit_intercept): + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + + return False, None + def set_objective(self, X, y, lmbd, fit_intercept): self.X, self.y, self.lmbd = X, y, lmbd self.fit_intercept = fit_intercept diff --git a/solvers/cuml.py b/solvers/cuml.py index 16e0f760..514a1042 100644 --- a/solvers/cuml.py +++ b/solvers/cuml.py @@ -5,6 +5,7 @@ cuda_version = None with safe_import_context() as import_ctx: import numpy as np + from scipy.sparse.linalg import LinearOperator from scipy import sparse cuda_version = requires_gpu() @@ -44,6 +45,12 @@ class Solver(BaseSolver): eps=1e-12, patience=5, strategy='iteration' ) + def skip(self, X, y, lmbd, fit_intercept): + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + + return False, None + def set_objective(self, X, y, lmbd, fit_intercept): self.X, self.y, self.lmbd = X, y, lmbd if sparse.issparse(X): diff --git a/solvers/cyanure.py b/solvers/cyanure.py index 675be5b6..c15b7ee6 100644 --- a/solvers/cyanure.py +++ b/solvers/cyanure.py @@ -4,6 +4,7 @@ with safe_import_context() as import_ctx: import scipy + from scipy.sparse.linalg import LinearOperator import numpy as np from cyanure import Regression @@ -19,6 +20,12 @@ class Solver(BaseSolver): 'Arxiv eprint 1912.08165 (2019)' ] + def skip(self, X, y, lmbd, fit_intercept): + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + + return False, None + def set_objective(self, X, y, lmbd, fit_intercept): self.X, self.y, self.lmbd = X, y, lmbd self.fit_intercept = fit_intercept diff --git a/solvers/glmnet.py b/solvers/glmnet.py index a1856f45..49b936db 100644 --- a/solvers/glmnet.py +++ b/solvers/glmnet.py @@ -5,6 +5,7 @@ with safe_import_context() as import_ctx: import numpy as np from scipy import sparse + from scipy.sparse.linalg import LinearOperator from rpy2 import robjects from rpy2.robjects import numpy2ri, packages @@ -33,6 +34,12 @@ class Solver(BaseSolver): patience=7, eps=1e-38, strategy='tolerance' ) + def skip(self, X, y, lmbd, fit_intercept): + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + + return False, None + def set_objective(self, X, y, lmbd, fit_intercept): if sparse.issparse(X): r_Matrix = packages.importr("Matrix") diff --git a/solvers/glum.py b/solvers/glum.py index 9c6d79d1..ae64d538 100644 --- a/solvers/glum.py +++ b/solvers/glum.py @@ -5,6 +5,7 @@ with safe_import_context() as import_ctx: import numpy as np + from scipy.sparse.linalg import LinearOperatro from glum import GeneralizedLinearRegressor from sklearn.exceptions import ConvergenceWarning @@ -17,6 +18,12 @@ class Solver(BaseSolver): stopping_criterion = SufficientProgressCriterion( patience=5, strategy='tolerance') + def skip(self, X, y, lmbd, fit_intercept): + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + + return False, None + def set_objective(self, X, y, lmbd, fit_intercept): self.X, self.y, self.lmbd = X, y, lmbd self.fit_intercept = fit_intercept diff --git a/solvers/irls.py b/solvers/irls.py index f7b52941..2ec231bf 100644 --- a/solvers/irls.py +++ b/solvers/irls.py @@ -3,6 +3,7 @@ with safe_import_context() as import_ctx: import numpy as np + from scipy.sparse.linalg import LinearOperator from sklearn.linear_model import Ridge @@ -28,6 +29,9 @@ def skip(self, X, y, lmbd, fit_intercept): if fit_intercept: return True, f"{self.name} does not handle fit_intercept" + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + return False, None def set_objective(self, X, y, lmbd, fit_intercept): diff --git a/solvers/julia_pgd.py b/solvers/julia_pgd.py index 999a419f..19cceadb 100644 --- a/solvers/julia_pgd.py +++ b/solvers/julia_pgd.py @@ -6,6 +6,7 @@ from benchopt.helpers.julia import assert_julia_installed with safe_import_context() as import_ctx: + from scipy.sparse.linalg import LinearOperator assert_julia_installed() @@ -33,6 +34,9 @@ def skip(self, X, y, lmbd, fit_intercept): if fit_intercept: return True, f"{self.name} does not handle fit_intercept" + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + return False, None def set_objective(self, X, y, lmbd, fit_intercept): diff --git a/solvers/l_bfgs_b.py b/solvers/l_bfgs_b.py index 2410c352..a44ecf55 100644 --- a/solvers/l_bfgs_b.py +++ b/solvers/l_bfgs_b.py @@ -3,6 +3,7 @@ with safe_import_context() as import_ctx: import numpy as np + from scipy.sparse.linalg import LinearOperator from numpy.linalg import norm from scipy.optimize import fmin_l_bfgs_b @@ -31,6 +32,8 @@ def skip(self, X, y, lmbd, fit_intercept): # XXX - not implemented but this should be quite easy if fit_intercept: return True, f"{self.name} does not handle fit_intercept" + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" return False, None diff --git a/solvers/lars.py b/solvers/lars.py index e2ad6fc8..4afb3399 100644 --- a/solvers/lars.py +++ b/solvers/lars.py @@ -5,6 +5,7 @@ with safe_import_context() as import_ctx: import warnings import numpy as np + from scipy.sparse.linalg import LinearOperator from sklearn.linear_model import LassoLars from sklearn.exceptions import ConvergenceWarning @@ -21,6 +22,12 @@ class Solver(BaseSolver): ] support_sparse = False + def skip(self, X, y, lmbd, fit_intercept): + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + + return False, None + def set_objective(self, X, y, lmbd, fit_intercept): self.X, self.y, self.lmbd = X, y, lmbd self.fit_intercept = fit_intercept diff --git a/solvers/lightning.py b/solvers/lightning.py index bf7be8eb..e94b9791 100644 --- a/solvers/lightning.py +++ b/solvers/lightning.py @@ -4,6 +4,7 @@ with safe_import_context() as import_ctx: import numpy as np + from scipy.sparse.linalg import LinearOperator from lightning.regression import CDRegressor @@ -27,6 +28,8 @@ class Solver(BaseSolver): def skip(self, X, y, lmbd, fit_intercept): if fit_intercept: return True, f"{self.name} does not handle fit_intercept" + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" return False, None diff --git a/solvers/modopt_fista.py b/solvers/modopt_fista.py index 9443f652..cb31590a 100644 --- a/solvers/modopt_fista.py +++ b/solvers/modopt_fista.py @@ -6,6 +6,8 @@ with safe_import_context() as import_ctx: from scipy import sparse + from scipy.sparse.linalg import LinearOperator + from scipy.linalg.interpolative import estimate_spectral_norm from modopt.opt.algorithms import ForwardBackward from modopt.opt.proximity import SparseThreshold from modopt.opt.linear import Identity @@ -45,7 +47,9 @@ def set_objective(self, X, y, lmbd, fit_intercept): self.var_init = np.zeros(n_features) def run(self, callback): - if sparse.issparse(self.X): + if isinstance(self.X, LinearOperator): + L = estimate_spectral_norm(self.X) ** 2 + elif sparse.issparse(self.X): L = sparse.linalg.svds(self.X, k=1)[1][0] ** 2 else: L = np.linalg.norm(self.X, ord=2) ** 2 @@ -64,6 +68,7 @@ def run(self, callback): q_lazy = 1 / 10 n_features = self.X.shape[1] + if self.fit_intercept: def op(w): return self.X @ w[:n_features] + w[-1] diff --git a/solvers/modopt_pogm.py b/solvers/modopt_pogm.py index 168db17f..25bc0461 100644 --- a/solvers/modopt_pogm.py +++ b/solvers/modopt_pogm.py @@ -6,6 +6,8 @@ with safe_import_context() as import_ctx: from scipy import sparse + from scipy.sparse.linalg import LinearOperator + from scipy.linalg.interpolative import estimate_spectral_norm from modopt.opt.algorithms import POGM from modopt.opt.proximity import SparseThreshold from modopt.opt.linear import Identity @@ -63,7 +65,9 @@ def trans_op(res): weights = np.full(self.X.shape[1], self.lmbd) - if sparse.issparse(self.X): + if isinstance(self.X, LinearOperator): + L = estimate_spectral_norm(self.X) ** 2 + elif sparse.issparse(self.X): L = sparse.linalg.svds(self.X, k=1)[1][0] ** 2 else: L = np.linalg.norm(self.X, ord=2) ** 2 diff --git a/solvers/noncvx_pro.py b/solvers/noncvx_pro.py index 8317a48d..3b66e059 100644 --- a/solvers/noncvx_pro.py +++ b/solvers/noncvx_pro.py @@ -7,7 +7,7 @@ from numpy.linalg import norm import scipy.optimize as sciop from scipy.sparse import issparse - + from scipy.sparse.linalg import LinearOperator class Solver(BaseSolver): name = "noncvx-pro" @@ -30,6 +30,9 @@ def set_objective(self, X, y, lmbd, fit_intercept): def skip(self, X, y, lmbd, fit_intercept): if fit_intercept: return True, f"{self.name} does not handle fit_intercept" + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + return False, None def run(self, n_iter): diff --git a/solvers/r_pgd.py b/solvers/r_pgd.py index 54c65421..531f91dc 100644 --- a/solvers/r_pgd.py +++ b/solvers/r_pgd.py @@ -5,6 +5,7 @@ with safe_import_context() as import_ctx: import numpy as np + from scipy.sparse.linalg import LinearOperator from rpy2 import robjects from rpy2.robjects import numpy2ri @@ -36,6 +37,8 @@ class Solver(BaseSolver): def skip(self, X, y, lmbd, fit_intercept): if fit_intercept: return True, f"{self.name} does not handle fit_intercept" + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" return False, None diff --git a/solvers/skglm.py b/solvers/skglm.py index 1581c7b1..add4b50b 100644 --- a/solvers/skglm.py +++ b/solvers/skglm.py @@ -4,6 +4,7 @@ with safe_import_context() as import_ctx: import warnings import numpy as np + from scipy.sparse.linalg import LinearOperator from skglm import Lasso from sklearn.exceptions import ConvergenceWarning @@ -26,6 +27,8 @@ class Solver(BaseSolver): def skip(self, X, y, lmbd, fit_intercept): if fit_intercept: return True, f"{self.name} does not handle fit_intercept" + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" return False, None diff --git a/solvers/sklearn.py b/solvers/sklearn.py index 572b9c35..73d58260 100644 --- a/solvers/sklearn.py +++ b/solvers/sklearn.py @@ -5,6 +5,7 @@ with safe_import_context() as import_ctx: import numpy as np + from scipy.sparse.linalg import LinearOperator from sklearn.linear_model import Lasso from sklearn.exceptions import ConvergenceWarning @@ -23,6 +24,12 @@ class Solver(BaseSolver): 'vol. 12, pp. 2825-283 (2011)' ] + def skip(self, X, y, lmbd, fit_intercept): + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + + return False, None + def set_objective(self, X, y, lmbd, fit_intercept): self.X, self.y, self.lmbd = X, y, lmbd self.fit_intercept = fit_intercept diff --git a/solvers/snapml.py b/solvers/snapml.py index 14866d27..332cb535 100644 --- a/solvers/snapml.py +++ b/solvers/snapml.py @@ -5,6 +5,7 @@ with safe_import_context() as import_ctx: from snapml import LinearRegression import numpy as np + from scipy.sparse.linalg import LinearOperator class Solver(BaseSolver): @@ -26,6 +27,9 @@ class Solver(BaseSolver): def skip(self, X, y, lmbd, fit_intercept): if self.gpu and get_cuda_version() is None: return True, "snapml[gpu=True] needs a GPU to run" + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + return False, None def set_objective(self, X, y, lmbd, fit_intercept): diff --git a/solvers/spams.py b/solvers/spams.py index f90b57b7..065bee9b 100644 --- a/solvers/spams.py +++ b/solvers/spams.py @@ -4,6 +4,7 @@ with safe_import_context() as import_ctx: import scipy import numpy as np + from scipy.sparse.linalg import LinearOperator from spams import lasso, fistaFlat @@ -21,6 +22,9 @@ class Solver(BaseSolver): def skip(self, X, y, lmbd, fit_intercept): if fit_intercept: return True, f"{self.name} does not work with fit_intercept" + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + return False, None def set_objective(self, X, y, lmbd, fit_intercept): From 21863cb5313aa7f6a0857a0d4ed792aa58db8d34 Mon Sep 17 00:00:00 2001 From: Samuel Vaiter Date: Mon, 3 Jul 2023 16:04:53 +0200 Subject: [PATCH 3/8] Add requirements --- objective.py | 1 + 1 file changed, 1 insertion(+) diff --git a/objective.py b/objective.py index 7b7b879d..7a607c26 100644 --- a/objective.py +++ b/objective.py @@ -12,6 +12,7 @@ class Objective(BaseObjective): 'fit_intercept': [True, False], 'reg': [.5, .1, .05], } + requirements = ["scipy"] def __init__(self, reg=.1, fit_intercept=False): self.reg = reg From 89a993748c6ff49dd13fcaabceb4c5b48ce513bc Mon Sep 17 00:00:00 2001 From: Samuel Vaiter Date: Mon, 3 Jul 2023 16:07:44 +0200 Subject: [PATCH 4/8] CI trigger From 036d4c4902cae2c0483dc36c7a9fe080acccadf4 Mon Sep 17 00:00:00 2001 From: Samuel Vaiter Date: Mon, 3 Jul 2023 16:13:14 +0200 Subject: [PATCH 5/8] Fix linter --- datasets/dct_inpainting.py | 12 +++++------- solvers/glum.py | 11 ++++------- solvers/l_bfgs_b.py | 2 +- solvers/noncvx_pro.py | 3 ++- solvers/snapml.py | 2 +- solvers/spams.py | 2 +- 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/datasets/dct_inpainting.py b/datasets/dct_inpainting.py index f5d67323..bfc6e9b6 100644 --- a/datasets/dct_inpainting.py +++ b/datasets/dct_inpainting.py @@ -1,7 +1,6 @@ from benchopt import BaseDataset from benchopt import safe_import_context - with safe_import_context() as import_ctx: from scipy.fftpack import dctn, idctn from scipy.datasets import ascent @@ -27,7 +26,8 @@ def _load_image(noise_level=0.01, random_state=27): def get_data(self): if self.X is None or self.y is None: - y = self._load_image(noise_level=0.1, random_state=self.random_state) + y = self._load_image(noise_level=0.1, + random_state=self.random_state) (pw, ph) = y.shape rng = np.random.RandomState(self.random_state) @@ -38,17 +38,15 @@ def get_data(self): def _fwd_operator(u): dct_coeffs = idctn(u.reshape((pw, ph)), norm="ortho").reshape( - (pw * ph,) - ) + (pw * ph, )) dct_coeffs[mask] = 0.0 return dct_coeffs def _rfwd_operator(x): masked_coeffs = x.copy() masked_coeffs[mask] = 0.0 - idct_coeffs = dctn( - masked_coeffs.reshape((pw, ph)), norm="ortho" - ).reshape((pw * ph,)) + idct_coeffs = dctn(masked_coeffs.reshape((pw, ph)), + norm="ortho").reshape((pw * ph, )) return idct_coeffs _fwd_scipy_operator = LinearOperator( diff --git a/solvers/glum.py b/solvers/glum.py index ae64d538..8275ec34 100644 --- a/solvers/glum.py +++ b/solvers/glum.py @@ -5,7 +5,7 @@ with safe_import_context() as import_ctx: import numpy as np - from scipy.sparse.linalg import LinearOperatro + from scipy.sparse.linalg import LinearOperator from glum import GeneralizedLinearRegressor from sklearn.exceptions import ConvergenceWarning @@ -18,12 +18,6 @@ class Solver(BaseSolver): stopping_criterion = SufficientProgressCriterion( patience=5, strategy='tolerance') - def skip(self, X, y, lmbd, fit_intercept): - if isinstance(X, LinearOperator): - return True, f"{self.name} does not handle implicit operator" - - return False, None - def set_objective(self, X, y, lmbd, fit_intercept): self.X, self.y, self.lmbd = X, y, lmbd self.fit_intercept = fit_intercept @@ -46,6 +40,9 @@ def set_objective(self, X, y, lmbd, fit_intercept): def skip(self, X, y, lmbd, fit_intercept): # glum instantiates a Hessian of size (n_features, n_features) + if isinstance(X, LinearOperator): + return True, f"{self.name} does not handle implicit operator" + if X.shape[1] > 20_000: return True, "glum does not support n_features >= 20000" return False, None diff --git a/solvers/l_bfgs_b.py b/solvers/l_bfgs_b.py index a44ecf55..c1b2ff5a 100644 --- a/solvers/l_bfgs_b.py +++ b/solvers/l_bfgs_b.py @@ -33,7 +33,7 @@ def skip(self, X, y, lmbd, fit_intercept): if fit_intercept: return True, f"{self.name} does not handle fit_intercept" if isinstance(X, LinearOperator): - return True, f"{self.name} does not handle implicit operator" + return True, f"{self.name} does not handle implicit operator" return False, None diff --git a/solvers/noncvx_pro.py b/solvers/noncvx_pro.py index 3b66e059..3bb1c5c5 100644 --- a/solvers/noncvx_pro.py +++ b/solvers/noncvx_pro.py @@ -9,6 +9,7 @@ from scipy.sparse import issparse from scipy.sparse.linalg import LinearOperator + class Solver(BaseSolver): name = "noncvx-pro" @@ -32,7 +33,7 @@ def skip(self, X, y, lmbd, fit_intercept): return True, f"{self.name} does not handle fit_intercept" if isinstance(X, LinearOperator): return True, f"{self.name} does not handle implicit operator" - + return False, None def run(self, n_iter): diff --git a/solvers/snapml.py b/solvers/snapml.py index 332cb535..15a3edf4 100644 --- a/solvers/snapml.py +++ b/solvers/snapml.py @@ -29,7 +29,7 @@ def skip(self, X, y, lmbd, fit_intercept): return True, "snapml[gpu=True] needs a GPU to run" if isinstance(X, LinearOperator): return True, f"{self.name} does not handle implicit operator" - + return False, None def set_objective(self, X, y, lmbd, fit_intercept): diff --git a/solvers/spams.py b/solvers/spams.py index 065bee9b..4dadf534 100644 --- a/solvers/spams.py +++ b/solvers/spams.py @@ -24,7 +24,7 @@ def skip(self, X, y, lmbd, fit_intercept): return True, f"{self.name} does not work with fit_intercept" if isinstance(X, LinearOperator): return True, f"{self.name} does not handle implicit operator" - + return False, None def set_objective(self, X, y, lmbd, fit_intercept): From b49042340ff2fe8ea714b0ee7224603f92b7476f Mon Sep 17 00:00:00 2001 From: Samuel Vaiter Date: Mon, 3 Jul 2023 16:29:26 +0200 Subject: [PATCH 6/8] Add pooch requirements to dct_inpaiting --- datasets/dct_inpainting.py | 1 + 1 file changed, 1 insertion(+) diff --git a/datasets/dct_inpainting.py b/datasets/dct_inpainting.py index bfc6e9b6..f1586882 100644 --- a/datasets/dct_inpainting.py +++ b/datasets/dct_inpainting.py @@ -10,6 +10,7 @@ class Dataset(BaseDataset): name = "dct_inpainting" + requirements = ["pooch"] def __init__(self, random_state=27): self.random_state = random_state From d07342728019c4c43e47f79113d7e22e5f7c2e62 Mon Sep 17 00:00:00 2001 From: Samuel Vaiter Date: Mon, 3 Jul 2023 16:47:49 +0200 Subject: [PATCH 7/8] dirty import of pooch --- datasets/dct_inpainting.py | 1 + 1 file changed, 1 insertion(+) diff --git a/datasets/dct_inpainting.py b/datasets/dct_inpainting.py index f1586882..bd303eb0 100644 --- a/datasets/dct_inpainting.py +++ b/datasets/dct_inpainting.py @@ -4,6 +4,7 @@ with safe_import_context() as import_ctx: from scipy.fftpack import dctn, idctn from scipy.datasets import ascent + import pooch # noqa: F401 from scipy.sparse.linalg import LinearOperator import numpy as np From 8e8331317899e0ecfa23972884ad61935c883844 Mon Sep 17 00:00:00 2001 From: Samuel Vaiter Date: Tue, 4 Jul 2023 00:22:16 +0200 Subject: [PATCH 8/8] Apply @mathurinm comments --- datasets/dct_inpainting.py | 8 ++++---- objective.py | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/datasets/dct_inpainting.py b/datasets/dct_inpainting.py index bd303eb0..fab4a276 100644 --- a/datasets/dct_inpainting.py +++ b/datasets/dct_inpainting.py @@ -2,11 +2,11 @@ from benchopt import safe_import_context with safe_import_context() as import_ctx: - from scipy.fftpack import dctn, idctn - from scipy.datasets import ascent import pooch # noqa: F401 - from scipy.sparse.linalg import LinearOperator import numpy as np + from scipy.datasets import ascent + from scipy.fftpack import dctn, idctn + from scipy.sparse.linalg import LinearOperator class Dataset(BaseDataset): @@ -30,7 +30,7 @@ def get_data(self): if self.X is None or self.y is None: y = self._load_image(noise_level=0.1, random_state=self.random_state) - (pw, ph) = y.shape + pw, ph = y.shape rng = np.random.RandomState(self.random_state) mask = rng.binomial(1, 0.9, pw * ph).astype(bool) diff --git a/objective.py b/objective.py index 7a607c26..7b7b879d 100644 --- a/objective.py +++ b/objective.py @@ -12,7 +12,6 @@ class Objective(BaseObjective): 'fit_intercept': [True, False], 'reg': [.5, .1, .05], } - requirements = ["scipy"] def __init__(self, reg=.1, fit_intercept=False): self.reg = reg