机器学习部分:均值归一化问题

均值归一化(mean normalization)

除了在特征缩放中将特征除以最大值以外,有时候我们也会进行一个称为均值归一化(mean normalization)的工作。

具体做法就是:如果你有一个特征xixi你就用xi−μixi−μi来替换。这样做的目的是为了让你的特征值具有为0的平均值。很明显 我们不需要把这一步应用到x0中,因为x0x0中,因为x0总是等于1的,所以它不可能有为0的的平均值。

但是对其他的特征来说,比如房子的大小取值介于0 ~ 2000,并且假如房子面积的平均值是等于1000的,那么你可以用这个公式

x1=size−10002000x1=size−10002000

类似地,如果你的房子有五间卧室,并且平均一套房子有两间卧室,那么你可以使用这个公式来归一化你的第二个特征x2:

x2=卧室数−25x2=卧室数−25

在这两种情况下你可以算出新的特征x1和x2x1和x2,它们的范围可以在-0.5 ~ +0.5之间,当然这肯定不对,x2的值实际上肯定会大于0.5。更一般的规律是用:

xn−μnSnxn−μnSn, , μn为平均值μn为平均值, , Sn为最大值−最小值Sn为最大值−最小值

来替换原来的特征xnxn。其中定义μn的意思是在训练集中特征xnxn的平均值。而SnSn是该特征值的范围(最大值减去最小值)。

最后直的一提的是:特征缩放其实并不需要太精确,其目的只是为了让梯度下降能够运行得更快一点,让梯度下降收敛所需的循环次数更少一些而已。

#include<bits/stdc++.h>
using namespace std;
#define eps 1e-10


double x[100][100]={{1,1,4},{1,2,5},{1,5,1},{1,4,2}};
double y[100]={19,26,19,20};
double theta[100]={0,0};
int m=4;
int n=2;
double learn_rate=0.1;
double error=100.0;

void p(){

    for(int i=1;i<=n;i++){                      //lie
        double averagex=0.0;
        double Maxx2=x[0][i],Minx2=x[0][i];
        for(int j=0;j<m;j++){
            averagex+=x[j][i];
            Maxx2=max(Maxx2,x[j][i]);
            Minx2=min(Minx2,x[j][i]);
        }
        averagex/=m;
        //cout<<Maxx2<<" "<<Minx2<<" "<<averagex<<endl;
        for(int j=0;j<m;j++){
            x[j][i]=(x[j][i]-averagex)/(Maxx2-Minx2);
        }
    }
}


double get_hx(int index){
    double ans=0.0;
    for(int i=0;i<=n;i++) ans+=x[index][i]*theta[i];
    return ans;
}

int main(){
   double error1=0.0,error2=0.0;
//    cout<<endl<<endl;
//    cout<<"x0"<<" "<<"x1"<<" "<<"x2"<<" "<<"y"<<endl;
//
//    for(int i=0;i<m;i++){
//        for(int j=0;j<=n;j++){
//            cout<<x[i][j]<<"  ";
//        }
//        cout<<y[i];
//        cout<<endl;
//    }
//    cout<<endl<<endl;
    p();

//    cout<<"x0"<<"     "<<"x1"<<"     "<<"x2"<<"   "<<"y"<<endl;
//    for(int i=0;i<m;i++){
//        for(int j=0;j<=n;j++){
//            printf("%.2f  ",x[i][j]);
//        }
//        cout<<y[i];
//        cout<<endl;
//    }
//    cout<<endl<<endl;
//
//
//    return 0;

    while(true){
        for(int i=0;i<m;i++){
            double h_x=get_hx(i);
            for(int j=0;j<=n;j++){
                theta[j]+=(y[i]-h_x)*learn_rate*x[i][j]/m;
            }
        }

        for(int i=0;i<=n;i++) cout<<theta[i]<<" ";
        cout<<endl;

        //找出最小的值,即与上一次的结果相差小于eps
        error1=0.0;
        for(int i=0;i<m;i++){
            error1+=((y[i]-get_hx(i))/m)*(y[i]-get_hx(i))/2;
        }
        if(abs(error1-error2)<eps) break;
        else error2=error1;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wyqwilliam/article/details/81750885