深度学习入门:Day-12

内容:

- 池化层
- 池化层和卷积层的实现

池化层

(1).池化是缩小高、长方向上的空间的运算.池化方法:

  • Max池化是从目标区域中取出最大值;
  • Average池化则是计算目标区域的平均值,只需要将上面的max–>>mean

(2)池化后的形状:
设输入图像尺寸为WxH,其中W:图像宽,H:图像高,D:通道数(图像深度),滤波器大小(FxF),S:步长,池化后输出图像大小:(若结果不是整数,可以参考上一节卷积的处理方式)

(3).池化层的特征:
- 没有要学习的参数:
池化层和卷积层不同,没有要学习的参数。池化只是从目标区域中取得最大值(或者平均值),所以不存在要学习的参数。
- 通道数不发生变化
经过池化运算,输入数据和输出数据的通道数不会发生变化。
- 对微小位置的变化具有鲁棒性(健壮)
输入数据发生微小偏差时,池化仍会返回相同的结果。因此,池化对输入数据的微小偏差具有鲁棒性。

池化层和卷积层的实现

基于im2col的展开
(1):im2col函数,将输入数据展开(将应用滤波器的区域横向展开为1列)以适合滤波器(权重)。(2):然后将卷积层的滤波器(权重)纵向展开为1列。(3):计算两个矩阵的乘积即可。

注:

  • 在滤波器的应用区域重叠的情况下,使用im2col展开后,展开后的元素个数会多于原方块的元素个数。
  • im2col的实现存在比普通的实现消耗更多内存的特点。
im2col函数
import numpy as np 
def im2col(input_data, filter_h, filter_w, stride=1, pad=0):
	"""
	Parameters
	----------
	input_data : 由(数据量, 通道, 高, 长)的4维数组构成的输入数据,如np.random.rand(10,1,28,28)
	filter_h : 滤波器的高
	filter_w : 滤波器的长
	stride : 步幅
	pad : 填充
	Returns
	-------
	col : 2维数组
	"""
	
	N, C, H, W = input_data.shape # batch_num:批数量
	out_h = (H + 2*pad - filter_h)//stride + 1
	out_w = (W + 2*pad - filter_w)//stride + 1

	img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')#填充阵列
	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
## 案例
x1=np.random.rand(1,3,7,7)
col1=im2col(x1,5,5,stride=1,pad=0)
print(col1.shape)#(9, 75)
x2=np.random.rand(10,3,7,7)
col2=im2col(x2,5,5,stride=1,pad=0)
print(col2.shape)#(90, 75)

源码学习:
np.pad#填充阵列

参数解释:
第一个参数array是待填充数组
第二个参数pad_with是:
Number of values padded to the edges of each axis(填充到每个轴的边的值数)。
((before_1, after_1), ... (before_N, after_N)) unique pad widthsfor each axis.
before = after = pad width for all axes。
填充的形状,
(1)1d--->>>(2,3)表示前面两个,后面三个,填充的元素取决于填充的方法
(2)维的见下图
第三个参数是填充的方法
填充方法:
constant---->>>连续一样的值填充,有关于其填充值的参数。
constant_values=(x, y)时前面用x填充,后面用y填充。缺参数是为0000。。。
edge--->>>用边缘值填充
linear_ramp--->>>边缘递减的填充方式
maximum, mean, median, minimum分别用最大值、均值、中位数和最小值填充
reflect, symmetric都是对称填充。前一个是关于边缘对称,后一个是关于边缘外的空气对称
wrap--->>>用原数组后面的值填充前面,前面的值填充后面
也可以有其他自定义的填充方法

以多维(常数填充)填充为例,第二个参数(元组的个数)的形状与array的形状一致;
图中通过不同的颜色标记了各个参数对应的操作。

  • #reshape(FN,-1)表示reshape会自动计算-1维度上的元素个数,以使多维数据的元素个数前后一致。
  • #transpose更改多维数据轴的顺序,其中的数值为索引。

im2col函数的逆:col2im

def col2im(col, input_shape, filter_h, filter_w, stride=1, pad=0):
    """

    Parameters
    ----------
    col :
    input_shape : 输入数据的形状(例:(10, 1, 28, 28))
    filter_h :
    filter_w
    stride
    pad

    Returns
    -------

    """
    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]

卷积层

卷积层的类:

class Convolution:
	def __init__(self,W,b,stride=1,pad=0):
		self.W=W
		self.b=b
		self.stride=stride
		self.pad=pad
	def forward(self,x):
		FN,C,FH,FW=self.W.shape   #FN 表示滤波器的数量
		N,C,H,W=x.shape
		out_h=int(1+(H+2*self.pad-FH)/self.stride)
		out_w=int(1+(W+2*self.pad-FW)/self.stride)
		
		col=im2col(x,FH,FW,self.stride,self.pad)
		col_W=self.W.reshape(FN,-1).T#滤波器的展开  
		out=np.dot(col,col_W)+self.b
		
		out=out.reshape(N,out_h,out_w,-1).transpose(0,3,1,2)
		return out

池化层的实现:

池化层的实现和卷积层相同,都使用im2col展开输入数据。
池化情况下,在通道方向上是独立的,这一点与卷积层不同。

class Pooling:
	def __init__(self,pool_h,pool_w,stride=1,pad=0):
		self.pool_h=pool_h
		self.pool_w=self_w
		self.stride=stride
		self.pad=pad
	def forward(self,x):
		N,C,H,W=x.shape
		out_h=int(1+(H-self.pool_h)/self.stride)
		out_w=int(1+(W-self.pool_w)/self.stride)
		
		#展开(1):展开输入数据
		col=im2col(x,seel.pool_h,self.pool_w,self.stride,self.pad)
		col=col.reshape(-1,self.pool_h*self.pool_w)
		
		#最大值(2):求各行的最大值
		out=np.max(col,axis=1)
		
		#转换(3):转换为合适的输出大小
		out=out.reshape(N,out_h,out_w,C).transpose(0,3,1,2)
		return out 

关于卷积和池化的反向传播后补

参考文献:
图文并茂的Python教程-numpy.pad
图像卷积和池化操作后的特征图大小计算方法

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值