起源
起源:最小二乘法源於天文學和大地測量學領域。因為這兩個領域對精度的高要求而被發明。
1801年,意大利天文學家朱塞普·皮亞齊發現了第一顆小行星谷神星。進行了40天的跟蹤觀測后,但由於谷神星運行到太陽背后,失去了具體位置信息。隨后全世界的科學家利用皮亞齊的觀測數據開始尋找谷神星,但是根據大多數人計算的結果來尋找谷神星都沒有結果。時年24歲的高斯也計算了谷神星的軌道。奧地利天文學家海因里希·奧伯斯根據高斯計算出來的軌道重新發現了谷神星。高斯使用的最小二乘法的方法發表於1809年他的著作《天體運動論》中,這個高斯正是著名數學家 卡爾·弗里德里希·高斯 ,沒錯就是我們大學數學認識的那個高斯。

機器學習本質其實就是求最優解的過程,最小二乘法是回歸算法中求最優解的方法之一,還有一個是梯度下降法,以后會講~。
思考
我們在正式講最小二乘法之前,讀者大大們可以想下下面這個問題臨近中秋,小明想要自己做月餅,現在已知五種規格月餅所需的面粉重量如下:
| 月餅重量(g) | 面粉重量(g) |
|---|---|
| 30 | 20 |
| 100 | 81 |
| 80 | 110 |
| 190 | 90 |
| 220 | 180 |
現在小明想做規格為140g的月餅,請問他需要多少克月餅現在讀者大大們根據平時經驗,可以思考下怎么求。九年義務教育讓我看見這種題目就條件反射列方程求未知數,不知道讀者大大們是不是也是這樣~
原理
我們從另一個角度來看這個問題我們將這5個月餅用坐標系標出來,如下圖 然后我們先用畫出一條接近這5個點的線,假設線性關系為

是不是只要我們找出一條最接近這5個點的線就可以了,這樣算出來的值是最接近真實值的。

由圖可以得出,需要這條線跟這個5個點的誤差最小, 每個點跟線的誤差如下所示

因為誤差是長度,所以要算絕對值,計算起來不方便,用平方來替代

最后將所有誤差值累加得出

最小二乘法呼之欲出,這就是最小二乘法的原理了,即讓誤差的平方總和盡可能小。從求一條最接近這五個點的線的問題轉化成求最小化誤差的問題。

求解
那么怎么求呢,繼續以上面的為例子。這是一個二次函數。總誤差的平方:

根據多元微積分,當

這個時候 ϵ 取得最小值,求的a,b的解為

a,b求出后,這條最接近的線也就出來了

進一步現在假設這條線是 二次函數,結果怎樣

我們可以選擇不同的 f(x),根據最小二乘法得出不一樣的擬合函數。不過選擇f(x)還是不能太隨意,不然要么不准,要么容易過擬合。代碼實現整個思路如下

目標函數:代入生成的x,生成對應的y
def real_func(x):
return np.sin(2*np.pi*x)
隨機生成10個x進行實驗:
x = np.linspace(0, 1, 10)
構造多項式擬合函數:
#多項式
def fit_func(p,x):
"""
eg:p = np.poly1d([2,3,5,7])
print(p)==>>2x3 + 3x2 + 5x + 7
""" f = np.poly1d(p) return f(x)
計算誤差:
#殘差
def residuals_func(p, x, y):
ret = fit_func(p, x) - y return ret
leastsq 是 scipy 庫 進行最小二乘法計算的函數,也就是通過誤差函數以及數據點進行我們前面講的對參數進行求導操作,最后得出我們擬合出來的函數。
def fitting(M=0):
"""
n 為 多項式的次數
"""
# 隨機初始化多項式參數
#numpy.random.rand(d0)的隨機樣本位於[0, 1)之間。d0表示返回多少個
p_init = np.random.rand(M+1) #生成M+1個隨機數的列表
# 最小二乘法
p_lsq = leastsq(residuals_func, p_init, args=(x, y)) # 三個參數:誤差函數、函數參數列表、數據點
print('Fitting Parameters:', p_lsq[0]) # 可視化 plt.plot(x_points, real_func(x_points), label='real') plt.plot(x_points, fit_func(p_lsq[0], x_points), label='fitted curve') plt.plot(x, y, 'bo', label='noise') plt.legend() return p_lsq # M=0 p_lsq = fitting(M=0)

我們從一次函數依次增加項式,找到最合適的擬合曲線。

到9次的時候,已經完全擬合這些點了 。

總結
我們可以看出,最小二乘法的原理其實非常簡單,運用起來也簡潔,應用廣泛。但是它也有一定的局限性,比如如果擬合函數不是線性的,就無法用最小二乘法了。還有一點,本文講的最小二乘法是最簡潔的,但是它對噪聲的容忍度很低,容易造成過擬合,所以還需要加上正則化,這個有興趣的讀者可以了解下。最小二乘法運用誤差角度求最優解的思路是我們機器學習中一個很經典也很常用的思維方向之一,為學習機器學習打下一個好基礎。這也是把它放在我們的機器學習系列最開始的原因。
ps:需要完整代碼,關注公眾號,回復‘最小二乘法’獲得~
本文首發微信公眾號“哈爾的數據城堡”.
