Deep Learning with Pytorch 中文简明笔记 第八章 Using convolutions to generalize

Deep Learning with Pytorch 中文简明笔记 第八章 Using convolutions to generalize

Pytorch作为深度学习框架的后起之秀,凭借其简单的API和简洁的文档,收到了越来越多人的关注和喜爱。本文主要总结了 Deep Learning with Pytorch 一书第八章[Using convolutions to generalize]的主要内容,并加以简单明了的解释,作为自己的学习记录,也供大家学习和参考。

主要内容

  • 理解卷积
  • 建立卷积神经网络
  • 创建定制nn.Module的子类
  • module和API的不同
  • 设计神经网络的建议

1. 卷积

主要介绍了什么是卷积,卷积的运算操作

在这里插入图片描述

卷积有一些特性:

  • 对相邻像素的局部操作
  • 平移不变性
  • 相对于其他方式有更少的参数

2. 卷积的实现

在Pytorch中,torch.nn模型提供了一维、二维和三维卷积,其中nn.Conv1d用于序列,nn.Conv2d用于图像,nn.Conv3d用于立方体或者视频。

对于CIFAR-10数据集,应当使用nn.Conv2d。在nn.Conv2d中需要传递的参数有,输入特征数目(通道数目),输出特征数目和kernel的大小。例如定义一个输入为3,输出为16,kernel为3×3的卷积层。

# In[11]: 
conv = nn.Conv2d(3, 16, kernel_size=3) 
conv

# Out[11]: 
Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1))

实际上有多少个卷积核呢,应该16×3个。相当于对于原图片的每一个通道,分别用16个不同卷积核去做卷积。也可以理解为原来的每一个channel,运算完之后编程16个channel。那么权重的数目即为16×3×3×3。bias的数目为16。

# In[12]: 
conv.weight.shape, conv.bias.shape

# Out[12]: 
(torch.Size([16, 3, 3, 3]), torch.Size([16]))

尝试对图片做一下卷积。

# In[13]: 
img, _ = cifar2[0] 
output = conv(img.unsqueeze(0)) 
img.unsqueeze(0).shape, output.shape

# Out[13]: 
(torch.Size([1, 3, 32, 32]), torch.Size([1, 16, 30, 30]))

# In[15]: 
plt.imshow(output[0, 0].detach(), cmap='gray') 
plt.show()

在这里插入图片描述

2.1 卷积的Padding

由于卷积运算的特殊性,会导致图片变小。对于奇数大小的kernel,图片的高度和宽度会减小(kernel_size -1) / 2,在上面的例子中即减小1个像素。这里可以使用padding来解决这个问题。

# In[16]: 
conv = nn.Conv2d(3, 1, kernel_size=3, padding=1) 
output = conv(img.unsqueeze(0)) 
img.unsqueeze(0).shape, output.shape

# Out[16]: 
(torch.Size([1, 3, 32, 32]), torch.Size([1, 1, 32, 32]))

在这里插入图片描述

使用padding的原因有两个,一是避免卷积操作影响图片尺寸,二是对于一些网络结构,我们希望图片经过卷积前后的大小一致,以便进行两者的加减操作。

2.2 卷积的简单理解

对卷积核手动设置权重和偏置

# In[17]: 
with torch.no_grad(): 
	conv.bias.zero_()
with torch.no_grad():
	conv.weight.fill_(1.0 / 9.0)

# In[18]: 
output = conv(img.unsqueeze(0)) 
plt.imshow(output[0, 0].detach(), cmap='gray') 
plt.show()

简单来看,就是对卷积核所在范围内的图像取平均

在这里插入图片描述

下面换另一个卷积核

# In[19]: 
conv = nn.Conv2d(3, 1, kernel_size=3, padding=1)
with torch.no_grad(): 
	conv.weight[:] = torch.tensor([[-1.0, 0.0, 1.0], [-1.0, 0.0, 1.0], [-1.0, 0.0, 1.0]])
	conv.bias.zero_()

从卷积核来看,卷积核右侧的权重大,左侧的权重小,对于垂直的边缘响应应该更大,

在这里插入图片描述

结果确实如此,实际上上面的卷积核就是垂直边缘检测的卷积核。而卷积神经网络,从一定程度上就是学习到不同的卷积核,来从图片中提取并组合各种特征,来达到最终的目的。

在这里插入图片描述

2.3 更进一步:深度和池化(pooling)

对于小的图片,小的卷积核就足够提取到一些特征。而当图片变大时,小的卷积核就显得不够了,但是使用更大的卷积核意味着更大的参数量,更臃肿的模型。有没有什么办法可以在大图像时依旧使用小卷积核呢?解决问题的方法就是池化。

池化是的基本思想就是下采样,将周围几个像素合并为一个像素。大致可分为:

  • 平均值池化(average pooling),周围像素取平均值作为新像素。
  • 最大值池化(max pooling),周围像素取最大值作为新像素。

此外,可以以采用有间隔的卷积核。这行方法都会损失一些信息,但是更重要是保留图片最重要信息,供下层卷积层进一步提取高级特征。图中展示了最大值池化的详细步骤。

在这里插入图片描述

# In[21]: 
pool = nn.MaxPool2d(2) 
output = pool(img.unsqueeze(0))
img.unsqueeze(0).shape, output.shape

# Out[21]: 
(torch.Size([1, 3, 32, 32]), torch.Size([1, 3, 16, 16])
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值