PyTorch 实现经典模型3:VGG
VGG
网络结构
代码
1) 导入必需的包
# 1) 导入必需的包
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.transforms as transforms
2) 搭建网络模型
# 2) 搭建网络模型
class VGG(nn.Module):def __init__(self):super(VGG, self).__init__()self.layer11 = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=1, padding=1)self.layer12 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, padding=1)self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)self.layer21 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=1)self.layer22 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, stride=1, padding=1)self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)self.layer31 = nn.Conv2d(in_channels=128, out_channels=256, kernel_size=3, stride=1, padding=1)self.layer32 = nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1)self.layer33 = nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1)self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2)self.layer41 = nn.Conv2d(in_channels=256, out_channels=512, kernel_size=3, stride=1, padding=1)self.layer42 = nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1)self.layer43 = nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1)self.pool4 = nn.MaxPool2d(kernel_size=2, stride=2)self.layer51 = nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1)self.layer52 = nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1)self.layer53 = nn.Conv2d(in_channels=512, out_channels=512, kernel_size=3, stride=1, padding=1)self.pool5 = nn.MaxPool2d(kernel_size=2, stride=2)self.fc1 = nn.Linear(7*7*512, 4096)self.fc2 = nn.Linear(4096, 4096)self.fc3 = nn.Linear(4096, 1000)def forward(self, x):x = self.pool1(nn.ReLU(self.layer12(nn.ReLU(self.layer11(x)))))x = self.pool2(nn.ReLU(self.layer22(nn.ReLU(self.layer21(x)))))x = self.pool3(nn.ReLU(self.layer33(nn.ReLU(self.layer32(nn.ReLU(self.layer31(x)))))))x = self.pool4(nn.ReLU(self.layer43(nn.ReLU(self.layer42(nn.ReLU(self.layer41(x)))))))x = self.pool5(nn.ReLU(self.layer53(nn.ReLU(self.layer52(nn.ReLU(self.layer51(x)))))))x = x.view(-1,7*7*512)x = self.fc1(x)x = self.fc2(x)x = self.fc3(x)return x
3) 导入使用的数据集、网络结构、优化器、损失函数等
4) 训练模型
5) 保存模型结构参数
6) 加载模型并测试模型效果
论文几点注意
感受野
感受野(Receptive Field)的定义是卷积神经网络每一层输出的特征图(feature map)上的像素点在输入图片上映射的区域大小。通俗解释就是特征图上的一个点跟原图上有关系的点的区域。
感受野被称作是CNN中最重要的概念之一,目标检测流行的算法如 SSD,Faster RCNN 和 prior box 和 anchor box 的设计都是以感受野为依据做的设计。
思考:
- 如果conv1:5x5 stride=1,valid感受野是多少?
结论:
- 一个卷积核(5x5)感受野大小与两个3x3卷积核感受野等效,以此类推三个3x3卷积核感受野与一个7x7卷积核等效。
感受野计算公式:
rn=rn−1+(kn−1)∏i=1n−1sir_n=r_{n-1}+(k_n-1)\prod_{i=1}^{n-1}s_irn=rn−1+(kn−1)i=1∏n−1si
其中,rn−1r_{n-1}rn−1:上一层感受野大小;knk_nkn:本层卷积核尺寸;sis_isi:卷积步幅。
还有写作其他形式
RFl+1=RFl+(kernal_size−1)∗strideRF_{l+1}=RF_l+(kernal\_size-1)*strideRFl+1=RFl+(kernal_size−1)∗stride
eg:(原图感受野大小为 1)
卷积层 | 卷积核 | 步长 | 卷积方式 | 感受野大小 |
---|---|---|---|---|
conv1: | 3x3 | stride=1 | valid | 1+(3-1)=3 |
conv2: | 3x3 | stride=1 | valid | 3+(3-1)*1=5 |
conv3: | 3x3 | stride=1 | valid | 5+(3-1)*1*1=7 |
conv4: | 3x3 | stride=1 | valid | 7+(3-1)*1*1*2=11 |
maxp: | 2x2 | stride=1 | valid | 11+(2-1)*1*1*2*1=13 |
注意:感受野这里计算理论值,实际起作用的感受野大小小于理论感受野。
3*3卷积核,1*1卷积核
为什么使用3*3卷积核?
- 深度更深且增加了非线性;
3个3*3卷积核感受野与一个7*7卷积核感受野等效,但是三个3*3卷积之间加入了激活函数,与仅适用一个7*7卷积核相比,深度更深且增加了非线性。 - 参数量减少。
假设输入数据通道大小为C,3个C通道的3*3卷积核参数量为 3*(C*3*3*C)=27C*C。1个C通道的7*7卷积核参数量为C*7*7*C=49C*C。
1*1卷积核的作用?
- 一种为决策增加非线性因素的方式;
- 调整网络维度扩维或缩小维度。
eg:mobilenet使用1*1卷积核来扩维;
resnet使用1*1卷积核来减小维度。
VGG 网络特点
- 小卷积核
VGG使用多个小卷积核(3*3) 的卷积层代替大的卷积层,一方面可以减少参数,另一方面相当于进行了更多的非线性映射,以增加网络的拟合/表达能力。 - 小池化核
相比 AlexNet 的 3*3 池化核,VGG 全部采用 2*2 的池化核。 - 层数更深
VGG常用结构层为 16 层,19 层(仅计算conv,fc层),AlexNet 为 8 层(5个conv,3个fc)。 - 全连接转卷积
网络测试阶段将训练阶段的是三个全连接替换为三个卷积,测试时重用训练时的参数,使得测试得到的全卷积网络因为无全连接的限制,因而可以接收任意宽或高为输入。
[Integrated Recognition Localization and Detection using Convolutional Networks]
卷积层替换全连接层
全连接层计算公式为:fc=wT+bfc=w^T+bfc=wT+b。假设输入到全连接层特征大小为7x7
x5,输出特征大小为1000x1.首先将输入特征变为一个列向量。
7∗7∗5→(245,1)则x大小为(245,1)7*7*5 \rightarrow (245,1)\\ 则\ x\ 大小为(245,1)7∗7∗5→(245,1)则 x 大小为(245,1)
然后与全连接层权重相乘,偏置相加
w大小为(245,100)b大小为(1000∗1)w\ 大小为(245,100)\\ b\ 大小为(1000*1)w 大小为(245,100)b 大小为(1000∗1)
假如测试时输入的特征大小为 14x14x5,需要输出的特征仍为 1000x1。xxx大小变为(980,1)。而此时www大小为(245,1000),会出现尺寸不匹配问题。
而如果使用卷积层,使用 1000 个 7x7x5 的卷积代替 fc 层,卷积参数量为 7x7x5
x1000 与 fc 层参数量相同,所以可以将 fc 层学习到的参数赋给卷积层。
假设输入特征为 7x7x5,令 stride=1。最后输出尺度为 [1,1,1,1000] 可以降维为 [1,1000]。
如果输入特征为 14x14x5,最后得到特征为 [1,2,2,1000] 即为一个 scoremap,我们对它求平均得到 [1,1000] 向量。
微调(Fine-tuning) 概念
使用预训练的神经网络模型,来训练我们自己的数据集合。使用训练好的权重来初始化我们的网络,而不是随机初始化。在实践中,我们通常不会完全从头开始训练DCNN,这是因为有能满足深度网络需求的足够大小的数据集相当少见。作为代替,常见的是在一个大型数据集上预训练一个DCNN,然后使用这一训练的DCNN的权重作为初始设置或作为相关任务的固定特征提取器。
什么情况下使用?
- 自己设计的网络不好用,精度太低;
- 数据集合相似但是数据量小;
- 自己的计算资源不够。
为什么微调会有效?
- 神经网络浅层学习的通用特征是基础特征,如边缘,轮廓颜色等特征;
- 深层是针对特定数据更抽象的特征,对于人脸来说可能就是某个人的脸;
- 全连接层就是对特征进行组合并评分分类。
我们可以利用网络前几层学到的通用特征,仅让网络学习数据的抽象特征,节省资源和时间。
微调(Fine-tuning):迁移学习策略取决于多种因素,但是最重要的两个是新数据量的大小及新数据集与原数据集的相似度。以下为4种主要情景:
- 新数据量小,内容上相似:
只需训练最后的输出层,即最后一层,因为可能分类的数量不同,最后一层需要做修改。 - 新数据量大,内容上相似:
这是最理想的情况,我们可以微调整个网络,因为数据量大不用担心过拟合。 - 新数据量小,内容上不同:
由于数据较小,且相似度低,这种情况微调效果不是很好,可以尝试冻结前边大部分卷积层,重新训练网络的高层卷积层及全连接层。 - 新数据量大,内容上不同:
由于数据集很大,且相似度比较低,最好不要使用预训练模型,从头开始训练整个网络。
Ref
- 论文官方地址
- VGG系列(Pytorch实现)
- 【PyTorch】PyTorch搭建基础VGG16网络
PyTorch 实现经典模型3:VGG相关推荐
- PyTorch 实现经典模型2:AlexNet
AlexNet 网络结构 论文总结 成功使用ReLU作为CNN的激活函数,并验证效果在较深的网络中超过了Sigmoid.成功解决了Sigmoid在网络较深时的梯度弥散问题. 训练时使用Dropout随 ...
- PyTorch 实现经典模型6:RCNN (Fast RCNN, Faster RCNN)
RCNN (Fast RCNN, Faster RCNN) 适用范围 图像分类(Image classification) 目标检测(Object detection) 网络结构 代码 Ref R-C ...
- PyTorch 实现经典模型5:ResNet
ResNet 网络结构 代码 #------------------------------用50行代码搭建ResNet---------------------------------------- ...
- PyTorch 实现经典模型4:GoogLeNet
GoogLeNet 创新点: 通过多种卷积核叠加网络复杂性 学习多种卷积 提升计算效率 GoogLeNet网络深度达到22层 1x1卷积降低维度 降低计算量,提升计算效率 网络结构 代码 import ...
- PyTorch 实现经典模型1:LeNet5
模型:LeNet5 网络结构 符号说明 网络参数 代码实现 1) 导入必需的包 2) 搭建网络模型 3) 导入使用的数据集 4) 训练模型 5) 保存模型 6) 测试模型效果 所遇错误 '_Incom ...
- PyTorch 实现经典模型8:FCN
FCN 网络结构 代码 class fcn(nn.Module):def __init__(self, num_classes):super(fcn, self).__init__()self.sta ...
- PyTorch 实现经典模型7:YOLO (v1, v2, v3, v4)
YOLO (v1, v2, v3, v4) 网络结构 YOLO v3 网络结构 代码 Ref <机器爱学习>YOLO v1深入理解 <机器爱学习>YOLOv2 / YOLO90 ...
- PyTorch Hub发布获Yann LeCun强推!一行代码调用经典模型
作者 | Team PyTorch 译者 | Monanfei 责编 | 夕颜 出品 | AI科技大本营(ID: rgznai100) 导读:6月11日,Facebook PyTorch 团队推出了全 ...
- Facebook 发布 PyTorch Hub:一行代码实现经典模型调用!
作者 | Team PyTorch 译者 | Monanfei 责编 | 夕颜 出品 | AI科技大本营(ID: rgznai100) 6月11日,Facebook PyTorch 团队推出了全新 A ...
最新文章
- VS Code - Debugger for Chrome调试JavaScript的两种方式
- 我花 1 分钟写了一段爬虫,帮助小姐姐解放了双手
- 12036火车票小工具,希望大家都能顺利回家
- [JavaWeb-JDBC]JDBC概念
- Java 这么卷,要转 Go 吗?
- WCF开发中遇到的问题及解决系列(一):运行WCF客户端时碰到错误“AddressAlreadyInUseException”...
- HAR with Python WebDriver and BrowserMob Proxy
- Myeclipse2017破解:成功解决me Trial expired 0 days ago mgeclipse It's now time to buy the best IDE for yo
- 正余弦转化之诱导公式:“奇变偶不变、符号看象限”
- 第二课——如何有逼格地打字
- 债券价格和到期收益率的关系_什么是到期收益率 到期收益率与债券价格的关系...
- go.php跳转外部浏览器,Go调用浏览访问url链接
- JAVA_数字转大写
- 计算机网口在什么位置,电脑网线插路由器哪个口?
- 3.6Python之sys模块
- 【回炉重造】——反射
- 遇到程序员不修改bug时怎么办?我教你
- 十、什么是临界资源及如何访问临界资源
- 中M2018春C入门和进阶练习集
- 过河问题(牛虎过河、商人仆人过河、农夫妖怪过河、传教士野人过河)(第2届第2题)
热门文章
- java中的builder模式
- 生成元(Digit Generator ,ACM/ICPC Seoul 2005 ,UVa 1583)
- 迷你DVD管理器项目
- jquery实现页面加载时删除特定class 的div内前三个字符
- retain copy(浅复制) mutablecopy (深复制)
- Oracle Database 12c(12.1) Beta已经开始内部测试
- UA MATH571A QE练习 R语言 单因子试验的回归分析
- UA MATH571A R语言回归分析实践 多元回归2 医疗费用的决定
- 超图三维数据处理学习摘要1
- 在winform中使用三层架构学习总结