numpy可实现卷积转换成矩阵乘法算法,但是使用np.lib.stride_tricks.as_strided这个函数可以实现更高效的卷积算法
np.lib.stride_tricks.as_strided(x, shape=None, strides=None, subok=False, writeable=True)
- x: 原数组
- shape: 变换之后数组的shape
- strides: 给定如何从原数组变换得到结果
那么如何确定strides呢?首先从一个简单的例子开始,假设有一矩阵X
X
=
[
1
2
3
4
5
6
7
8
9
]
X = \left[ \begin{array}{} 1&2&3\\ 4&5&6\\ 7&8&9 \end{array} \right]
X=
147258369
对矩阵X进行2x2的卷积操作,最重要的是拿到每次卷积运算的矩阵block,相当于将矩阵X,转化为一个2x2x2x2的矩阵A
A = [ [ 1 2 4 5 ] [ 2 3 5 6 ] [ 4 5 7 8 ] [ 5 6 8 9 ] ] A = \left[\begin{array}{} \left[\begin{array}{} 1&2\\ 4&5 \end{array} \right] & \left[\begin{array}{} 2&3\\ 5&6 \end{array} \right]\\\\ \left[\begin{array}{} 4&5\\ 7&8 \end{array} \right] & \left[\begin{array}{} 5&6\\ 8&9 \end{array} \right] \end{array} \right] A= [1425][4758][2536][5869]
如下(i,j,k,x) -> (i,j,k,x+1),在x维度上移动1,移动在原X矩阵中要移动4 bytes,所以strides为 (*, *, *, 4)
如下(i,j,k,x) -> (i,j,k+1,x),在k维度上移动1,移动在原X矩阵中要移动12 bytes,所以strides为 (*, *, 12, 4)
如下(i,j,k,x) -> (i,j+1,k,x),在k维度上移动1,移动在原X矩阵中要移动4 bytes,所以strides为 (*, 4, 12, 4)
如下(i,j,k,x) -> (i+1,j,k,x),在k维度上移动1,移动在原X矩阵中要移动12 bytes,所以strides为 (12, 4, 12, 4)