最小二乘法是一種通過數(shù)值對曲線函數(shù)擬合的一種統(tǒng)計學方法,這里的最小是擬合誤差達到最小。我們可以根據(jù)擬合后的函數(shù)可以做一些預測或預報。它在數(shù)字信號處理、機器學習等領(lǐng)域廣泛的應(yīng)用。本文W君將和大家一起學習如何通過最小二乘法進行線性回歸。
我們來用一個最簡單的一元線性回歸模型的例子來理解最小二乘法。在生活中,我們知道人的身高和腳的大小是成正比的,這里我們假設(shè)身高和腳的大小是成一元線性關(guān)系的。那么我們怎么去建立這樣一個一元線性模型呢?我們從人群中隨機抽取幾個身高不同的人,分別測量他們的身高和腳長,假如下面的表格就是我們的統(tǒng)計數(shù)據(jù)。
將他們在坐標系上顯示,如下圖,可以看到這些數(shù)據(jù)是趨近于一條直線的。
那么如何擬合這個直線呢?早在1805年勒讓德就提出了最小二乘法。其方法就是根據(jù)已知的m個樣本特征值,列出一個目標函數(shù)E,并求其最優(yōu)解,從而使得實際值與預估值達到最小。這里的目標函數(shù)也叫損失函數(shù),它是可以表征回歸模型中估測值和真實值的不一致程度,其值越小越接近真實情況。它是由若干個預測值和真實之差的平方和構(gòu)成,所以我們稱之為最小二乘。
樣本特征值:
目標函數(shù):
這里我們假設(shè)擬合函數(shù)為:
這時我們的目標函數(shù)就為:
然后,通過最小二乘法使目標函數(shù)最小,求出這時的θ0和θ1的值,就可以得出擬合曲線了。
那么,問題來了?怎樣讓目標函數(shù)最小,求出θ0和θ1這兩個參數(shù)呢? 這里我們有兩種方法,對其進行求解,分別是代數(shù)法和矩陣法。
代數(shù)法
先高能預警一下,代數(shù)法公式看上去比較復雜,讓人看得不免有些枯燥,W君覺得這里還是有必要列一下,大家只要理解了就好。代數(shù)法的解法就是先分別對θ0和θ1分別求偏導數(shù),然后分別使導數(shù)為0,得到一個關(guān)于θ0和θ1的方程組,最后解方程組即可。
損失函數(shù)對θ0求導,得到方程:
損失函數(shù)對θ1求導,得到方程:
根據(jù)上面兩個方程組成一個二元一次方程組,求解θ0和θ1:
類似的,對于n元一次方程也需要對每個參數(shù)進行求導,得出一個n元一次方程組,并求解出這n個θ參數(shù)。
看到這里一大堆公式是不是已經(jīng)頭大了?確實W君也覺得讓人頭大,那么,還有沒有更加簡潔的方法呀?這就是下面我們要學習的矩陣法了。
矩陣法
矩陣解法要比代數(shù)法簡潔很多,也是大家比較習慣使用的方法。這里我們用n元一次函數(shù)作為擬合函數(shù)來求導矩陣法的公式,推導過程同樣是痛苦的,但是大家最后記住公式就好,我們來看公式推導過程。
擬合函數(shù):
其矩陣表示如下:
所以,損失函數(shù):
在利用矩陣的跡公式得出:
令上面的公式為0,得出:
(敲黑板,這個公式我們一定要記住!!!)
這里的θ就是我們需要求的參數(shù),不過這里的是向量形式。
C++實現(xiàn)矩陣法
下面我們用矩陣法求解本文開頭的例子,我們使用表格中的身高和腳長作為樣本數(shù)據(jù),再利用開源庫Eigen來實現(xiàn)矩陣運算。關(guān)于Eigen的安裝和使用可以參考W君的這篇文章《快速入門矩陣運算——開源庫Eigen》。這里用到了轉(zhuǎn)置函數(shù)transpose()和求逆函數(shù)inverse()。
我們來看一下求解代碼,代碼中利用了矩陣法求θ向量的公式。
#include <iostream>
#include "eigen_3_3_7/Eigen/Eigen"
int main()
{
Eigen::MatrixXf X(8,2);
Eigen::VectorXf Y(8);
Eigen::VectorXf result;
X << 155, 1,
159, 1,
163, 1,
169, 1,
175, 1,
179, 1,
184, 1,
188, 1;
Y << 18.1, 19.7, 21.2, 24.2, 26.1, 27.8, 30.3, 32.4;
result = (X.transpose()*X).inverse() * X.transpose() * Y;
std::cout << "------ X ------" << std::endl << X << std::endl;
std::cout << "------ Y ------" << std::endl << Y << std::endl;
std::cout << "------ result ------" << std::endl << result << std::endl;
}
程序計算結(jié)果如下,θ向量兩個參數(shù)分別為0.425896和-48.0662。所以,我們擬合出的曲線就是 y=0.425896x - 48.0062了 ,是不是很簡單快捷?
最后,我們可以用Excel驗算下我們的結(jié)果,如下圖,擬合出的曲線和我們代碼求出來的是一致的。
關(guān)于如何使用Excel進行曲線擬合,W君后續(xù)計劃將會在Excel技巧里再為大家詳細介紹,敬請關(guān)注。