66
77from skglm .datafits import Quadratic , QuadraticMultiTask
88from skglm .penalties import (
9- L1 , L1_plus_L2 , WeightedL1 , MCPenalty , SCAD , IndicatorBox , L0_5 , L2_3 ,
9+ L1 , L1_plus_L2 , WeightedL1 , MCPenalty , SCAD , IndicatorBox , L0_5 , L2_3 , SLOPE ,
1010 L2_1 , L2_05 , BlockMCPenalty , BlockSCAD )
11- from skglm import GeneralizedLinearEstimator
12- from skglm .solvers import AndersonCD , MultiTaskBCD
11+ from skglm import GeneralizedLinearEstimator , Lasso
12+ from skglm .solvers import AndersonCD , MultiTaskBCD , FISTA
1313from skglm .utils import make_correlated_data
1414
1515
2525alpha_max = norm (X .T @ y , ord = np .inf ) / n_samples
2626alpha = alpha_max / 1000
2727
28+ tol = 1e-10
29+
2830penalties = [
2931 L1 (alpha = alpha ),
3032 L1_plus_L2 (alpha = alpha , l1_ratio = 0.5 ),
4446
4547@pytest .mark .parametrize ('penalty' , penalties )
4648def test_subdiff_diff (penalty ):
47- tol = 1e-10
4849 # tol=1e-14 is too low when coefs are of order 1. square roots are computed in
4950 # some penalties and precision is lost
5051 est = GeneralizedLinearEstimator (
@@ -58,7 +59,6 @@ def test_subdiff_diff(penalty):
5859
5960@pytest .mark .parametrize ('block_penalty' , block_penalties )
6061def test_subdiff_diff_block (block_penalty ):
61- tol = 1e-10 # see test_subdiff_dist
6262 est = GeneralizedLinearEstimator (
6363 datafit = QuadraticMultiTask (),
6464 penalty = block_penalty ,
@@ -68,5 +68,38 @@ def test_subdiff_diff_block(block_penalty):
6868 assert_array_less (est .stop_crit_ , est .solver .tol )
6969
7070
71+ def test_slope_lasso ():
72+ # check that when alphas = [alpha, ..., alpha], SLOPE and L1 solutions are equal
73+ alphas = np .full (n_features , alpha )
74+ est = GeneralizedLinearEstimator (
75+ penalty = SLOPE (alphas ),
76+ solver = FISTA (max_iter = 1000 , tol = tol , opt_strategy = "fixpoint" ),
77+ ).fit (X , y )
78+ lasso = Lasso (alpha , fit_intercept = False , tol = tol ).fit (X , y )
79+ np .testing .assert_allclose (est .coef_ , lasso .coef_ , rtol = 1e-5 )
80+
81+
82+ def test_slope ():
83+ # compare solutions with `pyslope`: https://github.com/jolars/pyslope
84+ try :
85+ from slope .solvers import pgd_slope # noqa
86+ from slope .utils import lambda_sequence # noqa
87+ except ImportError :
88+ pytest .xfail (
89+ "This test requires slope to run.\n "
90+ "https://github.com/jolars/pyslope" )
91+
92+ q = 0.1
93+ alphas = lambda_sequence (
94+ X , y , fit_intercept = False , reg = alpha / alpha_max , q = q )
95+ ours = GeneralizedLinearEstimator (
96+ penalty = SLOPE (alphas ),
97+ solver = FISTA (max_iter = 1000 , tol = tol , opt_strategy = "fixpoint" ),
98+ ).fit (X , y )
99+ pyslope_out = pgd_slope (
100+ X , y , alphas , fit_intercept = False , max_it = 1000 , gap_tol = tol )
101+ np .testing .assert_allclose (ours .coef_ , pyslope_out ["beta" ], rtol = 1e-5 )
102+
103+
71104if __name__ == "__main__" :
72105 pass
0 commit comments