zoukankan      html  css  js  c++  java
  • 最小二乘法

    1、什么是最小二乘思想?
    简单地说,最小二乘的思想就是要使得观测点和估计点的距离的平方和达到最小.这里的“二乘”指的是用平方来度量观测点与估计点的远近(在古汉语中“平方”称为“二乘”),“最小”指的是参数的估计值要保证各个观测点与估计点的距离的平方和达到最小。从这个上也可以看出,最小二乘也可用于拟合数据模型。

    这当中涉及到如下问题:
    ①观测点和距离点的距离:这个距离也被称为误差。既然要估计,总希望找到最好的估计值,那么误差越小越好。
    ②为什么是距离的平方和:距离的平方和也就是误差的平方和,既然误差越小越好,那是否可以用绝对值来代替?;楼主觉得用绝对值代替的这个想法是可以的,只是在之后的运算求值时处理比较复杂。(楼主隐约记得取绝对值最小的方法好像是最小一乘法)
    ③为什么平方求解方便呢?那就要从公式讲起了(楼主说好不上复杂公式推导的,好吧,这里就简单描述一下吧……)
    设拟合直线是 1.jpg ,距离(或误差)为 2.jpg ,那么最小二乘的思想就是让等式3.jpg 具有最小值。那么这就需要做求偏导了。(这也就是为什么最小二乘有个要求就是数据需要具有二阶矩),大致推导过程如下:
    4.jpg 
    整理后对方程组求解
    5.jpg 
    最终解得 6.jpg 

    c++代码实现

     1 /*
     2 最小二乘法C++实现
     3 参数1为输入文件
     4 输入 : x
     5 输出: 预测的y  
     6 */
     7 #include<iostream>
     8 #include<fstream>
     9 #include<vector>
    10 using namespace std;
    11 
    12 class LeastSquare{
    13     double a, b;
    14 public:
    15     LeastSquare(const vector<double>& x, const vector<double>& y)
    16     {
    17         double t1=0, t2=0, t3=0, t4=0;
    18         for(int i=0; i<x.size(); ++i)
    19         {
    20             t1 += x[i]*x[i];
    21             t2 += x[i];
    22             t3 += x[i]*y[i];
    23             t4 += y[i];
    24         }
    25         a = (t3*x.size() - t2*t4) / (t1*x.size() - t2*t2);  // 求得β1 
    26         b = (t1*t4 - t2*t3) / (t1*x.size() - t2*t2);        // 求得β2
    27     }
    28 
    29     double getY(const double x) const
    30     {
    31         return a*x + b;
    32     }
    33 
    34     void print() const
    35     {
    36         cout<<"y = "<<a<<"x + "<<b<<"
    ";
    37     }
    38 
    39 };
    40 
    41 int main(int argc, char *argv[])
    42 {
    43     if(argc != 2)
    44     {
    45         cout<<"Usage: DataFile.txt"<<endl;
    46         return -1;
    47     }
    48     else
    49     {
    50         vector<double> x;
    51         ifstream in(argv[1]);
    52         for(double d; in>>d; )
    53             x.push_back(d);
    54         int sz = x.size();
    55         vector<double> y(x.begin()+sz/2, x.end());
    56         x.resize(sz/2);
    57         LeastSquare ls(x, y);
    58         ls.print();
    59         
    60         cout<<"Input x:
    ";
    61         double x0;
    62         while(cin>>x0)
    63         {
    64             cout<<"y = "<<ls.getY(x0)<<endl;
    65             cout<<"Input x:
    ";
    66         }
    67     }
    68 }

    原理探究

    数据拟合中,为什么要让模型的预测数据与实际数据之差的平方而不是绝对值和最小来优化模型参数?

    这个问题已经有人回答了,见链接(http://blog.sciencenet.cn/blog-430956-621997.html

    个人感觉这个解释是非常有意思的。特别是里面的假设:所有偏离f(x)的点都是有噪音的。

    一个点偏离越远说明噪音越大,这个点出现的概率也越小。那么偏离程度x与出现概率f(x)满足什么关系呢?——正态分布。

    000149653.png

    已知N个点(用D来表示),求直线(用h来表示)出现的概率就可以表示为:P(h|D)

    根据贝叶斯定理:P(h|D)=P(D|h)*P(h)/P(D)即P(h|D)∝P(D|h)*P(h) (∝表示“正比于”)

    这就是一个生成模型了——由直线h生成点集D。

    我们再作一个假设:h生成D中的每一个点都是独立的(如果了解贝叶斯文本分类的话,这里就很好理解了),那么P(D|h)=p(d1|h)*p(d2|h)…

    结合前面正态分布,我们可以写出这样的式子:p(di|h)∝ exp(-(ΔYi)^2)

    那么P(D|h)∝EXP[-(ΔY1)^2]* EXP[-(ΔY2)^2] * EXP[-(ΔY3)^2] * ..

    又因为:ea*eb*ec=ea+b+c

    所以p(D|h)∝ EXP{-[(ΔY1)^2 +(ΔY2)^2 + (ΔY3)^2 + ..]}

    我们知道f(x)=ex的分布图像为:

    000207654.jpg

    因为e的指数永远小于0,所以,想要p(D|h)最大,就必须使[(ΔY1)^2 + (ΔY2)^2 + (ΔY3)^2 + ..]无限接近于0,即:最大化p(D|h)就是要最小化[(ΔY1)^2 + (ΔY2)^2 + (ΔY3)^2 + ..]

    到此,最小二乘法的原理得到了诠释。

    参考:http://www.cnblogs.com/iamccme/archive/2013/05/15/3080737.html

    http://sbp810050504.blog.51cto.com/2799422/1269572

    http://bbs.pinggu.org/thread-3041002-1-1.html

  • 相关阅读:
    iptables之NAT端口转发设置
    Windows server 2008 R2远程桌面3389端口号修改
    Nginx启动错误:error while loading shared libraries: libpcre.so.1
    sp_change_users_login 'Update_One', '用户名', '登录名';
    Sqlserver 数据库定时自动备份
    ES DSL 基础查询语法学习笔记
    kafka命令使用
    kafka集群中常见错误的解决方法:kafka.common.KafkaException: Should not set log end offset on partition
    快速排序法(双冒泡排序法)
    运算符
  • 原文地址:https://www.cnblogs.com/zl1991/p/7515273.html
Copyright © 2011-2022 走看看