1

我试图了解线性回归的 LASSO 算法。我已经使用朴素的坐标下降法实现了算法进行优化。但是,我从代码中获得的系数与从 R 中 LASSO 的“glmnet”包获得的系数不匹配。我想了解如何使算法更准确,以便系数与从R. 我认为他们也使用坐标下降。

注意:我生成了一些带有 11 个观察值和 6 个特征(x,x^2,x^3,...,x^6)的玩具数据。最后一列包含从虚拟函数 (e^(-x^2)) 生成的 y 值。我想用 LASSO 来估计这个函数。另外,我随机选择了初始权重向量,多次交叉检查我的结果。

这是我的代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>

int num_dim = 6;
int num_obs = 11;

/*Computes the normalization factor*/
float norm_feature(int j,double arr[][7],int n){

float sum = 0.0;
int i;
for(i=0;i<n;i++){

    sum = sum + pow(arr[i][j],2);
}

return sum;
}


/*Computes the partial sum*/
float approx(int dim,int d_ignore,float weights[],double arr[][7],int 
i){

int flag = 1;
if(d_ignore == -1)
    flag = 0;
int j;
float sum = 0.0;
for(j=0;j<dim;j++){
    if(j != d_ignore)
        sum = sum + weights[j]*arr[i][j];
    else
        continue;
}

return sum;

}

/* Computes rho-j */
float rho_j(double arr[][7],int n,int j,float weights[7]){

 float sum = 0.0;
 int i;
 float partial_sum ;
 for(i=0;i<n;i++){

    partial_sum = approx(num_dim,j,weights,arr,i);
    sum = sum + arr[i][j]*(arr[i][num_dim]-partial_sum);


}




return sum;
}

float intercept(float arr1[7],double arr[][7],int dim) {

int i;
float sum =0.0;
for (i = 0; i < num_obs; i++) {
    sum = sum + pow((arr[i][num_dim]) - approx(num_dim, -1, arr1, arr, 
i), 1);
}

return sum;
}


int main(){

double data[num_obs][7];
int i=0,j=0;
float a = 1.0;

float lambda = 0.1; //Setting lambda

float weights[7]; //weights[6] contains the intercept

srand((unsigned int) time(NULL));


/*Generating the data matrix */
for(i=0;i<11;i++)
    data[i][0] = ((float)rand()/(float)(RAND_MAX)) * a;
for(i=0;i<11;i++)
    for(j=1;j<6;j++)
        data[i][j] = pow(data[i][0],j+1);
for(i=0;i<11;i++)
    data[i][6] = exp(-pow(data[i][0],2)); // the last column in the 
datamatrix contains the y values generated by the dummy function

/*Printing the data matrix */
printf("Data Matrix:\n");
for(i=0;i<11;i++){
    for(j=0;j<7;j++){
        printf("%lf ",data[i][j]);}
    printf("\n");}

printf("\n");

int seed =0;
while(seed<20) {


    //Initializing the weight vector
    for (i = 0; i < 7; i++)
        weights[i] = ((float) rand() / (float) (RAND_MAX)) * a;

    int iter = 500;
    int t = 0;
    int r, l;
    double rho[num_dim];
    for (i = 0; i < 6; i++) {
        rho[i] = rho_j(data, num_obs, r, weights);
    }

    // Intercept initialization
    weights[num_dim] = intercept(weights,data,num_dim);

    printf("Weights initialization: ");
    for (i = 0; i < (num_dim+1); i++)
        printf("%f ", weights[i]);

    printf("\n");

    while (t < iter) {

        for (r = 0; r < num_dim; r++) {


            rho[r] = rho_j(data, num_obs, r, weights);
            //printf("rho %d:%f ",r,rho[r]);
            if (rho[r] < -lambda / 2)
                weights[r] = (rho[r] + lambda / 2) / norm_feature(r, 
data, num_obs);
            else if (rho[r] > lambda / 2)
                weights[r] = (rho[r] - lambda / 2) / norm_feature(r, 
data, num_obs);
            else
                weights[r] = 0;

            weights[num_dim] = intercept(weights, data, num_dim);


        }


       /* printf("Iter(%d): ", t);
        for (l = 0; l < 7; l++)
            printf("%f ", weights[l]);
        printf("\n");*/

        t++;
    }

    //printf("\n");
    printf("Final Weights: ");
    for (i = 0; i < 7; i++)
        printf("%f ", weights[i]);
    printf("\n");
    printf("\n");
seed++;

}

 return 0;

}

伪代码: 伪代码

4

0 回答 0