昨天終於用 Python 實作出了梯度下降法!看起來好像很簡單,但實際上並沒有那麼簡單喔。今天就拋出一些我自己也沒有答案的問題,讓大家了解實際上在操作梯度下降法時會遇到的問題
其實決大部分的時候我們是不知道目標點在哪裡的。昨天示範的是「簡單線性迴歸」的例子,因此可以求解,但若遇到的是非線性的狀況就沒有這麼簡單了。
在昨天的例子當中,假如我們不知道目標點在哪裡,但是我們還是必須先選擇一個起始點,這時候在一個二維平面上,就會有無數多個可能的起始點。如果選到不好的起始點的話,結果可能就不如我們預期。
在 learning rate = 0.00005, iteration = 10000 的情況下,選擇 a = 0
, b = 0
當作起始點,結果如下
但如果選擇 a = 0
, b = 15
當作起始點,結果會發現我們離目標點好像還有一段距離
等等,但是我們不是不知道目標點在哪裡嗎?這時候我們可以用訓練資料來,帶入下面的式子
來計算出 Loss function 值。計算方式如下
error = 0
for n in range(len(x_test_data)):
error = error + (y_test_data[n] - b - a*x_test_data[n])**2
這時候就會發現,從 a = 0
, b = 0
出發得到的 error 為
1879.6125244812688
從 a = 0
, b = 15
出發得到的 error 為
1886.094750642195
也就是說,在 learning rate & iteration 固定的情況下,從 a = 0
, b = 0
出發的結果,會比從 a = 0
, b = 15
出發的結果還要來得好
假設我們就從 a = 0
, b = 15
出發,如果走更多步,會不會讓測試資料算出來的 error 更小,讓我們更接近目標點呢?
答案是會的。最原本我們只走 10000 步,如果我們多到 100000,error 就會變小成為
1879.5818815331004
如果我們多到 1000000,error 就會變成
1879.5818815331013
好像不會變得更小了,但同時程式執行的時間變得更長了(是那種人體有感的變長)。看來要透過走更多步來到達目標點好像不是個好辦法。
如果走太多步會浪費資源(時間),那不如讓 learning rate 變大一點,也就是每一步走得更大步,這樣一來我們就可以更快走到目標點了!
一樣從 a = 0
, b = 0
出發,假設我的目標是要讓 iteration 次數減少至 1000(原本的十分之一),如果 learning rate 還是跟原本一樣是 0.00005
,會發現結果好像還是差了一點距離
error 為
1880.8209020679415
如果 learning rate 放大 10 倍變成 0.0005
,結果好像更接近了
error 為
1879.6124080433851
接下來讓我們打開推進器,把 learning rate 再放大 10 倍變成 0.005
... 然後就會發現結果炸裂了,永遠走不到目標點的附近,會發現圖片上的線條在亂噴
還記得我們在 [Day 9] 梯度下降法會遇到的問題 談到的 overshotting 的問題嗎?因為走的步伐太大,很容易就跨過目標點(最低點),結果就是像下面的左圖一樣,在山谷間來回震盪。
今天簡單的提到了三個會影響到梯度下降法結果的問題:
明天我們將繼續深入探討梯度下降法喔。明天見 :)