Reference:Spatial Transformer Networks [Google.DeepMind]
Reference:[Theano源碼,基於Lasagne]
閑扯:大數據不如小數據
這是一份很新的Paper(2015.6),來自於Google旗下的新銳AI公司DeepMind的四位劍橋Phd研究員。
他們針對CNN的特點,構建了一個新的局部網絡層,稱為空間變換層,如其名,它能將輸入圖像做任意空間變換。
在我的論文[深度神經網絡在面部情感分析系統中的應用與改良]中,提出了一個有趣觀點:
大數據不如小數據,如果大數據不能被模型有效利用。
該現象是比較常見的,如ML實戰的一個經典問題:數據不均衡,這樣模型就會對大類數據過擬合,忽略小類數據。
另外,就是[Evolving Culture vs Local Minima:文化、進化與局部最小值]提到的課程學習觀點:
將大數據按照難易度剖分,分批學習,要比直接全部硬塞有效得多。
當前,我們炙手可熱的模型仍然是蒟蒻的,而數據卻是巧奪天工、超乎想象的。
因而,想要通過模型完全摸清數據的Distribution是不現實的,發明、改良模型結構仍然是第一要務,
而不單純像Li Feifei教授劍走偏鋒,用ImageNet這樣的大數據推進深度學習進程。
空間變換的重要意義
在我的論文[深度神經網絡在面部情感分析系統中的應用與改良]中,分析了CNN的三個強大原因:
[局部性]、[平移不變性]、[縮小不變性],還對缺失的[旋轉不變性]做了相應的實驗。
這些不變性的本質就是圖像處理的經典手段,[裁剪]、[平移]、[縮放]、[旋轉]。
這些手段又屬於一個家族:空間變換,又服從於同一方法:坐標矩陣的仿射變換。
那么,神經網絡是否有辦法,用一種統一的結構,自適應實現這些變換呢?DeepMind用一種簡易的方式實現了。
圖像處理技巧:仿射矩陣、逆向坐標映射、雙線性插值
1.1 仿射變換矩陣
實現[裁剪]、[平移]、[縮放]、[旋轉],只需要一個$[2,3]$的變換矩陣:
$\begin{bmatrix}\theta_{11} & \theta_{12} & \theta_{13} \\ \theta_{21}& \theta_{22} & \theta_{23}\end{bmatrix}$
—————————————————————————————————————————————————————————
對於平移操作,坐標仿射矩陣為:
$\begin{bmatrix}1 & 0 & \theta_{13} \\ 0& 1 & \theta_{23}\end{bmatrix}\begin{bmatrix}x\\ y\\1\end{bmatrix}=\begin{bmatrix}x+\theta_{13}\\
y+\theta_{23}\end{bmatrix}$
—————————————————————————————————————————————————————————
對於縮放操作,坐標仿射矩陣為:
$\begin{bmatrix}\theta_{11} & 0 & 0 \\ 0& \theta_{22} & 0\end{bmatrix}\begin{bmatrix}x\\ y\\1\end{bmatrix}=\begin{bmatrix}\theta_{11}x\\
\theta_{22}y\end{bmatrix}$
—————————————————————————————————————————————————————————
對於旋轉操作,設繞原點順時針旋轉$\alpha$度,坐標仿射矩陣為:
$\begin{bmatrix}cos(\alpha) & sin(\alpha) & 0 \\ -sin(\alpha)& cos(\alpha) & 0\end{bmatrix}\begin{bmatrix}x\\ y\\1\end{bmatrix}=\begin{bmatrix}
cos(\alpha)x+sin(\alpha)y\\ -sin(\alpha)x+cos(\alpha)y\end{bmatrix}$
這里有個trick,由於圖像的坐標不是中心坐標系,所以只要做下Normalization,把坐標調整到[-1,1]。
這樣,就繞圖像中心旋轉了,下文中會使用這個trick。
—————————————————————————————————————————————————————————
至於裁剪操作,沒有看懂Paper的關於左2x2 sub-matrix的行列式值的解釋,但可以從坐標范圍解釋:
只要$x^{'}$、$y^{'}$的范圍比$x$,$y$小,那么就可以認為是目標圖定位到了源圖的局部。
這種這種仿射變換沒有具體的數學形式,但肯定是可以在神經網絡搜索過程中使用的。
1.2 逆向坐標映射
注:感謝網友@載重車提出疑問,修正了這部分的內容。具體請移步評論區。
★本部分作為一個對論文的錯誤理解,保留。
在線性代數計算中,一個經典的求解思路是:
$\begin{bmatrix}\theta_{11} & \theta_{12} & \theta_{13} \\ \theta_{21}& \theta_{22} & \theta_{23}\end{bmatrix}\begin{bmatrix}x^{Source}\\ y^{Source}\\ 1\end{bmatrix}=\begin{bmatrix}x^{Target}\\ y^{Target}\end{bmatrix}$
這種做法在做圖像處理時,會給並行矩陣程序設計造成尷尬——需要犧牲額外的空間存儲映射源,:
由於$(x^{Target},y^{Target})$必然是離散的,當我們需要得到$Pixel(x^{Target},y^{Target})$的值時,
如果不及時保存$(x^{Source},y^{Source})$,那么就必須即時單點復制$Pixel(x^{Source},y^{Source})->Pixel(x^{Target},y^{Target})$
顯然,這種方法的實現依賴於$For$循環:
$For(0....i....Height)\\ \quad For(0....j....Width) \\ \quad \quad Calculate\&Copy$
為了能讓矩陣並行計算成為可能,我們需要逆轉一下思路:
$\begin{bmatrix}\theta_{11} & \theta_{12} & \theta_{13} \\ \theta_{21}& \theta_{22} & \theta_{23}\end{bmatrix}^{'}\begin{bmatrix}x^{Target}\\ y^{Target}\\ 1\end{bmatrix}=\begin{bmatrix}x^{Source}\\ y^{Source}\end{bmatrix}$
之后,構建變換目標圖就轉化成了,數組下標取元素問題:
$PixelMatrix^{Target}=PixelMatrix^{Source}[x^{Source},y^{Source}]$
這依賴於仿射矩陣的一個性質:
$\begin{bmatrix}\theta_{11} & \theta_{12} & \theta_{13} \\ \theta_{21}& \theta_{22} & \theta_{23}\end{bmatrix}^{'}=\begin{bmatrix}\theta_{11} & \theta_{12} & \theta_{13} \\ \theta_{21}& \theta_{22} & \theta_{23}\end{bmatrix}^{-1}$
即,由Target變換為Source時,新仿射矩陣為源仿射矩陣的逆矩陣。
1.3 雙線性插值
考慮一個$[1,10]$圖像放大10倍問題,我們需要將10個像素,擴展到為100的數軸上,整個圖像應該有100個像素。
但其中90個對應Source圖的坐標是非整數的,是不存在的,如果我們用黑色($RGB(0,0,0)$)填充,此時圖像是慘不忍睹的。
所以需要對缺漏的像素進行插值,利用圖像數據的局部性近似原理,取鄰近像素做平均生成。
雙線性插值是一個兼有質量與速度的方法(某些電子游戲里通常這么排列:線性插值、雙線性插值....):
如果$(x^{Source},y^{Source})$是實數坐標,那么先取整(截尾),然后沿軸擴展$d$個坐標單位,得到$P_{21}$、$P_{12}$、$P_{22}$
一般的(源碼中),取$d=1$,式中分母全被消去,再利用圖中雙線性插值式進行插值,得到$Pixel(x^{Source},y^{Source})$的近似值。
神經網絡
2.1 塊狀神經元
CNN是一個變革的先驅者模型,它率先提出局部連接觀點,減少網絡廣度,增加網絡深度。
局部連接讓神經元呈塊狀,單參數成參數組;讓網絡2D化,切合2D圖像;讓權值共享,大幅度減少參數量。
仿射矩陣自適應學習理論,因此而得以實現:
2.2 基本結構與前向傳播
論文中的結構圖描述得不是很清楚,個人做了部分調整,如下:
DeepMind為了描述這個空間變換層,首先添加了坐標網格計算的概念,即:
對應輸入源特征圖像素的坐標網格——Sampling Grid,保存着$(x^{Source},y^{Source})$
對應輸出源特征圖像素的坐標網格——Regluar Grid ,保存着$(x^{Target},y^{Target})$
然后,將仿射矩陣神經元組命名為定位網絡 (Localisation Network)。
對於一次神經元提供參數,坐標變換計算,記為 $\tau_{\theta}(G)$,根據1.2,有:
$\tau_{\theta}(G_{i})=\begin{bmatrix}\theta_{11} & \theta_{12} & \theta_{13} \\ \theta_{21}& \theta_{22} & \theta_{23}\end{bmatrix}^{'}\cdot\begin{bmatrix}x_{i}^{Target}\\ y_{i}^{Target}\\ 1\end{bmatrix}=\begin{bmatrix}x_{i}^{Source}\\ y_{i}^{Source}\end{bmatrix}\quad where \quad i=1,2,3,4..,H*W$
該部分對應於圖中的①②,但是與論文中的圖有些變化,可能是作者並沒有將逆向計算的Trick搬到結構圖中來。
所以你看到的仍然是Sampling Grid提供坐標給定位網絡,而具體實現的時候恰好是相反的,坐標由Regluar Grid提供。
————————————————————————————————————————————————————————
Regluar Grid提供的坐標組是順序逐行掃描坐標的序列,序列長度為 $[Heght*Width]$,即:
將2D坐標組全部1D化,根據在序列中的位置即可立即算出,在Regluar Grid中位置。
這么做的最大好處在於,無須額外存儲Regluar Grid坐標$(x^{Target},y^{Target})$。
因為從輸入特征圖$U$數組中,按下標取出的新像素值序列,仍然是逐行掃描順序,簡單分隔一下,便得到了輸出特征圖$V$。
該部分對應於圖中的③。
————————————————————————————————————————————————————————
(1.3)中提到了,直接簡單按照$(x^{Source},y^{Source})$,從源像素數組中復制像素值是不可行的。
因為仿射變換后的$(x^{Source},y^{Source})$可以為實數,但是像素位置坐標必須是整數。
為了解決像素值缺失問題,必須進行插值。插值核函數很多,源碼中選擇了論文中提供的第二種插值方式——雙線性插值。
(1.3)的插值式非常不優雅,DeepMind在論文利用max與abs函數,改寫成一個簡潔、優雅的插值等式:
$V_{i}^{c}=\sum _{n}^{H}\sum _{m}^{W}U_{nm}^{c}\max(0,1-|x_{i}^{S}-m|)\max(0,1-|y_{i}^{S}-n|) \quad where \quad i\in [1,H^{'}W^{'}],c\in[1,3]$
兩個 $\sum$ 實際上只篩出了四個鄰近插值點,雖然寫法簡潔,但白循環很多,所以源碼中選擇了直接算4個點,而不是用循環篩。
該部分對應圖中的④。
2.3 梯度流動與反向傳播
添加空間變換層之后,梯度流動變得有趣了,如圖:
形成了三股分支流:
(I)后の流:
$ErrorGradient\rightarrow .....\rightarrow \frac{\partial Next}{\partial V_{i}^{c}}$
這是Back Propagation從后層繼承的動力源泉,沒有它,你就不可能完成Back Propagation。
(II)里の流:
$\left\{\begin{matrix}\frac{\partial V_{i}^{c}}{\partial x_{i}^{S}}\rightarrow \frac{\partial x_{i}^{S}}{\partial \theta}\\ \frac{\partial V_{i}^{c}}{\partial y_{i}^{S}}\rightarrow \frac{\partial y_{i}^{S}}{\partial \theta}\end{matrix}\right.$
個人對這股流的最好描述就是:一江春水流進了小黑屋。
是的,你沒有看錯,這股流根本就沒有流到網絡開頭,而是在定位網絡處就斷流了。
由此來看,定位網絡就好像是在主網絡旁側偷建的小黑屋,是一個違章建築。
所以也無怪乎作者說,定位網絡直接變成了一個回歸模型,因為更新完參數,流就斷了,獨立於主網絡。
(III)前の流:
$\frac{\partial V_{i}^{c}}{\partial U_{nm}^{i}}\rightarrow\frac{\partial U_{nm}^{i}}{\partial Previous}$
這是Back Propagation傳宗接代的根本保障,沒有它,Back Propagation就斷子絕孫了。
2.4* 局部梯度
論文中多次出現[局部梯度](Sub-Gradient) 的概念。
作者們反復強調,他們寫的,優雅簡潔的采樣核函數,是不連續的,不能如下直接求導:
$g=\frac{\partial V_{i}^{c}}{\partial \theta}$
而應該是分兩步,先對$x_{i}^{S}$ 、$x_{i}^{S}$ 求局部梯度: $\frac{\partial V_{i}^{c}}{\partial x_{i}^{c}}$ 、$\frac{\partial V_{i}^{c}}{\partial y_{i}^{c}}$,后有:
$\left\{\begin{matrix}g=\frac{\partial V_{i}^{c}}{\partial x_{i}^{S}} \cdot \frac{\partial x_{i}^{S}}{\partial \theta}\\ g=\frac{\partial V_{i}^{c}}{\partial y_{i}^{S}} \cdot \frac{\partial y_{i}^{S}}{\partial \theta}\end{matrix}\right.$
有趣的是,對於Theano這種自動求導的Tools,局部梯度可以直接被忽視。
因為Theano的Tensor機制,會聰明地討論並且解離非連續函數,追蹤每一個可導子式,即便你用了作者們的優雅的采樣函數,
Tensor.grad函數也能精確只對篩出的4個點求導,所以在Theano里討論非連續函數和局部梯度,是會被貽笑大方的。