零基礎入門深度學習(2) - 線性單元和梯度降低

往期回顧

在上一篇文章中,咱們已經學會了編寫一個簡單的感知器,並用它來實現一個線性分類器。你應該還記得用來訓練感知器的『感知器規則』。然而,咱們並無關心這個規則是怎麼獲得的。本文經過介紹另一種『感知器』,也就是『線性單元』,來講明關於機器學習一些基本的概念,好比模型、目標函數、優化算法等等。這些概念對於全部的機器學習算法來講都是通用的,掌握了這些概念,就掌握了機器學習的基本套路。python

 

線性單元是啥

感知器有一個問題,當面對的數據集不是線性可分的時候,『感知器規則』可能沒法收斂,這意味着咱們永遠也沒法完成一個感知器的訓練。爲了解決這個問題,咱們使用一個可導的線性函數來替代感知器的階躍函數,這種感知器就叫作線性單元。線性單元在面對線性不可分的數據集時,會收斂到一個最佳的近似上。git

爲了簡單起見,咱們能夠設置線性單元的激活函數程序員

 

 

 

 

這樣的線性單元以下圖所示github

對比此前咱們講過的感知器算法

這樣替換了激活函數以後,線性單元將返回一個實數值而不是0,1分類。所以線性單元用來解決迴歸問題而不是分類問題。編程

 

線性單元的模型

當咱們說模型時,咱們實際上在談論根據輸入預測輸出的算法。好比,能夠是一我的的工做年限,能夠是他的月薪,咱們能夠用某種算法來根據一我的的工做年限來預測他的收入。好比:網絡

 

 

 

 

函數叫作假設,而是它的參數。咱們假設參數,參數,若是一我的的工做年限是5年的話,咱們的模型會預測他的月薪爲python2.7

 

 

 

你也許會說,這個模型太不靠譜了。是這樣的,由於咱們考慮的因素太少了,僅僅包含了工做年限。若是考慮更多的因素,好比所處的行業、公司、職級等等,可能預測就會靠譜的多。咱們把工做年限、行業、公司、職級這些信息,稱之爲特徵。對於一個工做了5年,在IT行業,百度工做,職級T6這樣的人,咱們能夠用這樣的一個特徵向量來表示他機器學習

 = (5, IT, 百度, T6)ide

既然輸入變成了一個具有四個特徵的向量,相對應的,僅僅一個參數就不夠用了,咱們應該使用4個參數,每一個特徵對應一個。這樣,咱們的模型就變成

 

 

 

 

其中,對應工做年限,對應行業,對應公司,對應職級。

爲了書寫和計算方便,咱們能夠令等於,同時令對應於特徵。因爲其實並不存在,咱們能夠令它的值永遠爲1。也就是說

 

 

其中

 

這樣上面的式子就能夠寫成

 

 

 

 

咱們還能夠把上式寫成向量的形式

 

 

 

長成這種樣子模型就叫作線性模型,由於輸出就是輸入特徵的線性組合。

 

監督學習和無監督學習

接下來,咱們須要關心的是這個模型如何訓練,也就是參數取什麼值最合適。

機器學習有一類學習方法叫作監督學習,它是說爲了訓練一個模型,咱們要提供這樣一堆訓練樣本:每一個訓練樣本既包括輸入特徵,也包括對應的輸出(也叫作標記,label)。也就是說,咱們要找到不少人,咱們既知道他們的特徵(工做年限,行業...),也知道他們的收入。咱們用這樣的樣本去訓練模型,讓模型既看到咱們提出的每一個問題(輸入特徵),也看到對應問題的答案(標記)。當模型看到足夠多的樣本以後,它就能總結出其中的一些規律。而後,就能夠預測那些它沒看過的輸入所對應的答案了。

另一類學習方法叫作無監督學習,這種方法的訓練樣本中只有而沒有。模型能夠總結出特徵的一些規律,可是沒法知道其對應的答案

不少時候,既有又有的訓練樣本是不多的,大部分樣本都只有。好比在語音到文本(STT)的識別任務中,是語音,是這段語音對應的文本。咱們很容易獲取大量的語音錄音,然而把語音一段一段切分好並標註上對應文字則是很是費力氣的事情。這種狀況下,爲了彌補帶標註樣本的不足,咱們能夠用無監督學習方法先作一些聚類,讓模型總結出哪些音節是類似的,而後再用少許的帶標註的訓練樣本,告訴模型其中一些音節對應的文字。這樣模型就能夠把類似的音節都對應到相應文字上,完成模型的訓練。

 

線性單元的目標函數

如今,讓咱們只考慮監督學習。

在監督學習下,對於一個樣本,咱們知道它的特徵,以及標記。同時,咱們還能夠根據模型計算獲得輸出。注意這裏面咱們用表示訓練樣本里面的標記,也就是實際值;用帶上劃線的表示模型計算的出來的預測值。咱們固然但願模型計算出來的越接近越好。

數學上有不少方法來表示的的接近程度,好比咱們能夠用的差的平方的來表示它們的接近程度

 

 

 

 

咱們把叫作單個樣本的偏差。至於爲何前面要乘,是爲了後面計算方便。

訓練數據中會有不少樣本,好比個,咱們能夠用訓練數據中全部樣本的偏差的和,來表示模型的偏差,也就是

 

 

 

 

上式的表示第一個樣本的偏差,表示第二個樣本的偏差......。

咱們還能夠把上面的式子寫成和式的形式。使用和式,不光書寫起來簡單,逼格也跟着暴漲,一箭雙鵰。因此必定要寫成下面這樣

 

 

 

其中

 

 

 

 

(式2)中,表示第個訓練樣本的特徵,表示第個樣本的標記,咱們也能夠用元組表示第訓練樣本。則是模型對第個樣本的預測值。

咱們固然但願對於一個訓練數據集來講,偏差最小越好,也就是(式2)的值越小越好。對於特定的訓練數據集來講,的值都是已知的,因此(式2)實際上是參數的函數。

 

 

 

 

因而可知,模型的訓練,實際上就是求取到合適的,使(式2)取得最小值。這在數學上稱做優化問題,而就是咱們優化的目標,稱之爲目標函數。

 

梯度降低優化算法

大學時咱們學過怎樣求函數的極值。函數的極值點,就是它的導數的那個點。所以咱們能夠經過解方程,求得函數的極值點

不過對於計算機來講,它可不會解方程。可是它能夠憑藉強大的計算能力,一步一步的去把函數的極值點『試』出來。以下圖所示:

首先,咱們隨便選擇一個點開始,好比上圖的點。接下來,每次迭代修改的爲,通過數次迭代後最終達到函數最小值點。

你可能要問了,爲啥每次修改的值,都能往函數最小值那個方向前進呢?這裏的奧祕在於,咱們每次都是向函數的梯度的相反方向來修改。什麼是梯度呢?翻開大學高數課的課本,咱們會發現梯度是一個向量,它指向函數值上升最快的方向。顯然,梯度的反方向固然就是函數值降低最快的方向了。咱們每次沿着梯度相反方向去修改的值,固然就能走到函數的最小值附近。之因此是最小值附近而不是最小值那個點,是由於咱們每次移動的步長不會那麼恰到好處,有可能最後一次迭代走遠了越過了最小值那個點。步長的選擇是門手藝,若是選擇小了,那麼就會迭代不少輪才能走到最小值附近;若是選擇大了,那可能就會越過最小值很遠,收斂不到一個好的點上。

按照上面的討論,咱們就能夠寫出梯度降低算法的公式

 

 

 

 

其中,是梯度算子,就是指的梯度。是步長,也稱做學習速率。

對於上一節列出的目標函數(式2)

 

 

 

 

梯度降低算法能夠寫成

 

 

 

 

聰明的你應該能想到,若是要求目標函數的最大值,那麼咱們就應該用梯度上升算法,它的參數修改規則是

 

 

 

 

下面,請先作幾回深呼吸,讓你的大腦補充足夠的新鮮的氧氣,咱們要來求取,而後帶入上式,就能獲得線性單元的參數修改規則。

關於的推導過程,我單獨把它們放到一節中。您既能夠選擇慢慢看,也能夠選擇無視。在這裏,您只須要知道,通過一大串推導,目標函數的梯度是

 

 

 

 

所以,線性單元的參數修改規則最後是這個樣子

 

 

 

有了上面這個式子,咱們就能夠根據它來寫出訓練線性單元的代碼了。

須要說明的是,若是每一個樣本有M個特徵,則上式中的都是M+1維向量(由於咱們加上了一個恆爲1的虛擬特徵,參考前面的內容),而是標量。用高逼格的數學符號表示,就是

 

 

 

 

爲了讓您看明白說的是啥,我吐血寫下下面這個解釋(寫這種公式可累可累了)。由於是M+1維列向量,因此(式3)能夠寫成

 

 

 

 

若是您仍是沒看明白,建議您也吐血再看一下大學時學過的《線性代數》吧。

 

的推導

這一節你盡能夠跳過它,並不太會影響到全文的理解。固然若是你非要弄明白每一個細節,那恭喜你騷年,機器學習的將來必定是屬於你的。

首先,咱們先作一個簡單的前戲。咱們知道函數的梯度的定義就是它相對於各個變量的偏導數,因此咱們寫下下面的式子

 

 

 

 

可接下來怎麼辦呢?咱們知道和的導數等於導數的和,因此咱們能夠先把求和符號裏面的導數求出來,而後再把它們加在一塊兒就好了,也就是

 

 

 

 

如今咱們能夠無論高大上的了,先專心把裏面的導數求出來。

 

 

 

 

咱們知道,是與無關的常數,而,下面咱們根據鏈式求導法則來求導(上大學時好像叫複合函數求導法則)

 

 

 

 

咱們分別計算上式等號右邊的兩個偏導數

 

 

 

 

代入,咱們求得裏面的偏導數是

 

 

 

 

最後代入,求得

 

 

 

 

至此,大功告成。

 

隨機梯度降低算法(Stochastic Gradient Descent, SGD)

若是咱們根據(式3)來訓練模型,那麼咱們每次更新的迭代,要遍歷訓練數據中全部的樣本進行計算,咱們稱這種算法叫作批梯度降低(Batch Gradient Descent)。若是咱們的樣本很是大,好比數百萬到數億,那麼計算量異常巨大。所以,實用的算法是SGD算法。在SGD算法中,每次更新的迭代,只計算一個樣本。這樣對於一個具備數百萬樣本的訓練數據,完成一次遍歷就會對更新數百萬次,效率大大提高。因爲樣本的噪音和隨機性,每次更新並不必定按照減小的方向。然而,雖然存在必定隨機性,大量的更新整體上沿着減小的方向前進的,所以最後也能收斂到最小值附近。下圖展現了SGD和BGD的區別

如上圖,橢圓表示的是函數值的等高線,橢圓中心是函數的最小值點。紅色是BGD的逼近曲線,而紫色是SGD的逼近曲線。咱們能夠看到BGD是一直向着最低點前進的,而SGD明顯躁動了許多,但整體上仍然是向最低點逼近的。

最後須要說明的是,SGD不只僅效率高,並且隨機性有時候反而是好事。今天的目標函數是一個『凸函數』,沿着梯度反方向就能找到全局惟一的最小值。然而對於非凸函數來講,存在許多局部最小值。隨機性有助於咱們逃離某些很糟糕的局部最小值,從而得到一個更好的模型。

 

實現線性單元

完整代碼請參考GitHub: https://github.com/hanbt/learn_dl/blob/master/linear_unit.py (python2.7)

接下來,讓咱們擼一把代碼。

由於咱們已經寫了感知器的代碼,所以咱們先比較一下感知器模型和線性單元模型,看看哪些代碼可以複用。

算法 感知器 線性單元
模型    
訓練規則    

比較的結果使人震驚,原來除了激活函數不一樣以外,二者的模型和訓練規則是同樣的(在上表中,線性單元的優化算法是SGD算法)。那麼,咱們只須要把感知器的激活函數進行替換便可。感知器的代碼請參考上一篇文章零基礎入門深度學習(1) - 感知器,這裏就再也不重複了。對於一個養成良好習慣的程序員來講,重複代碼是不可忍受的。你們應該把代碼保存在一個代碼庫中(好比git)。

 
from perceptron import Perceptron
#定義激活函數f
f = lambda x: x
class LinearUnit(Perceptron):
def __init__(self, input_num):
'''初始化線性單元,設置輸入參數的個數'''
Perceptron.__init__(self, input_num, f)

  

經過繼承Perceptron,咱們僅用幾行代碼就實現了線性單元。這再次證實了面向對象編程範式的強大。

接下來,咱們用簡單的數據進行一下測試。

 
def get_training_dataset():
'''
捏造5我的的收入數據
'''
# 構建訓練數據
# 輸入向量列表,每一項是工做年限
input_vecs = [[5], [3], [8], [1.4], [10.1]]
# 指望的輸出列表,月薪,注意要與輸入一一對應
labels = [5500, 2300, 7600, 1800, 11400]
return input_vecs, labels
def train_linear_unit():
'''
使用數據訓練線性單元
'''
# 建立感知器,輸入參數的特徵數爲1(工做年限)
lu = LinearUnit(1)
# 訓練,迭代10輪, 學習速率爲0.01
input_vecs, labels = get_training_dataset()
lu.train(input_vecs, labels, 10, 0.01)
#返回訓練好的線性單元
return lu
if __name__ == '__main__':
'''訓練線性單元'''
linear_unit = train_linear_unit()
# 打印訓練得到的權重
print linear_unit
# 測試
print 'Work 3.4 years, monthly salary = %.2f' % linear_unit.predict([3.4])
print 'Work 15 years, monthly salary = %.2f' % linear_unit.predict([15])
print 'Work 1.5 years, monthly salary = %.2f' % linear_unit.predict([1.5])
print 'Work 6.3 years, monthly salary = %.2f' % linear_unit.predict([6.3])

  

程序運行結果以下圖

擬合的直線以下圖

 

小結

事實上,一個機器學習算法其實只有兩部分

  • 模型 從輸入特徵預測輸入的那個函數
  • 目標函數 目標函數取最小(最大)值時所對應的參數值,就是模型的參數的最優值。不少時候咱們只能得到目標函數的局部最小(最大)值,所以也只能獲得模型參數的局部最優值。

所以,若是你想最簡潔的介紹一個算法,列出這兩個函數就好了。

接下來,你會用優化算法去求取目標函數的最小(最大)值。[隨機]梯度{降低|上升}算法就是一個優化算法。針對同一個目標函數,不一樣的優化算法會推導出不一樣的訓練規則。咱們後面還會講其它的優化算法。

其實在機器學習中,算法每每並非關鍵,真正的關鍵之處在於選取特徵。選取特徵須要咱們人類對問題的深入理解,經驗、以及思考。而神經網絡算法的一個優點,就在於它可以自動學習到應該提取什麼特徵,從而使算法再也不那麼依賴人類,而這也是神經網絡之因此吸引人的一個方面。

如今,通過漫長的燒腦,你已經具有了學習神經網絡的必備知識。下一篇文章,咱們將介紹本系列文章的主角:神經網絡,以及用來訓練神經網絡的大名鼎鼎的算法:反向傳播算法。至於如今,咱們應該暫時忘記一切,盡情獎勵本身一下吧。

本想放個日料的,怕被說成不愛國,換成毛爺爺家的紅燒肉吧:P

 

參考資料

  1. Tom M. Mitchell, "機器學習", 曾華軍等譯, 機械工業出版社
  2. 轉載自https://www.zybuluo.com/hanbingtao/note/448086
相關文章
相關標籤/搜索