原文链接:Winograd卷积原理 | Hey~YaHei!
Winograd算法最早于1980年由Shmuel Winograd在《Arithmetic complexity of computations(1980)》中提出,主要用来减少FIR滤波器的计算量。
该算法类似FFT,将数据映射到另一个空间上,用加减运算代替部分乘法运算,在“加减运算速度远高于乘法运算”的前提下达到明显的加速效果(与FFT不同的是,Winograd将数据映射到一个实数空间而非复数空间)。
比如,
直接实现一个 m m m 输出、 r r r 参数的FIR滤波器 F ( m , r ) F(m,r) F(m,r),一共需要 m × r m \times r m×r 次乘法运算;
但使用Winograd算法,忽略变换过程的话,仅仅需要 m + r − 1 m + r - 1 m+r−1 次乘法运算。
F ( 2 , 3 ) F(2,3) F(2,3)
如果直接计算 F ( 2 , 3 ) F(2,3) F(2,3):
F ( 2 , 3 ) = [ d 0 d 1 d 2 d 1 d 2 d 3 ] [ g 0 g 1 g 2 ] = [ d 0 g 0 + d 1 g 1 + d 2 g 2 d 1 g 0 + d 2 g 1 + d 3 g 2 ] F(2,3)=\left[\begin{array}{lll}{d_{0}} & {d_{1}} & {d_{2}} \\ {d_{1}} & {d_{2}} & {d_{3}}\end{array}\right]\left[\begin{array}{l}{g_{0}} \\ {g_{1}} \\ {g_{2}}\end{array}\right]=\left[\begin{array}{l}{d_0g_0+d_1g_1+d_2g_2} \\ {d_1g_0+d_2g_1+d_3g_2}\end{array}\right] F(2,3)=[d0d1d1d2d2d3]⎣⎡g0g1g2⎦⎤=[d0g0+d1g1+d2g2d1g0+d2g1+d3g2]
其中,
d 0 , d 1 , d 2 d_0, d_1, d_2 d0,d1,d2和 d 1 , d 2 , d 3 d_1, d_2, d_3 d1,d2,d3为连续的两个输入序列;
g 0 , g 1 , g 2 g_0, g_1, g_2 g0,g1,g2为FIR的三个参数;
这个过程一共需要6次乘法,和4次加法
而Winograd算法指出, F ( 2 , 3 ) F(2,3) F(2,3) 可以这样计算:
F ( 2 , 3 ) = [ d 0 d 1 d 2 d 1 d 2 d 3 ] [ g 0 g 1 g 2 ] = [ m 1 + m 2 + m 3 m 2 − m 3 − m 4 ] F(2,3)=\left[\begin{array}{lll}{d_{0}} & {d_{1}} & {d_{2}} \\ {d_{1}} & {d_{2}} & {d_{3}}\end{array}\right]\left[\begin{array}{l}{g_{0}} \\ {g_{1}} \\ {g_{2}}\end{array}\right]=\left[\begin{array}{l}{m_{1}+m_{2}+m_{3}} \\ {m_{2}-m_{3}-m_{4}}\end{array}\right] F(2,3)=[d0d1d1d2d2d3]⎣⎡g0g1g2⎦⎤=[m1+m2+m3m2−m3−m4]
其中,
m 1 = ( d 0 − d 2 ) g 0 m 2 = ( d 1 + d 2 ) g 0 + g 1 + g 2 2 m 4 = ( d 1 − d 3 ) g 2 m 3 = ( d 2 − d 1 ) g 0 − g 1 + g 2 2 \begin{array}{ll}{m_{1}=\left(d_{0}-d_{2}\right) g_{0}} & {m_{2}=\left(d_{1}+d_{2}\right) \frac{g_{0}+g_{1}+g_{2}}{2}} \\ {m_{4}=\left(d_{1}-d_{3}\right) g_{2}} & {m_{3}=\left(d_{2}-d_{1}\right) \frac{g_{0}-g_{1}+g_{2}}{2}}\end{array} m1=(d0−d2)g0m4=(d1−d3)g2m2=(d1+d2)2g0+g1+g2m3=(d2−d1)2g0−g1+g2
该用矩阵运算可以表示成:
Y = A T [ ( G g ) ⊙ ( B T d ) ] Y=A^{T}\left[(G g) \odot\left(B^{T} d\right)\right] Y=AT[(Gg)⊙(BTd)]
其中, ⊙ \odot ⊙表示点乘,而
B T = [ 1 0 − 1 0 0 1 1 0 0 − 1 1 0 0 1 0 − 1 ] , G = [ 1 0 0 1 2 1 2 1 2 1 2 − 1 2 1 2 0 0 1 ] , A T = [ 1 1 1 0 0 1 − 1 − 1 ] B^{T}=\left[\begin{array}{rrrr}{1} & {0} & {-1} & {0} \\ {0} & {1} & {1} & {0} \\ {0} & {-1} & {1} & {0} \\ {0} & {1} & {0} & {-1}\end{array}\right], G=\left[\begin{array}{rrr}{1} & {0} & {0} \\ {\frac{1}{2}} & {\frac{1}{2}} & {\frac{1}{2}} \\ {\frac{1}{2}} & {-\frac{1}{2}} & {\frac{1}{2}} \\ {0} & {0} & {1}\end{array}\right], A^{T}=\left[\begin{array}{rrrr}{1} & {1} & {1} & {0} \\ {0} & {1} & {-1} & {-1}\end{array}\right] BT=⎣⎢⎢⎡100001−11−1110000−1⎦⎥⎥⎤,G=⎣⎢⎢⎡121210021−210021211⎦⎥⎥⎤,AT=[10111−10−1]
g = [ g 0 g 1 g 2 ] T , d = [ d 0 d 1 d 2 d 3 ] T g=\left[\begin{array}{lll}{g_{0}} & {g_{1}} & {g_{2}}\end{array}\right]^{T}, d=\left[\begin{array}{llll}{d_{0}} & {d_{1}} & {d_{2}} & {d_{3}}\end{array}\right]^{T} g