阅读论文(3)VGG:Very Deep Convolutional Networks for Large-Scale Image Recognition
arXiv:1409.1556
参考:
https://www.bilibili.com/video/BV1Ao4y117Pd/?spm_id_from=333.999.0.0
4.2 使用pytorch搭建VGG网络_哔哩哔哩_bilibili
VGG模型
VGG结构共有5个VGG块,主要模型为VGG-16和VGG-19,分别对应16层和19层结构(包括全连接层),所有卷积层均使用3x3的卷积核,每一个VGG块由若干相同的卷积层构成

VGG核AlexNet的比较,相当于是将AlexNet一部分抽象出来形成VGG块,然后堆叠VGG块以增加模型层数

复现(pytorch)

可以看到每一个VGG块中保持图像的长宽不变,由于kernel size = 3,根据公式计算得padding = 1
同时块内卷积层之间通道数也是相同的
为了使得一个文件能够实现不同架构的VGG模型(VGG16、VGG19...),可以将不同的部分抽象出来,公用相同的部分,创建模型时声明具体的要求(参数)即可。
实现代码如下
model.py
import torch
from torch import nn
# cfgs字典记录了不同层的VGG模型
# 数字表示卷积核的个数, “M”表示池化层
cfgs = {
'vgg11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'vgg13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'vgg16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
'vgg19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
}
# 不同层的VGG模型的差别是特征提取部分(卷积层),模型分类部分都相同(3层全连接)
# 因此把VGG特征提取部分抽象出来,定义make_features,根据传入配置,构建不同的特征提取部分
def make_features(cfg: list):
layers = []
in_channels = 3 # 初始输入通道数,RGB 3通道
for v in cfg:
if v == 'M': # 最大池化层
layers += [nn.MaxPool2d(2, 2)]
else: # 卷积层
conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)
layers += [conv2d, nn.ReLU(True)]
in_channels = v # 更新下一层卷积输入通道数
return nn.Sequential(*layers) # * 为解包操作
class VGG(nn.Module):
# 通过初始化参数features,可以传入不同VGG模型的特征提取部分
def __init__(self, features, cla_num=1000, init_weight=False):
super(VGG, self).__init__()
self.features = features # VGG模型中特征提取部分
# VGG模型分类器
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(512 * 7 * 7, 2048),
nn.ReLU(True),
nn.Dropout(p=0.5),
nn.Linear(2048, 2048),
nn.ReLU(True),
nn.Dropout(p=0.5),
nn.Linear(2048, cla_num)
)
if init_weight:
self._initialize_weights()
def forward(self, x): # 前向传播
x = self.features(x)
x = self.classifier(x)
return x
def _initialize_weights(self): # 权重初始化
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
if m.bias is not None:
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
nn.init.normal_(m.weight, 0, 0.01)
nn.init.constant_(m.bias, 0)
def vgg(model_name='vgg16', **kwargs):
try:
cfg = cfgs[model_name]
except:
print("Warning: model number {} is not in cfgs dict!".format(model_name))
exit(-1)
model = VGG(make_features(cfg), **kwargs) # *kwargs是可变参数,包括cla_num和init_weights
return model
在需要创建网络模型时,只需要调用vgg函数并声明参数即可
model_name = "vgg16"
net = vgg(model_name, cla_num=5, init_weights=True)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2022-02-08 分治
2022-02-08 快速幂&矩阵快速幂
2022-02-08 poj1328:Radar Installation——区间贪心
2022-02-08 poj3104:Drying——贪心(二分+判定)
2022-02-08 poj2456:Aggressive cows——贪心(二分+判定)