@@ -528,11 +528,11 @@ def sparse_enet_coordinate_descent(floating [:] w,
528
528
@ cython.boundscheck (False )
529
529
@ cython.wraparound (False )
530
530
@ cython.cdivision (True )
531
- def enet_coordinate_descent_gram (double [:] w , double alpha , double beta ,
532
- np.ndarray[double , ndim = 2 , mode = ' c' ] Q,
533
- np.ndarray[double , ndim = 1 , mode = ' c' ] q,
534
- np.ndarray[double , ndim = 1 ] y,
535
- int max_iter , double tol , object rng ,
531
+ def enet_coordinate_descent_gram (floating [:] w , floating alpha , floating beta ,
532
+ np.ndarray[floating , ndim = 2 , mode = ' c' ] Q,
533
+ np.ndarray[floating , ndim = 1 , mode = ' c' ] q,
534
+ np.ndarray[floating , ndim = 1 ] y,
535
+ int max_iter , floating tol , object rng ,
536
536
bint random = 0 , bint positive = 0 ):
537
537
""" Cython version of the coordinate descent algorithm
538
538
for Elastic-Net regression
@@ -546,34 +546,52 @@ def enet_coordinate_descent_gram(double[:] w, double alpha, double beta,
546
546
q = X^T y
547
547
"""
548
548
549
+ # fused types version of BLAS functions
550
+ cdef DOT dot
551
+ cdef AXPY axpy
552
+ cdef ASUM asum
553
+
554
+ if floating is float :
555
+ dtype = np.float32
556
+ dot = sdot
557
+ axpy = saxpy
558
+ asum = sasum
559
+ else :
560
+ dtype = np.float64
561
+ dot = ddot
562
+ axpy = daxpy
563
+ asum = dasum
564
+
549
565
# get the data information into easy vars
550
566
cdef unsigned int n_samples = y.shape[0 ]
551
567
cdef unsigned int n_features = Q.shape[0 ]
552
568
553
569
# initial value "Q w" which will be kept of up to date in the iterations
554
- cdef double [:] H = np.dot(Q, w)
570
+ cdef floating [:] H = np.dot(Q, w)
555
571
556
- cdef double [:] XtA = np.zeros(n_features)
557
- cdef double tmp
558
- cdef double w_ii
559
- cdef double d_w_max
560
- cdef double w_max
561
- cdef double d_w_ii
562
- cdef double gap = tol + 1.0
563
- cdef double d_w_tol = tol
564
- cdef double dual_norm_XtA
572
+ cdef floating[:] XtA = np.zeros(n_features, dtype = dtype)
573
+ cdef floating tmp
574
+ cdef floating w_ii
575
+ cdef floating d_w_max
576
+ cdef floating w_max
577
+ cdef floating d_w_ii
578
+ cdef floating q_dot_w
579
+ cdef floating w_norm2
580
+ cdef floating gap = tol + 1.0
581
+ cdef floating d_w_tol = tol
582
+ cdef floating dual_norm_XtA
565
583
cdef unsigned int ii
566
584
cdef unsigned int n_iter = 0
567
585
cdef unsigned int f_iter
568
586
cdef UINT32_t rand_r_state_seed = rng.randint(0 , RAND_R_MAX)
569
587
cdef UINT32_t* rand_r_state = & rand_r_state_seed
570
588
571
- cdef double y_norm2 = np.dot(y, y)
572
- cdef double * w_ptr = < double * > & w[0 ]
573
- cdef double * Q_ptr = & Q[0 , 0 ]
574
- cdef double * q_ptr = < double * > q.data
575
- cdef double * H_ptr = & H[0 ]
576
- cdef double * XtA_ptr = & XtA[0 ]
589
+ cdef floating y_norm2 = np.dot(y, y)
590
+ cdef floating * w_ptr = < floating * > & w[0 ]
591
+ cdef floating * Q_ptr = & Q[0 , 0 ]
592
+ cdef floating * q_ptr = < floating * > q.data
593
+ cdef floating * H_ptr = & H[0 ]
594
+ cdef floating * XtA_ptr = & XtA[0 ]
577
595
tol = tol * y_norm2
578
596
579
597
if alpha == 0 :
@@ -597,8 +615,8 @@ def enet_coordinate_descent_gram(double[:] w, double alpha, double beta,
597
615
598
616
if w_ii != 0.0 :
599
617
# H -= w_ii * Q[ii]
600
- daxpy (n_features, - w_ii, Q_ptr + ii * n_features, 1 ,
601
- H_ptr, 1 )
618
+ axpy (n_features, - w_ii, Q_ptr + ii * n_features, 1 ,
619
+ H_ptr, 1 )
602
620
603
621
tmp = q[ii] - H[ii]
604
622
@@ -610,8 +628,8 @@ def enet_coordinate_descent_gram(double[:] w, double alpha, double beta,
610
628
611
629
if w[ii] != 0.0 :
612
630
# H += w[ii] * Q[ii] # Update H = X.T X w
613
- daxpy (n_features, w[ii], Q_ptr + ii * n_features, 1 ,
614
- H_ptr, 1 )
631
+ axpy (n_features, w[ii], Q_ptr + ii * n_features, 1 ,
632
+ H_ptr, 1 )
615
633
616
634
# update the maximum absolute coefficient update
617
635
d_w_ii = fabs(w[ii] - w_ii)
@@ -627,7 +645,7 @@ def enet_coordinate_descent_gram(double[:] w, double alpha, double beta,
627
645
# criterion
628
646
629
647
# q_dot_w = np.dot(w, q)
630
- q_dot_w = ddot (n_features, w_ptr, 1 , q_ptr, 1 )
648
+ q_dot_w = dot (n_features, w_ptr, 1 , q_ptr, 1 )
631
649
632
650
for ii in range (n_features):
633
651
XtA[ii] = q[ii] - H[ii] - beta * w[ii]
@@ -643,7 +661,7 @@ def enet_coordinate_descent_gram(double[:] w, double alpha, double beta,
643
661
R_norm2 = y_norm2 + tmp - 2.0 * q_dot_w
644
662
645
663
# w_norm2 = np.dot(w, w)
646
- w_norm2 = ddot (n_features, & w[0 ], 1 , & w[0 ], 1 )
664
+ w_norm2 = dot (n_features, & w[0 ], 1 , & w[0 ], 1 )
647
665
648
666
if (dual_norm_XtA > alpha):
649
667
const = alpha / dual_norm_XtA
@@ -654,7 +672,7 @@ def enet_coordinate_descent_gram(double[:] w, double alpha, double beta,
654
672
gap = R_norm2
655
673
656
674
# The call to dasum is equivalent to the L1 norm of w
657
- gap += (alpha * dasum (n_features, & w[0 ], 1 ) -
675
+ gap += (alpha * asum (n_features, & w[0 ], 1 ) -
658
676
const * y_norm2 + const * q_dot_w +
659
677
0.5 * beta * (1 + const ** 2 ) * w_norm2)
660
678
0 commit comments