其實我本來是不打算學這個算法的。雖然這個算法很基礎,但是跟數學太緊密了,滿屏的公式讓我有種欲哭無淚的感覺??墒?,每次看到深度學習一些新技術的時候,這個算法(或者其變體)總要跳出來干擾我的理解。就跟隔壁老王一樣,你不摸清楚他的來龍去脈,總感覺心里不踏實。
我能怎么辦?我也很絕望啊!在飽受其困擾之后,我決定一探究竟,自己實現以下該算法,順便學習以下python以及NumPy。這代碼一寫,好家伙,我發現之前對epoch和mini_batch的理解都是有偏差的。果然還是要實踐才能發現我只是錯誤的以為我以為我懂了。
[注:已經了解基礎概念的,希望看證明或者詳細介紹backpropagation的,不需要看本篇水文,直接跳到下一篇]
要講Backpropagation,得從基礎的神經網絡說起(前一篇有講到神經網絡和深度學習等這些詞是嘛意思)。神經網絡有許多種形式,比較基礎的一種稱之為feedforward神經網絡(另外還有recurrent神經網絡,這里不涉及)。它是啥意思呢,盜一張圖說明一下:
簡單點說,就是前一層的輸出,作為后一層的輸入,后一層的輸出(或者中間值)并不對前一層造成影響。
圖中,每個圓圈,代表一個神經元。每一根箭頭,代表一個權重(weight, w),它表示輸出神經元與接收神經元之間聯系的強弱。每個圓圈(除了第一層的)會有一個偏差(bias, b)對應,表示一個修正,是一個與前一層神經元無關的常數。
如果認為前一層的輸出是x的話, 后一層跟前一層關聯的輸入就是
這玩意用矩陣的方式表示,就是wx(這里w和x都是矩陣, 對于圖中第一層和第二層而言,w是
4*6
的矩陣,x是6*1
的矩陣,為啥我要說這么細,因為這樣子對初學者來說才直觀)。但這里我們還需要加入一個常量起到偏移作用, 所以輸入就是z=wx+b
(注意,這里都是矩陣)。但是這樣還沒完,單純這樣的變化,并不能讓神經元的表達能力逆天,所以發明這些的人,又給神經元再套了一個函數,稱之為激活函數(Activation Function),它為神經元的輸出加入非線性特性,增強了神經網絡對訓練數據的學習能力。所以,神經元的輸出就變成了:
這里的a就是上文中的x。把這個公式不斷地應用到下一層,就可以計算出整個神經網絡的輸出。
深度學習的過程,說白了,就是先隨機
(當然并不是完全隨機,里面藏著一些貓膩)生成每一層的w和b,然后用一些方法不斷對它們進行修正。憑什么修正呢?數據!你得預先準備好一堆數據,每個數據的意思就是給定一個輸入(x), 應該得到什么輸出(d)。因為有了輸入之后,一定可以根據上面的公式和已有的w和b(我們已經隨機好了初始值), 算出一個最終輸出(y),算的過程就是上面這個公式一層一層迭代過去。這個輸出(y)跟真正的輸出(d)不一樣。學習過程就是不斷調整w和b, 讓d和y之間的差距盡量小。
這里又有一個地方要注意了,圖中最后一層只有一個神經元,但是實際上最后一層可以有多個神經元的,因此y是一個矩陣。相應的d也是一個矩陣。那怎么定義差距呢?下面兩個公式說明了一種定義方式:
這個看起來很直觀吧,就跟幾何上的“距離”類似。不過再次強調一下,這只是損失函數的一種形式(搞機器學習的學者們還發明了一堆奇形怪狀的損失函數,腦洞之大,我只能說在下心服口服)。
本來只想寫backpropagation的,因為網上很多推導不全,或者講得不夠直白。但沒想到只是介紹最最基礎的東西, 就這么多了, 那剩余的部分,待下回分解吧。