7
7
# Author: Vlad Niculae
8
8
# License: BSD
9
9
10
- from libc.stdlib cimport malloc, free
11
10
from libc.math cimport fabs
11
+ from cython.view cimport array
12
12
13
13
from lightning.impl.dataset_fast cimport ColumnDataset
14
14
@@ -19,7 +19,7 @@ from .cd_linear_fast cimport _cd_linear_epoch
19
19
cdef void _precompute(ColumnDataset X,
20
20
double [:, :, ::1 ] P,
21
21
Py_ssize_t order,
22
- double * out,
22
+ double [:, :: 1 ] out,
23
23
Py_ssize_t s,
24
24
unsigned int degree):
25
25
@@ -32,15 +32,17 @@ cdef void _precompute(ColumnDataset X,
32
32
cdef int n_nz
33
33
34
34
cdef Py_ssize_t i, j, ii
35
+ cdef unsigned int d
36
+ cdef double tmp
35
37
36
38
for i in range (n_samples):
37
- out[i] = 0
38
-
39
+ out[degree - 1 , i] = 0
40
+
39
41
for j in range (n_features):
40
42
X.get_column_ptr(j, & indices, & data, & n_nz)
41
43
for ii in range (n_nz):
42
44
i = indices[ii]
43
- out[i] += (data[ii] * P[order, s, j]) ** degree
45
+ out[degree - 1 , i] += (data[ii] * P[order, s, j]) ** degree
44
46
45
47
46
48
cdef inline double _update(int * indices,
@@ -50,12 +52,11 @@ cdef inline double _update(int* indices,
50
52
double [:] y,
51
53
double [:] y_pred,
52
54
LossFunction loss,
53
- double * d1,
54
- double * d2,
55
55
unsigned int degree,
56
56
double lam,
57
57
double beta,
58
- double * cache_kp):
58
+ double [:, ::1 ] D,
59
+ double [:] cache_kp):
59
60
60
61
cdef double l1_reg = 2 * beta * fabs(lam)
61
62
@@ -70,10 +71,10 @@ cdef inline double _update(int* indices,
70
71
i = indices[ii]
71
72
72
73
if degree == 2 :
73
- kp = d1[ i] - p_js * data[ii]
74
- elif degree == 3 :
75
- kp = 0.5 * (d1[ i] ** 2 - d2[ i])
76
- kp -= p_js * data[ii] * d1[ i]
74
+ kp = D[ 0 , i] - p_js * data[ii]
75
+ else : # degree == 3:
76
+ kp = 0.5 * (D[ 0 , i] ** 2 - D[ 1 , i])
77
+ kp -= p_js * data[ii] * D[ 0 , i]
77
78
kp += p_js ** 2 * data[ii] ** 2
78
79
79
80
kp *= lam * data[ii]
@@ -97,12 +98,11 @@ cdef inline double _cd_direct_epoch(double[:, :, ::1] P,
97
98
double [:] y,
98
99
double [:] y_pred,
99
100
double [:] lams,
100
- double * d1,
101
- double * d2,
102
101
unsigned int degree,
103
102
double beta,
104
103
LossFunction loss,
105
- double * cache_kp):
104
+ double [:, ::1 ] D,
105
+ double [:] cache_kp):
106
106
107
107
cdef Py_ssize_t s, j
108
108
cdef double p_old, update, offset
@@ -118,9 +118,9 @@ cdef inline double _cd_direct_epoch(double[:, :, ::1] P,
118
118
for s in range (n_components):
119
119
120
120
# initialize the cached ds for this s
121
- _precompute(X, P, order, d1 , s, 1 )
121
+ _precompute(X, P, order, D , s, 1 )
122
122
if degree == 3 :
123
- _precompute(X, P, order, d2 , s, 2 )
123
+ _precompute(X, P, order, D , s, 2 )
124
124
125
125
for j in range (n_features):
126
126
@@ -129,7 +129,7 @@ cdef inline double _cd_direct_epoch(double[:, :, ::1] P,
129
129
# compute coordinate update
130
130
p_old = P[order, s, j]
131
131
update = _update(indices, data, n_nz, p_old, y, y_pred,
132
- loss, d1, d2, degree, lams[s], beta, cache_kp)
132
+ loss, degree, lams[s], beta, D , cache_kp)
133
133
P[order, s, j] -= update
134
134
sum_viol += fabs(update)
135
135
@@ -138,9 +138,10 @@ cdef inline double _cd_direct_epoch(double[:, :, ::1] P,
138
138
i = indices[ii]
139
139
140
140
if degree == 3 :
141
- d2[i] -= (p_old ** 2 - P[order, s, j] ** 2 ) * data[ii] ** 2
141
+ D[1 , i] -= ((p_old ** 2 - P[order, s, j] ** 2 ) *
142
+ data[ii] ** 2 )
142
143
143
- d1[ i] -= update * data[ii]
144
+ D[ 0 , i] -= update * data[ii]
144
145
y_pred[i] -= update * cache_kp[ii]
145
146
return sum_viol
146
147
@@ -169,11 +170,8 @@ def _cd_direct_ho(double[:, :, ::1] P not None,
169
170
cdef bint converged = False
170
171
171
172
# precomputed values
172
- cdef double * d1 = < double * > malloc(n_samples * sizeof(double ))
173
- cdef double * d2
174
- if degree == 3 :
175
- d2 = < double * > malloc(n_samples * sizeof(double ))
176
- cdef double * cache_kp = < double * > malloc(n_samples * sizeof(double ))
173
+ cdef double [:, ::1 ] D = array((degree - 1 , n_samples), sizeof(double ), ' d' )
174
+ cdef double [:] cache_kp = array((n_samples,), sizeof(double ), ' d' )
177
175
178
176
for it in range (max_iter):
179
177
viol = 0
@@ -182,11 +180,11 @@ def _cd_direct_ho(double[:, :, ::1] P not None,
182
180
viol += _cd_linear_epoch(w, X, y, y_pred, col_norm_sq, alpha, loss)
183
181
184
182
if fit_lower and degree == 3 : # fit degree 2. Will be looped later.
185
- viol += _cd_direct_epoch(P, 1 , X, y, y_pred, lams, d1, d2 ,
186
- 2 , beta, loss , cache_kp)
183
+ viol += _cd_direct_epoch(P, 1 , X, y, y_pred, lams, 2 , beta, loss ,
184
+ D , cache_kp)
187
185
188
- viol += _cd_direct_epoch(P, 0 , X, y, y_pred, lams, d1, d2 ,
189
- degree, beta, loss , cache_kp)
186
+ viol += _cd_direct_epoch(P, 0 , X, y, y_pred, lams, degree, beta, loss ,
187
+ D , cache_kp)
190
188
191
189
if verbose:
192
190
print (" Iteration" , it + 1 , " violation sum" , viol)
@@ -197,10 +195,4 @@ def _cd_direct_ho(double[:, :, ::1] P not None,
197
195
converged = True
198
196
break
199
197
200
- # Free up cache
201
- free(d1)
202
- free(cache_kp)
203
- if degree == 3 :
204
- free(d2)
205
-
206
198
return converged
0 commit comments