卷積優化方法之Winograd
在卷積神經網絡當中, 卷積運算是尤其是計算敏感的, 尤其是在端上設備中, 對於性能的要求更為苛刻。對於卷積優化的方法也有很多種,本文便針對近年來最常見的優化方法Winograd做一個簡單總結。
相關資料
winograd算法最早是1980年由Terry Winograd提出的,當時並沒有引起太大的轟動。在CVPR'16會議上,Lavin等人[1]提出了利用winogrd加速卷積運算,於是winograd加速卷積優化在算法圈里火了一把。網上較多的實現版本為andravin實現的py版本[2]。目前cudnn中計算卷積就使用了該方法。
[1] "Fast Algorithms for Convolutional Neural Networks" Lavin and Gray, CVPR 2016.
[2] https://github.com/andravin/wincnn
算法
在winograd算法下,對於一維卷積,當輸出為m,卷積核長為r,要對應的乘法數量:
將一維卷積擴展到二維,如果輸出維度為mxn,卷積核維度為rxs,則對應的乘法數量:
對一個矩陣大小為4 * 4的輸入,卷積核大小為3 * 3,對應的輸出為2 * 2,正常計算的情況下,滑動窗口或者im2col的計算方法的乘法次數為2*2*3*3 = 36次,而當使用winograd時,對應的乘法次數為$ u(F(2*2,3*3)) = (2+3-1) * (2+3-1)=16 $,乘法次數明顯減少。
假設對應的一維輸入為[d0,d1,d2,d3],對應的卷積為[g0,g1,g2],對應的輸出為[m0,m1,m2],那么:
其中:
這種計算方式需要2+3-1=4次乘法,4次加法。寫成矩陣乘法的形式即為:
其中$ \odot $表示 element-wise multiplication. 對於F(2,3),以上矩陣分別為:
擴展為二維的形式即為:
注意
- 以上描述的 Winograd 算法只展示了在二維的圖像 (更確切的說是 tile) 上的過程, 具體在 ConvNet 的多個 channel 的情況, 直接逐個 channel 按照上述方法計算完然后相加即可;
- 按照 1. 的思路, 在計算多個 channel 的時候, 仍然有可減少計算次數的地方.
- 按照 2. 的思路, Winograd 在目前使用越來越多的 depthwise conv 中其優勢不明顯了.
- 在 tile 較大的時候, Winograd 方法不適用, 因為, 在做 inverse transform 的時候的計算開銷抵消了 Winograd 帶來的計算節省.
Winograd 會產生誤差