一元線性迴歸(1):批量梯度下降法、Python代碼實現

機器學習(2)


初見線性迴歸中,說到了:“顯然不是什麼歪瓜裂棗都能符合”今天就來介紹選擇迴歸方程的方法之一:梯度下降法。
在這裏插入圖片描述

一元線性迴歸方程

我們往往會得到形如y = kx + b的各種方程,此時我們就需要性能度量來評價這個方程的優劣:
在這裏插入圖片描述
在這裏,爲了接下來的計算方便,我們選用如下公式:
在這裏插入圖片描述
接下來將分別以y = kx 和 y = kx + b兩種方程介紹批量梯度下降法:

y = kx

梯度下降

在這裏插入圖片描述
現有ABCDE五個點作爲訓練集,以及fgh t pqs七個不同的方程,其斜率分別爲:
1.6 / 1.5 / 1.2/ 1 / 0.8 / 0.5 / 0.4
我們要找到最符合這個訓練集的線性迴歸方程,分別用這7個方程代入前文公式計算結果:(結果記爲E)
在這裏插入圖片描述
得到六組數據(k,E):

k E
1.6 1.980
1.5 1.375
1.2 0.220
1 0.000
0.8 0.220
0.5 1.375
0.4 1.980

我們在座標軸上畫出這七個點:
在這裏插入圖片描述
不難發現,這些點似乎是在一條類似拋物線的曲線上。
在這裏插入圖片描述
並且,當k等於1的時候,E纔有最小值:0。而梯度下降的目的就是,找到這個最小的E ,從而找到最符合訓練集的線性迴歸方程

怎麼讓E最小?——梯度下降法

梯度下降法的原理就是,將每個數據代入公式計算出E,若E過大,則增加/減少k值,再重新將每個數據代入公式計算出E,直到找到一個k,使E的值最小或者在我們允許的範圍內。(白話)

“梯度”是什麼?

我們將E的計算公式對k求偏導數,所得結果就叫做“梯度”
在這裏插入圖片描述
在這裏插入圖片描述

怎麼實現梯度下降?

在這裏插入圖片描述
(我的數學公式軟件不支持α等希臘字母,這裏用a代替了,其實都一樣的。)
其中,k是當前的斜率,E對k的偏導數就是前文提到的“梯度”,而α就是學習率
由此,便能夠實現讓k不斷增大/減小使得程序最終能找到一個最小的或在我們允許的最小範圍內的E。

學習率——α的選定

學習率α是我們自己選定的數,1、0.1 、 0.05等等均可。在設置好α以後,我們並不需要讓程序自己去改動它,因爲每次迭代完成,E對k的偏導都會變小,使k每次減小的幅度都會比上一次要小:

在這裏插入圖片描述
所以,當本次E與上一次E的差值在我們期望的區間裏時,就可以認爲當前的E是一個比較合適的值

這裏要注意的是,α不是一個隨便就能用的數

若α過小

直觀感受如圖:
在這裏插入圖片描述
而體現在程序中,則代表着需要循環特別多次才能找到最小的E:
在這裏插入圖片描述

若α過大

α過大則會無法收斂,如圖:
在這裏插入圖片描述
在程序中則體現爲:
在這裏插入圖片描述
所以,α的取值也是很重要的/doge

代碼實現

我們已經知道了E會不斷減小並且減小的幅度會越來越小。所以,當本次E與上一次E的差值在我們期望的區間裏時,就可以認爲當前的E是一個比較合適的值

x = [1,2,3,4,5]#自定義ABCDE的橫座標
y = [1,2,3,4,5]#自定義ABCDE的縱座標

error = 0.00001 #我們允許的 兩次E的差的範圍
a = 0.01 #學習率
err = 0 #初始化 f(xi)-yi 的值
E = 0 #前文計算性能度量的結果
E1 = 0 #上一次的計算結果
time = 0 #循環次數
m = len(x) #點的數量
k = 0 #k的初值,可以自己設爲其他的數

while True:
    time += 1
    for i in range(m):
        err = k * x[i] - y[i]
        k -= a * err * x[i] / m #令k增大/減小

    for j in range(len(x)):
        E +=(y[j] - k*x[j])**2/2/m #計算E

    if abs(E - E1) < error: #當兩次E的差值在我們允許的範圍內時,退出循環
        break #結束循環,while True語句一定要有結束循環的條件,否則會一直循環下去。

    else:
        print('k:%f err:%f'%(k,E))
        E1 = E
        E = 0 #將E重置

print('Over,k=%f'%(k))
print('%dtimes'%(time))

運行結果:
在這裏插入圖片描述

y = kx + b

y=kx只是衆多情況中較爲簡單的一種,實際的一元線性方程中往往都是有“b”的。
不過,即使增加了一個參數,也沒有影響,我們依然可以用同樣的原理來完成梯度下降。

梯度下降

如今E的計算公式又增加了一個參數b,那麼我們就要分別對k和b進行梯度下降,同樣通過求偏導數的方法來實現:
在這裏插入圖片描述
然後k和b分別減去偏導數:
在這裏插入圖片描述
同樣可以實現梯度下降
因爲現在是由兩個參數共同決定E的值,所以圖像也從二維升到了三維,不過梯度下降的原理並不會改變

代碼實現

x = [1,2,3,4,5]#自定義ABCDE的橫座標
y = [102,103,104,105,106]#自定義ABCDE的縱座標

error = 0.00001 #我們允許的 兩次E的差的範圍
a = 0.01 #學習率
err = 0 #初始化 f(xi)-yi 的值
E = 0 #前文計算性能度量的結果
E1 = 0 #上一次的計算結果
time = 0 #循環次數
m = len(x) #點的數量
k = 0 #k的初值,可以自己設爲其他的數
b = 0 #b的初值,可以自己設爲其他的數

while True:
    time += 1
    for i in range(m):
        err = k * x[i] + b - y[i]
        k -= a * err * x[i] / m #令k增大/減小
        b -= a * err / m #令b增大/減小

    for j in range(len(x)):
        E +=(y[j] - k*x[j] - b)**2/2/m #計算E

    if abs(E - E1) < error: #判斷E值是否符合我們的要求
        break #結束循環,while True語句一定要有結束循環的條件,否則會一直循環下去。

    else:
        print('k:%f b:%f err:%f'%(k,b,E))
        E1 = E
        E = 0 #將E重置

print('Over,k=%f,b=%f'%(k,b))
print('%dtimes'%(time))

運行結果:
在這裏插入圖片描述
如此,一元線性迴歸的批量梯度下降法(BGD)便完成了,除了BGD,還有隨機梯度下降、小批量梯度下降等,這些可能會在以後單獨再寫。

在線性迴歸中,梯度下降是比較常用的方法,此外還有最小二乘法等。這會在之後的幾期中詳細說明,並將二者進行對比。


我是康.,希望做一名能幫助到各位的博主!機器學習系列剛剛開坑,請多指教!
除了機器學習,我偶爾還會做一些單片機/嵌入式、Python相關的文章,歡迎感興趣的小夥伴與我共同學習,一起進步!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章