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- 填充一个常数,默认为0constant_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)) |