1982年的Hopfiled網絡首次將統計物理學的能量觀點引入到神經網絡中,html
將神經網絡的全局最小值求解,近似認爲是求解熱力學系統的能量最低點(最穩定點)。編程
爲此,特意爲神經網絡定義了神經網絡能量函數$E(x|Label)$,其中$x$爲輸入。網絡
$E(x|Label)=-\frac{1}{2}Wx \Delta Y \quad where \quad \Delta Y=y-label$ (省略Bias項)app
值得注意的是,這套山寨牌能量函數只能求出局部最小值,SVM用二次規劃函數替換掉以後才能求全局最小值。框架
惟一的敗筆是,Hopfiled網絡的輸出仍然採用了階躍函數Sign,走的仍是Rosenblatt的老路子。機器學習
這個能量函數很是有趣,它在階躍函數狀態下永遠是遞減的,即使是W永遠是正的。(錯誤的隨機初始化也是OK的)。ide
緣由以下:函數
I、當階躍函數輸出爲1時,Wx爲正,若產生Loss,$\Delta Y=1-(-1)=2$,顯然$\Delta YE(x|y)$爲負。學習
II、當階躍函數輸出爲-1時,Wx爲負,若產生Loss,$\Delta Y=-1-(1)=-2$,顯然$\Delta YE(x|y)$仍是爲負。優化
III、若無LOSS,$\Delta Y=1-1$或$(-1)-(-1)$都爲0,$\Delta E(x|y)$也爲0。
祖師爺Hinton在1985年創立了第一個隨機神經網絡,首次將機率引入神經網絡這個大玄學中。
值得一提的是,在當時機率圖模型也是被公認爲玄學之一,不少研究者認爲,信機率還不如信神經網絡。(今天卻是反過來了)
Boltzmann機延續了Hopfiled能量函數的傳統,可是用一個奇葩的歸一化函數來產生機率,以取代相對不精確的階躍函數。
這個歸一化函數描述以下:
$P(y)=\frac{1}{1+e^{\frac{-(Wx+b)}{T}}}$
其中T爲溫度係數,超參數之一,須要調參。
看起來怎麼那麼眼熟呢,扔掉T以後,這不就是Sigmoid函數麼。
能夠看到,Boltzmann機爲了表達機率,選用了Sigmoid函數做爲神經網絡的機率平滑產生器。
1986年由Smolensky創立的限制Boltzmann機將Hopfiled網絡的輸出部折回,這樣就產生了多變量的輸出。
如何去表達此時多變量狀況下的機率,能量模型—配分函數(Partition Function)解決了這一點:
$P(x)=\frac{e^{-E(x)}}{Z}=\frac{e^{-E(x)}}{\sum _{i}e^{-E(i)}}$
配分項Z是你們耳熟能詳的噁心之物,它的求解讓深度學習推遲了20年。
在深度學習被卡的20年間,配分項函數在多變量的判別模型中普遍推廣,疑似是Softmax的雛形。
在LeCun的EBM教程Slides的介紹了配分判別函數,也就是今天的Softmax函數。
★The partition function ensures that undesired answers are given low probability
★For learning, we need to approximate the partition function (or its gradient with respect to the parameters)
順便將其批判了一番:
★Max likelihood learning gives high probability to good answers
★Problem: there are too many bad answers!
這部分的觀點能夠參照PRML的序章關於貝葉斯擬合學習的討論,採用配分判別的Loss、基於極大似然的頻統方法
很是容易產生過擬合和弱泛化,貝葉斯學習和深度學習則引入先驗Prior在極大似然的統計基礎上作懲罰。
配分判別函數的定義以下:
$P(Y|X)=\frac{e^{-\beta}E(Y,X)}{\int_{y\in Y}e^{-\beta}E(y,X)}$
其中$\beta$爲係數,扔掉以後就是Softmax函數。
$NLL = - \sum _{i}^{examples}\sum _{k}^{classes}l(y(i)=k)\cdot log[Softmax(X_{k}^{i})]$
不作過多介紹,見個人早期博文:Softmax迴歸
前向傳播求Loss的時候只要記住一點區別:
I、在Logistic迴歸中,對每一個樣本,Loss-=$\log(1-Sigmoid)$或者Loss-=$\log(Sigmoid)$
II、在Softmax迴歸中,對每一個樣本,Loss只減去對應Label的$\log(Softmax)$
比較I、II也能夠看出來,Logistic迴歸的二選一隻是Softmax迴歸的N選一的特例。
儘管DeepLearning的基石是多樣本與並行計算,可是在泛型章節中不考慮多樣本狀況。
求導描述將盡可能與Caffe框架中的命名方式同步,以便於理解代碼。
同時假定Softmax Axis上,命中Label的下標爲k。
上圖是在當單樣本狀況下,直接取Softmax Axis而畫的,如今咱們假設這是一個N=3的分類問題。(0,1,2)
同時取Class=2做爲當前樣本,命中的Label,即k=2。
因爲Loss只和命中的分類有關,有:
$Softmax(X_{k})=\frac{e^{X_{k}}}{\sum _{i}e^{X_{i}}}$
則NLL (Negative-Log-Likelihood)爲:
$NLL=-\log(Softmax(X_{k}))=-\log(\frac{e^{X_{K}}}{\sum _{i}e^{X_{i}}})\\ \quad \\ \qquad \qquad \qquad \qquad \qquad \qquad \; \; \,=\log(\sum _{i}e^{X_{i}})-log(e^{X_{k}}) \\ \quad \\ \qquad \qquad \qquad \qquad \qquad \qquad \; \; \, =\log(\sum _{i}e^{X_{i}})-X_{k}$
此時對於神經元$X_{k}$,有以下兩種求導方案:
I、 $BottomDiff(k)=\frac{\partial NLL}{\partial Softmax(X_{k})}\frac{\partial Softmax(X_{k})}{\partial X_{k}}$
II、 $BottomDiff(k)=\frac{\partial NLL}{\partial X_{k}}$
其中,第一種是沒有必要的,通常而言,Softmax的中間導數幾乎不會用到。
除非咱們讓Softmax後面不接Loss,接其它的層,下一節會講這種特殊狀況,求導至關複雜。
如今考慮更通常的神經元$X_{i}$,對NLL求導:
$\frac{\partial \log(\sum _{i}e^{X_{i}})-X_{k}}{\partial X_{i}}=\left\{\begin{matrix}\frac{e^{X_{K}}}{\sum _{i}e^{X_{i}}} - 1 \quad (i\neq k) \\ \\\frac{e^{X_{K}}}{\sum _{i}e^{X_{i}}} \quad (i=k)\\ \\0 \quad (if \;ignore\;i)\end{matrix}\right.$
編程時:
對於①條件:先Copy一下Softmax的結果(即prob_data)到bottom_diff,再對k位置的unit減去1
對於②條件:直接Copy一下Softmax的結果(即prob_data)到bottom_diff
對於③條件:找到ignore位置的unit,強行置爲0。
圖示以下:
在SoftmaxLayer中,咱們將會遇到最廣泛的反向傳播任務:已知top_diff,求bottom_diff。
爲了表述方便,設已知的top_diff的偏導表達式爲:$\frac{\partial l}{Softmax(X)}$,則:
$BottomDiff(i)=\sum _{j}\frac{\partial l}{\partial Softmax(X_{j})}\frac{\partial Softmax(X_{j})}{\partial X_{i}}$
這是單獨對Softmax求導的最麻煩之處,因爲全鏈接性,輸入神經元$X_{i}$將被所有的輸出神經元污染。
更通常的,咱們將其寫成:
$BottomDiff(i)=\frac{\partial l}{\partial Softmax(X)}\frac{\partial Softmax(X)}{\partial X_{i}}$。
考慮$\frac{\partial Softmax(X_{j})}{\partial X_{i}}$,有:
$\frac{\partial Softmax(X_{j})}{\partial X_{i}}=\left\{\begin{matrix}-Softmax(X_{j})*Softmax(X_{i})+Softmax(X_{i}) \quad i=j\\ \\ -Softmax(X_{j})*Softmax(X_{i}) \quad i\neq j\end{matrix}\right.$
聯合兩部分後,有:
$\sum \left\{\begin{matrix}-Softmax(X_{j})*\frac{\partial l}{\partial Softmax(X_{j})}*Softmax(X_{i})+Softmax(X_{i})*\frac{\partial l}{\partial Softmax(X_{j})} \quad i=j\\ \\ -Softmax(X_{j})*\frac{\partial l}{\partial Softmax(X_{j})}*Softmax(X_{i}) \quad i\neq j\end{matrix}\right.$
提取公共項部分:
$BottomDiff(i)=Softmax(X_{i})\left \langle \sum {j}\left \{-Softmax(X_{j})*\frac{\partial l}{\partial Softmax(X_{j})}\right \}+\frac{\partial l}{\partial Softmax(X_{i}) })\right \rangle\\ \quad \\ \qquad \qquad \qquad \; \; \; =TopData(i)\left \langle - \sum {j}\left \{TopData(j)*TopDiff(j)\right \}+TopDiff(i) \right \rangle\\ \quad \\ \qquad \qquad \qquad \; \; \; =TopData(i)\left \langle - \left \{TopData \bullet TopDiff \right \} +TopDiff(i) \right \rangle$
Caffe中作了如下兩點額外的優化:
I、因爲對全部$X_{i}$,都要計算相同的點積項$\sum {j}\left \{TopData(j)*TopDiff(j)\right \}$,
一個簡單優化是用GEMM作一次矩陣廣播,這樣,對每一個樣本的Softmax Axis軸上的多個單元,只需點積一次。
II、因爲top_data與bottom_diff的shape相同,最外層top_data可基於全樣原本乘,這在CUDA環境中,能夠有效提高瞬時並行度。
Caffe中將二軸Softmax(Batchsize/Softmax)擴展到了nD軸Softmax,用於全卷積網絡。
這部分代碼由此paper兩位做者Jonathan Long&Evan Shelhamer加入,Github的History以下:
空間Soffmax是爲了Dense Pixel Prediction(密集點預測)而生的,對於一張300x500的輸入圖像,
一次Softmax將產生300*500=15W個Loss,這屬於神經網絡——像素級理解,是目前最難的CV任務。
空間Softmax取消了Softmax前的InnerProduct作的Flatten,由於必須保證空間軸信息。
一個語義分割的圖示以下:
傳統機器學習中的樣本單數值Label,在ComputerVision中擴展爲多數值Label後,即變成GroundTruth。
Caffe中採用如下格式來規範存儲與讀取:
對於GroundTruth的$outer:inner=(i,j)$位置,即第$i$個樣本,空間$j$位置的Label,對應的Softmax向量以下:
$PixelExample=\left\{\begin{matrix}BottomData/BottomDiff(i*dim+0*inner+j) \quad class=0 \\
\quad \\ BottomData/BottomDiff(i*dim+1*inner+j) \quad class=1\\ \\ BottomData/BottomDiff(i*dim+2*inner+j) \quad class=2\\ \\...... \\ \\ BottomData/BottomDiff(i*dim+c*inner+j) \quad class=c\end{matrix}\right.$
這樣,對於outer_num數量的輸入圖像,就變成了outer_num*inner_num個像素樣本。
值得注意的是,目前最新的研究代表,在像素級的理解中,batch_size大於1是沒有意義的,會嚴重減慢收斂速度。
輸入單張圖像時,SGD作密集點預測,不會致使偏離最終的局部最值點,由於15W的Loss近似能夠當作batch_size=15,0000
從上節可知,空間軸(e.g. Height/Width)的引入,可當作是倍化了batch_size軸。
故在SoftmaxLayer中,對單樣本圖像的輸入,須要多引入一次循環模擬多樣本,循環量即inner_num。
對於泛型Softmax中的點積運算,由計算單點積值,須要變化至求一組$TopData \bullet TopDiff$:
一樣設$outer:inner=(i,j)$,那麼$j$位置的兩組點積向量分別以下:
$\bullet \left\{\begin{matrix}TopData/TopDiff(i*dim+0*inner+j) \quad class=0\\ \\ .........\\ \\ TopData/TopDiff(i*dim+c*inner+j) \quad class=c\\ \end{matrix}\right.$
因爲點積的元素每次都要跳躍inner_num個位置,可利用BLAS庫作StridedDot運算,點積增量設爲inner_num便可。
I、在GEMM矩陣廣播優化中,原來只須要將單點積值廣播成[classes,1]的矩陣,順次在Softmax-Axis軸上減去,即:
從$TopDiff(i*dim)$的一段減去,因爲無空間軸時,dim=classes,TopDiff的shape爲[batch_size,classes],
矩陣的值剛好填充到下同樣本的開頭。
擴展空間軸時,則須要減去[classes,inner_num]個值,注意因爲此時的shape爲[batch_size,classes,inner_num],
若是你要線性覆蓋,則須要先覆蓋class=0的inner_num個值,因此必定要保證廣播矩陣的shape爲[classes,inner_num]。
而後再作一次向量減法。因爲BLAS的GEMM運算支持$C=\beta C+\alpha AB $,可一步完成。
II、在最外圍的top_data乘算中,因爲top_data與bottom_diff的shape相同,擴展空間軸無需調整代碼。