im2col解析1
在cs231n
课程Convolutional Neural Networks: Architectures, Convolution / Pooling Layers中提到使用矩阵乘法方式完成卷积层及池化层操作,同时在Assignment #2: Fully-Connected Nets, Batch Normalization, Dropout, Convolutional Nets中给出了一个卷积层转全连接层的实现 - im2col.py
im2col
表示将滤波器局部连接矩阵向量化为列向量(column vector
),在行方向进行堆叠,最终得到2-D
矩阵
im2col.py
使用 花式下标求解 的方式,让我觉得应该写篇文章好好学习一下
本文介绍一些numpy
实现,下一篇介绍im2col
实现,第三篇实现im2row
,第四篇介绍另一种实现图像和行向量互换的方式,最后实现池化层图像和行向量的互换pool2row
- 数组扩展
- 数组变形
- 数组填充
- 维数转换
- 矩阵提取
- 数据叠加
数组扩展
numpy
提供了numpy.repeat以及numpy.tile实现基于数组原先数据的扩展
numpy.repeat
会重复数组中的每个元素
numpy.repeat(a, repeats, axis=None)
a
表示输入数组repeats
表示重复次数axis
表示沿着哪个轴进行重复,axis=0
表示沿着列,axis=1
表示沿着行(注意:axis
不能超出a
的维度)。默认会将输入数组拉平(flattened
),再沿着行进行重复
1 | # 对1-D数组进行扩展 |
1 | # 对2-D数组进行扩展 |
np.repeat
对逐元素进行重复,而np.tile
对逐数组进行重复
numpy.tile(A, reps)
A
表示输入数组reps
表示重复次数
有两种情况
- 当
A.ndim < reps.ndim
时,输入数组会扩展到reps相同维数,比如A.shape=(3,)
,那么扩展到2-D
就是(3,) -> (1,3)
,扩展到3-D
就是(3,) -> (1,1,3)
- 当
A.ndim > reps.ndim
时,reps
会先扩展到和A相同维数,扩展维数用1
填充,比如A.shape = (2,3,4,5),reps.shape = (2,3)
,那么reps
首先扩展到(1,1,2,3)
,再对A
进行扩展,结果为(2,3,8,15)
1 | >>> a = np.arange(3) |
1 | # A.ndim = reps.ndim,不改变数组维数,沿着维数方向进行扩展 |
1 | # A.ndim < reps.ndim,扩展A维数,再进行扩展 |
1 | # A.ndim > reps.ndim, 先扩展reps维度,再扩展A数组 |
数组变形
numpy
提供了方法numpy.reshape用于数组变形
numpy.reshape
在不改变数组数据的情况下变换数组大小
numpy.reshape(a, newshape, order='C')
a
表示输入数组newshape
表示新的数组大小,其中一个维度值可以为-1
,这样该维度大小将通过数组长度和剩余维数判断得出。注意:新的数组大小应该和输入数组大小一致order
表示索引读取元素顺序,默认读取方式和C
语言一致(大多数情况下就是这种方式):最后一个轴索引(the last axis index
)变化最快,第一个轴索引(the first axis index
)变化最慢。比如2-D
数组,先变化第二个轴,也就是按行读取,再变化第一个轴,也就是按列读取
1 | >>> x = np.arange(24) |
数组填充
在进行卷积神经网络计算时,需要零填充操作,numpy
提供了numpy.pad操作
numpy.pad(array, pad_width, mode, **kwargs)
array
表示输入数组pad_width
表示每轴填充的宽度,其格式为((before_1, after_1), … (before_N, after_N))
。如果所有轴都使用相同填充宽度,可以简化为(before, after)
,或者(pad,)
mode
表示填充模式,最常用的是constant
- 填充一个常数,默认为0
constant_values
是可选参数,表示常数值
1 | >>> a = np.arange(1, 5).reshape(2,2) |
1 | # 以下三种方法等价 |
1 | #可以指定不同的轴填充个数 |
维数转换
numpy
提供了numpy.transpose用于维数转换
numpy.transpose(a, axes=None)
a
表示输入数组axes
表示待转换的轴,是int
类型的元组(tuple
)
1 | # 2维数组转换相当于矩阵转置操作 |
1 | >>> x = np.arange(24).reshape(2,3,4) |
矩阵提取
当在多维数组中取一个2
维矩阵时,通常会使用切片方式
1 | >>> a |
还可以先获取矩阵对应数据下标,再进行计算
1 | >>> x |
1 | # 结合矩阵扩展和维数转换方法 |
数据叠加
参考:np.add.at indexing with array
numpy
提供函数numpy.add.at用于批量添加数据
ufunc.at(a, indices, b=None)
a
表示目标数组indices
表示指定下标,可以是数组或者元组结构b
是添加的数据,可以是标量或者数组,必须能够在a
上可广播(broadcastable
)
np.add.at
函数功能等同于a[indices]=b
,区别在于np.add.at
执行无缓冲即时操作(unbuffered in place operation
),也就是说同一个下标可以累加多次
1 | x = np.arange(5) |
1 | >>> x = np.zeros((2,3)) |