機器學習乾貨,一步一步通過Python實現梯度下降的學習

Gradient Descent - 梯度下降

梯度下降法(英語:Gradient descent)是一個一階最優化算法,通常也稱為最速下降法。 要使用梯度下降法找到一個函數的局部極小值,必須向函數上當前點對應梯度(或者是近似梯度)的反方向的規定步長距離點進行迭代搜索。如果相反地向梯度正方向迭代進行搜索,則會接近函數的局部極大值點;這個過程則被稱為梯度上升法

以上是維基百科對梯度下降的解釋。

下面我們來一步一步的學習一遍:

什麼是 梯度下降?

為了方便,我們準備一些數據,並通過Python繪製出圖像。

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖1:數據準備和圖像

如圖1所示,我們準備了一組數據,x軸為體重(Weight)數據,y軸是身高(Height)數據,通過Python中 matplotlib 包,將數據圖像話。

此時,圖像中的點似乎呈現出線性的關係。

問題來了,我們怎麼樣去找到最匹配的直線關係式呢?

有的同學會直接上手 線性迴歸。自然沒錯,但是今天的主角是 梯度下降

那麼,我們一起來用梯度下降的方式來解決這個問題吧!

第一步:假設函數關係 h(x)

既然上述圖像可以被看成是線性關係,我們就可以假設一個線性的函數關係式:h(x);

Predicted Height = Intercept + Slope * Weight

身高的預測值 = y軸截距 + 斜率 * 體重

找到最優化線性關係的問題就轉化成了:找到最優的 y軸截距 和 斜率的問題

用數學的方法來表示如下:

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖2:數學公式

在數據中,真實存在的 y值 和 預測值 h是存在誤差的。這個誤差可以用殘留誤差(Residual Error)來表示。

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖3

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖4:殘留誤差(Residual Error)

在圖4中,數據點(紅球)的y值與直線給出的預測值之間的誤差顯示為藍色的虛線

  • 在統計中,我們將所有誤差的平方和稱為Sum of the Squared Residuals 殘值平方和;
  • 在機器學習中,所有誤差的平方和稱為 損失函數 Loss Function ~ J;

為什麼損失函數里要用距離的平方而不是距離的絕對值?

大家有想過這個問題嗎?誤差是| 預測值_i - 實際值_i | ,那我取誤差絕對值的和的最小值不也可以稱為一個損失函數嘛。

千萬不要以為這個平方是隨隨便便來的。背後是有道理的。

誤差 = 預測值_i - 實際值_i

這個誤差是符合一定概率分佈的。看過我之前的文章介紹海量數據的中心極限定理的朋友,應該知道這個誤差 可以被假定為:

平均值 u = 0,方差為σ 的正態分佈。

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖5:正態分佈

那麼在已知正太分佈的情況下,每一個數據點都會對應一個誤差,而誤差出現的概率,準確的說是Likelihood是可以通過 正態分佈的函數求得的。

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖6:likelihood(概率)

機器學習乾貨,一步一步通過Python實現梯度下降的學習

所有數據點 誤差概率相加

當我們對上述函數取對數可得:

機器學習乾貨,一步一步通過Python實現梯度下降的學習

取對數

最大似然分析,不懂得看我之前的文章。我們要保證 L 最大,只要保證上式 右邊值最大。

式子右邊 第一項和第二項是定值,只要保證第三項最小就可以使 L最大。

由於 u = 0,只要 sum((誤差值_i)^2) 最小就可以啦!

這就是為什麼 損失函數 J要採用平方的數學解釋啦!

目標:找到β0 和 β1使得 損失函數 J 最小!!!

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖7:給出y和x的定義

在Python中,我們首先給β0 和 β1賦值為0,當然可以賦值成任何值。

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖8:梯度下降

為什麼叫梯度下降?

在圖8中,如果我們將每一個β0 和 β1 對應的的 殘值平方和

作圖表示出來,就能發現局部最低點,也就是殘值平方和最小的點。圖8是隻考慮斜率的情況下。如果同時考慮β0 和 β1,則是三維圖像,如圖9.

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖9

第二步:將β0 和 β1 插入相關函數和導數中;

介紹了這麼多梯度下降,接著我們就進入如何使用梯度下降 找到

β0 和 β1 吧!

小範圍的極小值點,我們會想到 函數的一階導數 = 0 對應的 x 值

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖10:一階導數

接下來,我們要定義一個重要的概念 學習效率(Learning Rate): a梯度下降對於 Learning Rate的選擇非常敏感。

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖11:梯度下降

當我們在當前的β0 和 β1 下無法使得 損失函數對於β0 和 β1 的偏微分為0。

損失函數對於β0 和 β1 的偏微分可以理解成β0 和 β1 變化的梯度方向(如圖11)。

那麼,我們在這個梯度下降的方向上給β0 和 β1 做一個微小的移動。

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖12

通過對β0 和 β1 最終找到是的損失函數 J 最小的β0 和 β1。

Python實現梯度下降

機器學習乾貨,一步一步通過Python實現梯度下降的學習

圖13

先從β0 和 β1 都為0開始,圖13中藍線。

機器學習乾貨,一步一步通過Python實現梯度下降的學習

我們運行1000次,並且將直線的演變過程畫出來:

機器學習乾貨,一步一步通過Python實現梯度下降的學習

為了有些同學想自己試試,我把代碼複製如下:

import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
x_data = [1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
y_data = [1, 2, 3, 1, 4, 5, 6, 4, 7, 10, 15, 9]
plt.plot(x_data, y_data, 'ro')
plt.title('Height vs Weight')
plt.xlabel('Weight')
plt.ylabel('Height')

# y = β0 + β1 * x
β0 = 0
β1 = 0
y = lambda x : β0 + β1 * x
def plot_line(y, data_points):
x_values = [i for i in range(int(min(data_points)) - 1, int(max(data_points)) + 2)]
y_values = [y(x) for x in x_values]
plt.plot(x_values, y_values, 'b')

plot_line(y, x_data)
learning_rate = 0.001
def summation(y, x_data, y_data):
slope_β0 = 0
slope_β1 = 0

for i in range(1, len(x_data)):
slope_β0 += y(x_data[i]) - y_data[i]
slope_β1 += (y(x_data[i]) - y_data[i]) * x_data[i]

return slope_β0 / len(x_data), slope_β1 / len(x_data)
for i in range(1000):
slope_β0, slope_β1 = summation(y, x_data, y_data)
β0 = β0 - learning_rate * slope_β0
β1 = β1 - learning_rate * slope_β1
plot_line(y, x_data)
plt.plot(x_data, y_data, 'ro')

總結

以上就是梯度下降的過程,以及如何通過python來實現梯度下降。

最後,我們可以得到我們想要的線性關係函數了。

機器學習乾貨,一步一步通過Python實現梯度下降的學習

y = 0.058 + 1 * x

希望大家喜歡我的文章。

“逃學博士”:理工科直男一枚,在冰天雪地的加拿大攻讀工程博士。閒暇之餘分享點科學知識和學習乾貨。


分享到:


相關文章: