1
1
import numpy as np
2
2
import pytest
3
+ from numpy .testing import assert_allclose
4
+ from scipy .sparse import issparse
3
5
4
6
from sklearn .base import ClassifierMixin
5
7
from sklearn .datasets import load_iris
6
8
from sklearn .linear_model import PassiveAggressiveClassifier , PassiveAggressiveRegressor
9
+ from sklearn .linear_model ._base import SPARSE_INTERCEPT_DECAY
10
+ from sklearn .linear_model ._stochastic_gradient import DEFAULT_EPSILON
7
11
from sklearn .utils import check_random_state
8
12
from sklearn .utils ._testing import (
9
13
assert_almost_equal ,
10
- assert_array_almost_equal ,
11
14
assert_array_equal ,
12
15
)
13
16
from sklearn .utils .fixes import CSR_CONTAINERS
@@ -24,7 +27,7 @@ class MyPassiveAggressive(ClassifierMixin):
24
27
def __init__ (
25
28
self ,
26
29
C = 1.0 ,
27
- epsilon = 0.01 ,
30
+ epsilon = DEFAULT_EPSILON ,
28
31
loss = "hinge" ,
29
32
fit_intercept = True ,
30
33
n_iter = 1 ,
@@ -41,6 +44,12 @@ def fit(self, X, y):
41
44
self .w = np .zeros (n_features , dtype = np .float64 )
42
45
self .b = 0.0
43
46
47
+ # Mimic SGD's behavior for intercept
48
+ intercept_decay = 1.0
49
+ if issparse (X ):
50
+ intercept_decay = SPARSE_INTERCEPT_DECAY
51
+ X = X .toarray ()
52
+
44
53
for t in range (self .n_iter ):
45
54
for i in range (n_samples ):
46
55
p = self .project (X [i ])
@@ -63,7 +72,7 @@ def fit(self, X, y):
63
72
64
73
self .w += step * X [i ]
65
74
if self .fit_intercept :
66
- self .b += step
75
+ self .b += intercept_decay * step
67
76
68
77
def project (self , X ):
69
78
return np .dot (X , self .w ) + self .b
@@ -123,15 +132,15 @@ def test_classifier_refit():
123
132
def test_classifier_correctness (loss , csr_container ):
124
133
y_bin = y .copy ()
125
134
y_bin [y != 1 ] = - 1
135
+ data = csr_container (X ) if csr_container is not None else X
126
136
127
- clf1 = MyPassiveAggressive (loss = loss , n_iter = 2 )
128
- clf1 .fit (X , y_bin )
137
+ clf1 = MyPassiveAggressive (loss = loss , n_iter = 4 )
138
+ clf1 .fit (data , y_bin )
129
139
130
- data = csr_container (X ) if csr_container is not None else X
131
- clf2 = PassiveAggressiveClassifier (loss = loss , max_iter = 2 , shuffle = False , tol = None )
140
+ clf2 = PassiveAggressiveClassifier (loss = loss , max_iter = 4 , shuffle = False , tol = None )
132
141
clf2 .fit (data , y_bin )
133
142
134
- assert_array_almost_equal (clf1 .w , clf2 .coef_ .ravel (), decimal = 2 )
143
+ assert_allclose (clf1 .w , clf2 .coef_ .ravel ())
135
144
136
145
137
146
@pytest .mark .parametrize (
@@ -251,15 +260,15 @@ def test_regressor_partial_fit(csr_container, average):
251
260
def test_regressor_correctness (loss , csr_container ):
252
261
y_bin = y .copy ()
253
262
y_bin [y != 1 ] = - 1
263
+ data = csr_container (X ) if csr_container is not None else X
254
264
255
- reg1 = MyPassiveAggressive (loss = loss , n_iter = 2 )
256
- reg1 .fit (X , y_bin )
265
+ reg1 = MyPassiveAggressive (loss = loss , n_iter = 4 )
266
+ reg1 .fit (data , y_bin )
257
267
258
- data = csr_container (X ) if csr_container is not None else X
259
- reg2 = PassiveAggressiveRegressor (tol = None , loss = loss , max_iter = 2 , shuffle = False )
268
+ reg2 = PassiveAggressiveRegressor (loss = loss , max_iter = 4 , shuffle = False , tol = None )
260
269
reg2 .fit (data , y_bin )
261
270
262
- assert_array_almost_equal (reg1 .w , reg2 .coef_ .ravel (), decimal = 2 )
271
+ assert_allclose (reg1 .w , reg2 .coef_ .ravel ())
263
272
264
273
265
274
def test_regressor_undefined_methods ():
0 commit comments