文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
反池化层的实现
我们可以通过正向传播时记录池化时最大值位置。 在反池化的时候,只把池化过程中最大激活值所在的位置坐标的值激活,其它的值置为 0 过程如下图所示:
maxpool 需要记录池化之前最大值的位置 :
im2col
im2col 函数 会考虑滤波器大小、步幅、填充,将输入数据展开为 2 维数组。池化的情况下,在通道方向上是独立的。具体地讲,如下图所示,池化的应用区域按通道单独展开。 像这样展开之后,只需对展开的矩阵求各行的最大值,并转换为合适的形状即可
- 将特征图按池化的大小展开成(-1,pool_h*pool_w ) 的形状(这里只论单张特征图),每行就是一池化的应用区域
- 记录每行最大值的位置 argmax
- 反池化时把特征图的值赋值到 0 矩阵 argmax 位置
具体思路如下图
实现代码如下:
class Reverse_Pooling:
def __init__(self,temp_data,pool_h,pool_w,stride=1,pad=0):
'''
temp_data:用于获取最大值索引,池化之前的数据
'''
self.pool_h = pool_h
self.pool_w = pool_w
self.stride = stride
self.pad = pad
self.temp_data = temp_data.numpy()
def im2col(self,input_data):
"""
input_data : 由(数据量,通道,高,长) 的 4 维数组构成的输入数据
-------
col : 2 维数组
"""
filter_h = self.pool_h
filter_w = self.pool_w
stride = self.stride
pad = self.pad
N, C, H, W = input_data.shape
out_h = (H + 2*pad - filter_h)//stride + 1 #计算池化之后的 H,W
out_w = (W + 2*pad - filter_w)//stride + 1
img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant') #进行边填充,padding
col = np.zeros((N, C, filter_h, filter_w, out_h, out_w)) #创建池化输出
for y in range(filter_h):
y_max = y + stride*out_h
for x in range(filter_w):
x_max = x + stride*out_w
col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]
col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)
return col
def col2im(self,col):
"""
col :col : 2 维数组(展开的池化层)
input_shape : 输入数据的形状(例:(10, 1, 28, 28))
"""
filter_h = self.pool_h
filter_w = self.pool_w
stride = self.stride
pad = self.pad
input_shape=self.x.shape
N,C,H,W = input_shape
out_h=(H+2*pad-filter_h)//stride+1
out_w=(W+2*pad-filter_w)//stride+1
col=col.reshape(N,out_h,out_w,C,filter_h,filter_w).transpose(0,3,4,5,1,2)
img=np.zeros((N,C,H+2*pad+stride-1,W+2*pad+stride-1))
for y in range(filter_h):
y_max = y+stride*out_h
for x in range(filter_w):
x_max = x +stride*out_w
img[:, :, y:y_max:stride, x:x_max:stride] += col[:, :, y, x, :, :]
return img[:, :, pad:H + pad, pad:W + pad]
def forward(self):
x=self.temp_data
N,C,H,W = x.shape
out_h = int(1+(H-self.pool_h)/self.stride) #计算池化后的 H,W
out_w = int(1+(W-self.pool_w)/self.stride)
#展开(1)
col = self.im2col(x) #所有特征图展开展开成(N,C,H*W)
col = col.reshape(-1,self.pool_h*self.pool_w) #(N,C,H*W)-->(N*C,H*W)
#最大值(2)
out = np.max(col,axis=1)
#取最大值坐标反向池化用
arg_max = np.argmax(col,axis=1)
self.x = x
self.arg_max = arg_max
def backward(self,dout):
self.forward()
dout = dout.numpy()
dout = dout.transpose(0,2,3,1)
pool_size = self.pool_h * self.pool_w
dmax = np.zeros((dout.size,pool_size)) #创建反池化输出
dmax[np.arange(self.arg_max.size),self.arg_max.flatten()] = dout.flatten() #对输出按索引赋值
dmax = dmax.reshape(dout.shape + (pool_size,))
dcol = dmax.reshape(dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1)
dx = self.col2im(dcol)
dx=fluid.dygraph.to_variable(dx.astype('float32'))
return dx
通过猫十二分类来了解卷积神经网络的特征学习
这里我们使用百度飞桨深度学习框架的猫十二分类数据集,看看卷积神经网络是如何学习到猫的特征的
解压数据集文件
fork 本项目后在终端粘贴下面命令(建议用 GPU 环境,CPU 很慢哦)
终端输入命令:
unzip data/data10954/cat_12_test.zip
unzip data/data10954/cat_12_train.zip
训练集一共 2161 张猫脸图片,总共分为 12 类猫脸,并且训练集已经把标注放在 train_list.txt 文件中
如图所示,前面是图片 PATH,后面是标签(有些图片不可读,我已经删除)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论