forked from MartinezTorres/uSnippets
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLassoShooting.hpp
61 lines (46 loc) · 1.4 KB
/
LassoShooting.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
////////////////////////////////////////////////////////////////////////
// minimal Lasso-Shooting code
//
// Manuel Martinez ([email protected])
//
// license: LGPLv3
//
// GCC-FLAGS: -Ofast -std=c++0x `pkg-config opencv --cflags` `pkg-config opencv --libs`
// Minimizes: ||Xb-Y|| + lambda |b|_1
#pragma once
#include <opencv/cv.h>
static cv::Mat1d LassoShooting(cv::Mat1d X, cv::Mat1d Y, double lambda, int minNonZero = 0, int maxIter = 10000, double epsilon = 1e-4) {
cv::Mat1d XTX = 2*X.t()*X;
cv::Mat1d XTY = 2*X.t()*Y;
double *pXTY = &XTY(0);
double *pXTX = &XTX(0);
cv::Mat1d B = cv::Mat1d(X.cols,1,0.);
double *pB = &B(0);
cv::Mat1d XPRE(X.cols,1,0.);
double *pXPRE = &XPRE(0);
int nonZero = 0;
for (double l = 1e10*lambda; l>=lambda or nonZero<minNonZero; l/=10) {
for (int iter=0; iter<maxIter; iter++) {
double update = 0;
for (int j=0; j<X.cols; j++) {
double oldB = pB[j];
double sj = pXPRE[j] - pXTY[j] - pXTX[j*XTX.cols+j]*pB[j];
if (sj>l) {
pB[j] = (l-sj)/pXTX[j*XTX.cols+j];
} else if (sj<-l) {
pB[j] =-(l+sj)/pXTX[j*XTX.cols+j];
} else {
pB[j] = 0;
}
if (oldB!=pB[j])
for (int k=0; k<X.cols; k++)
pXPRE[k] += pXTX[j*XTX.cols+k]*(pB[j]-oldB);
update += std::abs(oldB-pB[j]);
}
if (update<epsilon) break;
}
nonZero = 0;
for (int i=0; i<B.rows; i++) if (B(i)!=0.) nonZero++;
}
return B;
}