非参数学习算法之局部加权回归

    前面的线性回归(Linear Regression)是参数学习算法,我们需要拟合出Theta i, 如果特征值出现的太少,如只用一个theta, 可能会出现underfitting(欠拟合),如果特征值选择的过多,会几乎相连每一个点,导致函数不能反映其余数据的真实预测,这就是overfitting(过度拟合)。

    比如,房屋价格的预测,它的中心思想是在对参数进行求解的过程中,每个样本对当前参数值的影响是有不一样的权重的。比如上节中我们的回归方程为(这个地方用矩阵的方法来表示Ɵ表示参数,i表示第i个样本,h为在Ɵ参数下的预测值):

 

我们的目标是让

 

最小,然后求出来Ɵ,再代入h中就可以得到回归方程了。

 

但是如果类似以下的样本,他们的对应图如下:

如果用之前的方法,图中线为求出的回归方程,那么在x的取值和真实差别很大,这个情况叫做欠拟合(overfitting)。那么我们怎么办呢?我们的主要思想就是只对x的附近的一些样本进行选择,根据这些样本得到x附近这些样本所推倒出来的回归方程,那么此时我们得到的回归方程就比较拟合样本数据,得到的效果图如下:

我们解的思路如下,加入一个加权因子:

重新构造新的j(x)

    Exp是以e为低的指数,这个时候可以知道如果x距离样本很远的时候w(i)=0,否则为1,当我们预测一个值的时候就需要我们重新来计算当前的参数Ɵ的值,然后构造回归方程,计算当前的预测值。

    这就是局部加权回归LWR

C++实现代码如下:

#include<iostream>  
using namespace std;  
  
const int Number = 6;  
const int Dimesion = 3;  
const float learningRate=0.001;       
const float errorThr=1; //variance threshold  
const int MAX=1000;     //Max times of iteration  
  
typedef struct Data{  
    float vectorComponent[Dimesion];  
}vectorData;  
  
vectorData x[Number] = {  
   /* {1,1,4}, 
    {1,2,5}, 
    {1,5,1}, 
    {1,4,2},*/  
    {1,1,1},  
    {1,1,3},  
    {1,1,2},  
    {1,2,3},  
    {1,2,1},  
    {1,2,2},  
};  
float y[Number]={2,10,5,13,5,8};  
//lwr(局部线性回归)  
float weightValue(vectorData xi,vectorData x){  
    float weight = 0.0;  
    for(int i=0;i<Dimesion;i++){  
        weight+=pow(xi.vectorComponent[i]-x.vectorComponent[i],2);  
    }  
    float tempWeight = exp(-(weight/(2*36)));  
    if(tempWeight<0.02)  
        tempWeight = 0.0;  
    return tempWeight;  
}  
  
float multiPly(vectorData x1,vectorData x2){  
    float temp = 0.0;  
    for(int i=0;i<Dimesion;i++){  
        temp += x1.vectorComponent[i]*x2.vectorComponent[i];  
    }  
    return temp;  
}  
  
vectorData addVectorData(vectorData x1,vectorData x2){  
    vectorData temp;  
    for(int i=0;i<Dimesion;i++)  
        temp.vectorComponent[i] = x1.vectorComponent[i]+x2.vectorComponent[i];  
    return temp;  
}  
  
vectorData minusVectorData(vectorData x1,vectorData x2){  
    vectorData temp;  
    for(int i=0;i<Dimesion;i++)  
        temp.vectorComponent[i] = x1.vectorComponent[i]-x2.vectorComponent[i];  
    return temp;  
}  
  
vectorData numberMultiVectorData(float para,vectorData x1){  
    vectorData temp;  
    for(int i=0;i<Dimesion;i++)  
        temp.vectorComponent[i] = x1.vectorComponent[i]*para;  
    return temp;  
}  
float costFunction(vectorData parameter[],vectorData inputData[],float inputResultData[],vectorData object){  
    float costValue = 0.0;  
    float tempValue = 0.0;  
    float weightedValue = 0.0;  
    for(int i=0;i<Number;i++){  
        tempValue = 0.0;  
          
        //consider all the parameters although most of them is zero  
        for(int j=0;j<Number;j++)  
            tempValue += multiPly(parameter[j],inputData[i]);  
        costValue += weightValue(inputData[i],object)*pow((inputResultData[i]-tempValue),2);      
    }  
  
    return (costValue/2*4);  
}  
  
  
int LocallyWeightedAgression(vectorData parameter[],vectorData inputData[],float resultData[],vectorData objectVector){  
    float tempValue = 0.0;  
    float errorCost = 0.0;  
    float weightedValue = 0.0;  
    errorCost=costFunction(parameter,inputData,resultData,objectVector);  
    if(errorCost<errorThr)  
        return 1;  
    for(int iteration=0;iteration<MAX;iteration++){  
  
        //stochastic  
        for(int i=0;i<Number;i++){  
            //calculate the h(x)  
            weightedValue = weightValue(inputData[i],objectVector);  
            tempValue=0.0;  
            for(int j=0;j<Number;j++)  
                tempValue+=multiPly(parameter[j],inputData[i]);  
            //update the parameter by stochastic(随机梯度下降)  
            printf("the next parameter is ");  
            for(int ii=0;ii<Number;ii++){  
                parameter[ii] = addVectorData(parameter[ii],numberMultiVectorData(weightedValue*learningRate*(resultData[i]-tempValue),inputData[i]));  
                if(multiPly(parameter[ii],parameter[ii])!=0){  
                    for(int jj=0;jj<Dimesion;jj++){  
                        printf("%f ",parameter[ii].vectorComponent[jj]);  
                    }  
                }  
            }  
            printf("\n");  
            errorCost=costFunction(parameter,inputData,resultData,objectVector);  
            printf("error cost is %f\n",errorCost);  
            if(errorCost<errorThr)  
                break;  
        }//end stochastic one time  
  
    }//end when the iteration becomes MAX   
  
    //calculate the object vector  
    float resultValue = 0.0;  
    for(int i=0;i<Number;i++){  
        resultValue += weightValue(inputData[i],objectVector)*multiPly(parameter[i],objectVector);  
    }  
    printf("result value is %f \n",resultValue);  
    return 1;  
}  
  
int testLWA(){  
    vectorData objectData = {1,1.5,1.5};  
    vectorData localParameter[Number] = {0.0};  
    LocallyWeightedAgression(localParameter,x,y,objectData);  
    return 1;  
}  
int main(){  
  //  DescendAlgorithm(parameter,x,y);  
//  system("pause");  
    //clearParameter(parameter);  
    //Stochastic(parameter,x,y);  
    //float ForTestData[] = {1,10,20};  
    //testData(ForTestData);  
    testLWA();  
    system("pause");  
    return 1;  
}  


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值