4
4
from numba import float64
5
5
6
6
from skglm .datafits .base import BaseDatafit
7
+ from skglm .utils import spectral_norm
7
8
8
9
9
10
class Quadratic (BaseDatafit ):
@@ -22,6 +23,10 @@ class Quadratic(BaseDatafit):
22
23
The coordinatewise gradient Lipschitz constants. Equal to
23
24
norm(X, axis=0) ** 2 / n_samples.
24
25
26
+ global_lipschitz : float
27
+ Global Lipschitz constant. Equal to
28
+ norm(X, ord=2) ** 2 / n_samples.
29
+
25
30
Note
26
31
----
27
32
The class is jit compiled at fit time using Numba compiler.
@@ -35,6 +40,7 @@ def get_spec(self):
35
40
spec = (
36
41
('Xty' , float64 [:]),
37
42
('lipschitz' , float64 [:]),
43
+ ('global_lipschitz' , float64 ),
38
44
)
39
45
return spec
40
46
@@ -44,14 +50,18 @@ def params_to_dict(self):
44
50
def initialize (self , X , y ):
45
51
self .Xty = X .T @ y
46
52
n_features = X .shape [1 ]
53
+ self .global_lipschitz = norm (X , ord = 2 ) ** 2 / len (y )
47
54
self .lipschitz = np .zeros (n_features , dtype = X .dtype )
48
55
for j in range (n_features ):
49
56
self .lipschitz [j ] = (X [:, j ] ** 2 ).sum () / len (y )
50
57
51
- def initialize_sparse (
52
- self , X_data , X_indptr , X_indices , y ):
58
+ def initialize_sparse (self , X_data , X_indptr , X_indices , y ):
53
59
n_features = len (X_indptr ) - 1
54
60
self .Xty = np .zeros (n_features , dtype = X_data .dtype )
61
+
62
+ self .global_lipschitz = spectral_norm (X_data , X_indptr , X_indices , len (y )) ** 2
63
+ self .global_lipschitz /= len (y )
64
+
55
65
self .lipschitz = np .zeros (n_features , dtype = X_data .dtype )
56
66
for j in range (n_features ):
57
67
nrm2 = 0.
@@ -111,6 +121,10 @@ class Logistic(BaseDatafit):
111
121
The coordinatewise gradient Lipschitz constants. Equal to
112
122
norm(X, axis=0) ** 2 / (4 * n_samples).
113
123
124
+ global_lipschitz : float
125
+ Global Lipschitz constant. Equal to
126
+ norm(X, ord=2) ** 2 / (4 * n_samples).
127
+
114
128
Note
115
129
----
116
130
The class is jit compiled at fit time using Numba compiler.
@@ -123,6 +137,7 @@ def __init__(self):
123
137
def get_spec (self ):
124
138
spec = (
125
139
('lipschitz' , float64 [:]),
140
+ ('global_lipschitz' , float64 ),
126
141
)
127
142
return spec
128
143
@@ -140,9 +155,14 @@ def raw_hessian(self, y, Xw):
140
155
141
156
def initialize (self , X , y ):
142
157
self .lipschitz = (X ** 2 ).sum (axis = 0 ) / (len (y ) * 4 )
158
+ self .global_lipschitz = norm (X , ord = 2 ) ** 2 / (len (y ) * 4 )
143
159
144
160
def initialize_sparse (self , X_data , X_indptr , X_indices , y ):
145
161
n_features = len (X_indptr ) - 1
162
+
163
+ self .global_lipschitz = spectral_norm (X_data , X_indptr , X_indices , len (y )) ** 2
164
+ self .global_lipschitz /= 4 * len (y )
165
+
146
166
self .lipschitz = np .zeros (n_features , dtype = X_data .dtype )
147
167
for j in range (n_features ):
148
168
Xj = X_data [X_indptr [j ]:X_indptr [j + 1 ]]
@@ -187,6 +207,11 @@ class QuadraticSVC(BaseDatafit):
187
207
----------
188
208
lipschitz : array, shape (n_features,)
189
209
The coordinatewise gradient Lipschitz constants.
210
+ Equal to norm(yXT, axis=0) ** 2.
211
+
212
+ global_lipschitz : float
213
+ Global Lipschitz constant. Equal to
214
+ norm(yXT, ord=2) ** 2.
190
215
191
216
Note
192
217
----
@@ -200,6 +225,7 @@ def __init__(self):
200
225
def get_spec (self ):
201
226
spec = (
202
227
('lipschitz' , float64 [:]),
228
+ ('global_lipschitz' , float64 ),
203
229
)
204
230
return spec
205
231
@@ -209,12 +235,16 @@ def params_to_dict(self):
209
235
def initialize (self , yXT , y ):
210
236
n_features = yXT .shape [1 ]
211
237
self .lipschitz = np .zeros (n_features , dtype = yXT .dtype )
238
+ self .global_lipschitz = norm (yXT , ord = 2 ) ** 2
212
239
for j in range (n_features ):
213
240
self .lipschitz [j ] = norm (yXT [:, j ]) ** 2
214
241
215
- def initialize_sparse (
216
- self , yXT_data , yXT_indptr , yXT_indices , y ):
242
+ def initialize_sparse (self , yXT_data , yXT_indptr , yXT_indices , y ):
217
243
n_features = len (yXT_indptr ) - 1
244
+
245
+ self .global_lipschitz = spectral_norm (
246
+ yXT_data , yXT_indptr , yXT_indices , max (yXT_indices )+ 1 ) ** 2
247
+
218
248
self .lipschitz = np .zeros (n_features , dtype = yXT_data .dtype )
219
249
for j in range (n_features ):
220
250
nrm2 = 0.
@@ -264,8 +294,16 @@ class Huber(BaseDatafit):
264
294
265
295
Attributes
266
296
----------
297
+ delta : float
298
+ Threshold hyperparameter.
299
+
267
300
lipschitz : array, shape (n_features,)
268
- The coordinatewise gradient Lipschitz constants.
301
+ The coordinatewise gradient Lipschitz constants. Equal to
302
+ norm(X, axis=0) ** 2 / n_samples.
303
+
304
+ global_lipschitz : float
305
+ Global Lipschitz constant. Equal to
306
+ norm(X, ord=2) ** 2 / n_samples.
269
307
270
308
Note
271
309
----
@@ -279,7 +317,8 @@ def __init__(self, delta):
279
317
def get_spec (self ):
280
318
spec = (
281
319
('delta' , float64 ),
282
- ('lipschitz' , float64 [:])
320
+ ('lipschitz' , float64 [:]),
321
+ ('global_lipschitz' , float64 ),
283
322
)
284
323
return spec
285
324
@@ -289,12 +328,17 @@ def params_to_dict(self):
289
328
def initialize (self , X , y ):
290
329
n_features = X .shape [1 ]
291
330
self .lipschitz = np .zeros (n_features , dtype = X .dtype )
331
+ self .global_lipschitz = 0.
292
332
for j in range (n_features ):
293
333
self .lipschitz [j ] = (X [:, j ] ** 2 ).sum () / len (y )
334
+ self .global_lipschitz += (X [:, j ] ** 2 ).sum () / len (y )
294
335
295
- def initialize_sparse (
296
- self , X_data , X_indptr , X_indices , y ):
336
+ def initialize_sparse (self , X_data , X_indptr , X_indices , y ):
297
337
n_features = len (X_indptr ) - 1
338
+
339
+ self .global_lipschitz = spectral_norm (X_data , X_indptr , X_indices , len (y )) ** 2
340
+ self .global_lipschitz /= len (y )
341
+
298
342
self .lipschitz = np .zeros (n_features , dtype = X_data .dtype )
299
343
for j in range (n_features ):
300
344
nrm2 = 0.
0 commit comments