8000 MNT: Use memoryviews instead of ndarrays (#11722) · scikit-learn/scikit-learn@7849376 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7849376

Browse files
jakirkhamjnothman
authored andcommitted
MNT: Use memoryviews instead of ndarrays (#11722)
1 parent 38e7c8b commit 7849376

File tree

1 file changed

+19
-27
lines changed

1 file changed

+19
-27
lines changed

sklearn/linear_model/cd_fast.pyx

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,10 @@ cdef extern from "cblas.h":
141141
@cython.boundscheck(False)
142142
@cython.wraparound(False)
143143
@cython.cdivision(True)
144-
def enet_coordinate_descent(np.ndarray[floating, ndim=1, mode='c'] w,
144+
def enet_coordinate_descent(floating[::1] w,
145145
floating alpha, floating beta,
146-
np.ndarray[floating, ndim=2, mode='fortran'] X,
147-
np.ndarray[floating, ndim=1, mode='c'] y,
146+
floating[::1, :] X,
147+
floating[::1] y,
148148
int max_iter, floating tol,
149149
object rng, bint random=0, bint positive=0):
150150
"""Cython version of the coordinate descent algorithm
@@ -173,11 +173,11 @@ def enet_coordinate_descent(np.ndarray[floating, ndim=1, mode='c'] w,
173173
cdef unsigned int n_features = X.shape[1]
174174

175175
# compute norms of the columns of X
176-
cdef np.ndarray[floating, ndim=1] norm_cols_X = (X**2).sum(axis=0)
176+
cdef floating[::1] norm_cols_X = np.square(X).sum(axis=0)
177177

178178
# initial value of the residuals
179-
cdef np.ndarray[floating, ndim=1] R = np.empty(n_samples, dtype=dtype)
180-
cdef np.ndarray[floating, ndim=1] XtA = np.empty(n_features, dtype=dtype)
179+
cdef floating[::1] R = np.empty(n_samples, dtype=dtype)
180+
cdef floating[::1] XtA = np.empty(n_features, dtype=dtype)
181181

182182
cdef floating tmp
183183
cdef floating w_ii
@@ -199,23 +199,17 @@ def enet_coordinate_descent(np.ndarray[floating, ndim=1, mode='c'] w,
199199
cdef UINT32_t rand_r_state_seed = rng.randint(0, RAND_R_MAX)
200200
cdef UINT32_t* rand_r_state = &rand_r_state_seed
201201

202-
cdef floating *X_data = <floating*> X.data
203-
cdef floating *y_data = <floating*> y.data
204-
cdef floating *w_data = <floating*> w.data
205-
cdef floating *R_data = <floating*> R.data
206-
cdef floating *XtA_data = <floating*> XtA.data
207-
208202
if alpha == 0 and beta == 0:
209203
warnings.warn("Coordinate descent with no regularization may lead to unexpected"
210204
" results and is discouraged.")
211205

212206
with nogil:
213207
# R = y - np.dot(X, w)
214208
for i in range(n_samples):
215-
R[i] = y[i] - dot(n_features, &X_data[i], n_samples, w_data, 1)
209+
R[i] = y[i] - dot(n_features, &X[i, 0], n_samples, &w[0], 1)
216210

217211
# tol *= np.dot(y, y)
218-
tol *= dot(n_samples, y_data, 1, y_data, 1)
212+
tol *= dot(n_samples, &y[0], 1, &y[0], 1)
219213

220214
for n_iter in range(max_iter):
221215
w_max = 0.0
@@ -233,11 +227,10 @@ def enet_coordinate_descent(np.ndarray[floating, ndim=1, mode='c'] w,
233227

234228
if w_ii != 0.0:
235229
# R += w_ii * X[:,ii]
236-
axpy(n_samples, w_ii, &X_data[ii * n_samples], 1,
237-
R_data, 1)
230+
axpy(n_samples, w_ii, &X[0, ii], 1, &R[0], 1)
238231

239232
# tmp = (X[:,ii]*R).sum()
240-
tmp = dot(n_samples, &X_data[ii * n_samples], 1, R_data, 1)
233+
tmp = dot(n_samples, &X[0, ii], 1, &R[0], 1)
241234

242235
if positive and tmp < 0:
243236
w[ii] = 0.0
@@ -247,8 +240,7 @@ def enet_coordinate_descent(np.ndarray[floating, ndim=1, mode='c'] w,
247240

248241
if w[ii] != 0.0:
249242
# R -= w[ii] * X[:,ii] # Update residual
250-
axpy(n_samples, -w[ii], &X_data[ii * n_samples], 1,
251-
R_data, 1)
243+
axpy(n_samples, -w[ii], &X[0, ii], 1, &R[0], 1)
252244

253245
# update the maximum absolute coefficient update
254246
d_w_ii = fabs(w[ii] - w_ii)
@@ -267,19 +259,19 @@ def enet_coordinate_descent(np.ndarray[floating, ndim=1, mode='c'] w,
267259

268260
# XtA = np.dot(X.T, R) - beta * w
269261
for i in range(n_features):
270-
XtA[i] = dot(n_samples, &X_data[i * n_samples],
271-
1, R_data, 1) - beta * w[i]
262+
XtA[i] = (dot(n_samples, &X[0, i], 1, &R[0], 1)
263+
- beta * w[i])
272264

273265
if positive:
274-
dual_norm_XtA = max(n_features, XtA_data)
266+
dual_norm_XtA = max(n_features, &XtA[0])
275267
else:
276-
dual_norm_XtA = abs_max(n_features, XtA_data)
268+
dual_norm_XtA = abs_max(n_features, &XtA[0])
277269

278270
# R_norm2 = np.dot(R, R)
279-
R_norm2 = dot(n_samples, R_data, 1, R_data, 1)
271+
R_norm2 = dot(n_samples, &R[0], 1, &R[0], 1)
280272

281273
# w_norm2 = np.dot(w, w)
282-
w_norm2 = dot(n_features, w_data, 1, w_data, 1)
274+
w_norm2 = dot(n_features, &w[0], 1, &w[0], 1)
283275

284276
if (dual_norm_XtA > alpha):
285277
const = alpha / dual_norm_XtA
@@ -289,11 +281,11 @@ def enet_coordinate_descent(np.ndarray[floating, ndim=1, mode='c'] w,
289281
const = 1.0
290282
gap = R_norm2
291283

292-
l1_norm = asum(n_features, w_data, 1)
284+
l1_norm = asum(n_features, &w[0], 1)
293285

294286
# np.dot(R.T, y)
295287
gap += (alpha * l1_norm
296-
- const * dot(n_samples, R_data, 1, y_data, 1)
288+
- const * dot(n_samples, &R[0], 1, &y[0], 1)
297289
+ 0.5 * beta * (1 + const ** 2) * (w_norm2))
298290

299291
if gap < tol:

0 commit comments

Comments
 (0)
0