之所以叫盒飯版算法,是希望能在最短時間講一些沒那么正式的東西。
在機(jī)器學(xué)習(xí)里,我們通常用優(yōu)化方法來計算模型的未知參數(shù),隨機(jī)梯度下降方法(SGD)是其中一種優(yōu)化方法。
下面這篇博客介紹了如何用SGD來獲得一個線性模型。
https://machinelearningmastery.com/implement-linear-regression-stochastic-gradient-descent-scratch-python/
我截取其中一段來講。這篇文章講的SGD只能算是標(biāo)準(zhǔn)型,如果想了解更專業(yè)的,可以參考R語言的工具包sgd:
https://github.com/airoldilab/sgd/blob/master/README.md

SGD 有兩個參數(shù)(對標(biāo)準(zhǔn)型而言):學(xué)習(xí)率(Learning Rate)和迭代次數(shù)(Epochs)。計算參數(shù)是一個比較費(fèi)時的工作,有點(diǎn)像學(xué)英語,一天肯定學(xué)不會,每天只能學(xué)會一點(diǎn),這個大概就是學(xué)習(xí)率。既然忘了,就得反復(fù)學(xué),這就是迭代,有些人聰明,學(xué)一兩年就學(xué)會了,有些人差一點(diǎn),像我學(xué)了幾十年,還沒有訓(xùn)練出一個好的語言模型。

上圖說,SGD有三個循環(huán)過程:1、把所有的迭代都循環(huán)一遍;2、每次迭代中把所有的訓(xùn)練數(shù)據(jù)循環(huán)一遍;3、每次用到一條訓(xùn)練數(shù)據(jù)時把所有的參數(shù)都更新一遍。

參數(shù)更新依靠誤差。誤差從哪里來?今天想學(xué)100個單詞,結(jié)果只學(xué)會了50個,誤差就是沒學(xué)會的那50個,第二天想把沒學(xué)會的50個單詞學(xué)會,結(jié)果記下了10個,誤差縮小到40個,然后是第三天、第四天,運(yùn)氣好的時候,10天記下100個單詞。像我把單詞記在大腦內(nèi)存里,睡前總是忘了存盤,第二天一早發(fā)現(xiàn)大腦內(nèi)存清空了,昨天記的單詞就都忘記了,偶爾我還是會存盤的,一年半載之后,還是會記住這100個單詞的。

每次參數(shù)更新除了和誤差有關(guān)之外,還和學(xué)習(xí)率有關(guān),而且每個參數(shù)是基于特定數(shù)據(jù)進(jìn)行更新的,例如這里b1這個參數(shù)的更新基于某一輸入變量x1,因?yàn)槭蔷€性模型,所以只有x1,如果是非線性模型,就可能是x1、x2...了。

還有一個特殊參數(shù),叫做截距或偏差(bias)。這個bias的更新和其他參數(shù)的更新類似,只是不依賴任何輸入變量。從這個角度講,這個bias和機(jī)器學(xué)習(xí)里的偏差-方差分解(bias-variance decomposition)是不同的,大家學(xué)習(xí)的時候,不要混淆了。
有了循環(huán)框架和參數(shù)更新的策略,我們就能得到下面 SGD的程序。

這個程序得在python3上運(yùn)行,如果在python2運(yùn)行的話,第一個迭代結(jié)束后,程序就結(jié)束了。我寫了一個類似的R語言腳本,運(yùn)行后遇到了同樣的問題。折騰了很久之后,我問了阿澤,他看了一眼說:用py3。python這事解決了,但是R那個坑還在。
R語言腳本如下所示:

問題應(yīng)該出在方框中的那三層循環(huán)里,稍微改了一下之后,還是把這個坑填了,只是走的路有點(diǎn)長,全局變量和局部變量,總是要在腦子里轉(zhuǎn)幾圈才行。

這就是今天的盒飯版算法之隨機(jī)梯度下降方法(SGD)。大家可以關(guān)注下大洋彼岸的這些博客,可以學(xué)英文,學(xué)算法,學(xué)編程,還可以找出一些小錯誤,例如這篇博客的程序更像是梯度下降方法,“隨機(jī)”那部分并沒有體現(xiàn),還有其他小問題,不過用來展示原理的話,這些可以接受。
要不你們也贊賞一下我吧,看能不能湊足一個飯盒。