一.背景
5月9號到北大去聽hulu的講座《推薦系統和計算廣告在視頻行業應用》,想到能見到傳說中的項亮大神,特地拿了本《推薦系統實踐》求簽名。講座開始,主講人先問了下哪些同學有機器學習的背景,我恬不知恥的毅然舉手,真是慚愧。后來主講人在講座中提到了最小二乘法,說這個是機器學習最基礎的算法。神馬,最基礎,我咋不知道呢! 看來以后還是要對自己有清晰認識。
回來趕緊上百度,搜了下什么是最小二乘法。
先看下百度百科的介紹:最小二乘法(又稱最小平方法)是一種數學優化技術。它通過最小化誤差的平方和尋找數據的最佳函數匹配。利用最小二乘法可以簡便地求得未知的數據,並使得這些求得的數據與實際數據之間誤差的平方和為最小。最小二乘法還可用於曲線擬合。其他一些優化問題也可通過最小化能量或最大化熵用最小二乘法來表達。
通過這段描述可以看出來,最小二乘法也是一種優化方法,求得目標函數的最優值。並且也可以用於曲線擬合,來解決回歸問題。難怪《統計學習方法》中提到,回歸學習最常用的損失函數是平方損失函數,在此情況下,回歸問題可以著名的最小二乘法來解決。看來最小二乘法果然是機器學習領域做有名和有效的算法之一。
二. 最小二乘法
我們以最簡單的一元線性模型來解釋最小二乘法。什么是一元線性模型呢? 監督學習中,如果預測的變量是離散的,我們稱其為分類(如決策樹,支持向量機等),如果預測的變量是連續的,我們稱其為回歸。回歸分析中,如果只包括一個自變量和一個因變量,且二者的關系可用一條直線近似表示,這種回歸分析稱為一元線性回歸分析。如果回歸分析中包括兩個或兩個以上的自變量,且因變量和自變量之間是線性關系,則稱為多元線性回歸分析。對於二維空間線性是一條直線;對於三維空間線性是一個平面,對於多維空間線性是一個超平面...
對於一元線性回歸模型, 假設從總體中獲取了n組觀察值(X1,Y1),(X2,Y2), …,(Xn,Yn)。對於平面中的這n個點,可以使用無數條曲線來擬合。要求樣本回歸函數盡可能好地擬合這組值。綜合起來看,這條直線處於樣本數據的中心位置最合理。 選擇最佳擬合曲線的標准可以確定為:使總的擬合誤差(即總殘差)達到最小。有以下三個標准可以選擇:
(1)用“殘差和最小”確定直線位置是一個途徑。但很快發現計算“殘差和”存在相互抵消的問題。
(2)用“殘差絕對值和最小”確定直線位置也是一個途徑。但絕對值的計算比較麻煩。
(3)最小二乘法的原則是以“殘差平方和最小”確定直線位置。用最小二乘法除了計算比較方便外,得到的估計量還具有優良特性。這種方法對異常值非常敏感。
最常用的是普通最小二乘法( Ordinary Least Square,OLS):所選擇的回歸模型應該使所有觀察值的殘差平方和達到最小。(Q為殘差平方和)- 即采用平方損失函數。
樣本回歸模型:
其中ei為樣本(Xi, Yi)的誤差
平方損失函數:
則通過Q最小確定這條直線,即確定,以
為變量,把它們看作是Q的函數,就變成了一個求極值的問題,可以通過求導數得到。求Q對兩個待估參數的偏導數:
根據數學知識我們知道,函數的極值點為偏導為0的點。
解得:
這就是最小二乘法的解法,就是求得平方損失函數的極值點。
三. 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<<"\n"; 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:\n"; 61 double x0; 62 while(cin>>x0) 63 { 64 cout<<"y = "<<ls.getY(x0)<<endl; 65 cout<<"Input x:\n"; 66 } 67 } 68 }
四. 最小二乘法與梯度下降法
最小二乘法跟梯度下降法都是通過求導來求損失函數的最小值,那它們有什么區別呢。
相同
1.本質相同:兩種方法都是在給定已知數據(independent & dependent variables)的前提下對dependent variables算出出一個一般性的估值函數。然后對給定新數據的dependent variables進行估算。
2.目標相同:都是在已知數據的框架內,使得估算值與實際值的總平方差盡量更小(事實上未必一定要使用平方),估算值與實際值的總平方差的公式為:
其中為第i組數據的independent variable,
為第i組數據的dependent variable,
為系數向量。
不同
1.實現方法和結果不同:最小二乘法是直接對求導找出全局最小,是非迭代法。而梯度下降法是一種迭代法,先給定一個
,然后向
下降最快的方向調整
,在若干次迭代之后找到局部最小。梯度下降法的缺點是到最小點的時候收斂速度變慢,並且對初始點的選擇極為敏感,其改進大多是在這兩方面下功夫。
參考: http://blog.csdn.net/qll125596718/article/details/8248249