从头学pytorch(十六):VGG NET
VGG
AlexNet在Lenet的基础上增加了几个卷积层,改变了卷积核大小,每一层输出通道数目等,并且取得了很好的效果.但是并没有提出一个简单有效的思路.
VGG做到了这一点,提出了可以通过重复使⽤简单的基础块来构建深度学习模型的思路.
论文地址:https://arxiv.org/abs/1409.1556
vgg的结构如下所示:

上图给出了不同层数的vgg的结构.也就是常说的vgg16,vgg19等等.
VGG BLOCK
vgg的设计思路是,通过不断堆叠3x3的卷积核,不断加深模型深度.vgg net证明了加深模型深度对提高模型的学习能力是一个很有效的手段.

看上图就能发现,连续的2个3x3卷积,感受野和一个5x5卷积是一样的,但是前者有两次非线性变换,后者只有一次!,这就是连续堆叠小卷积核能提高
模型特征学习的关键.此外,2个3x3的参数数量也比一个5x5少.(2x3x3 < 5x5)
vgg的基础组成模块,每一个卷积层都由n个3x3卷积后面接2x2的最大池化.池化层的步幅为2.从而卷积层卷积后,宽高不变,池化后,宽高减半.
我们可以有以下代码:
def make_layers(in_channels,cfg):
layers = []
previous_channel = in_channels #上一层的输出的channel数量
for v in cfg:
if v == 'M':
layers.append(nn.MaxPool2d(kernel_size=2,stride=2))
else:
layers.append(nn.Conv2d(previous_channel,v,kernel_size=3,padding=1))
layers.append(nn.ReLU())
previous_channel = v
conv = nn.Sequential(*layers)
return conv
cfgs = {
'A': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'B': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'D': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
'E': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
}
cfgs定义了不同的vgg模型的结构,比如'A'代表vgg11. 数字代表卷积后的channel数. 'M'代表Maxpool
我们可以给出模型定义
class VGG(nn.Module):
def __init__(self,input_channels,cfg,num_classes=10, init_weights=True):
super(VGG, self).__init__()
self.conv = make_layers(input_channels,cfg) # torch.Size([1, 512, 7, 7])
self.fc = nn.Sequential(
nn.Linear(512*7*7,4096),
nn.ReLU(),
nn.Linear(4096,4096),
nn.ReLU(),
nn.Linear(4096,num_classes)
)
def forward(self, img):
feature = self.conv(img)
output = self.fc(feature.view(img.shape[0], -1))
return output
卷积层的输出可由以下测试代码得出
# conv = make_layers(1,cfgs['A'])
# X = torch.randn((1,1,224,224))
# out = conv(X)
# #print(out.shape)
加载数据
batch_size,num_workers=4,4
train_iter,test_iter = learntorch_utils.load_data(batch_size,num_workers,resize=224)
这里batch_size调到8我的显存就不够了...
定义模型
net = VGG(1,cfgs['A']).cuda()
定义损失函数
loss = nn.CrossEntropyLoss()
定义优化器
opt = torch.optim.Adam(net.parameters(),lr=0.001)
定义评估函数
def test():
acc_sum = 0
batch = 0
for X,y in test_iter:
X,y = X.cuda(),y.cuda()
y_hat = net(X)
acc_sum += (y_hat.argmax(dim=1) == y).float().sum().item()
batch += 1
#print('acc_sum %d,batch %d' % (acc_sum,batch))
return 1.0*acc_sum/(batch*batch_size)
训练
num_epochs = 3
def train():
for epoch in range(num_epochs):
train_l_sum,batch,acc_sum = 0,0,0
start = time.time()
for X,y in train_iter:
# start_batch_begin = time.time()
X,y = X.cuda(),y.cuda()
y_hat = net(X)
acc_sum += (y_hat.argmax(dim=1) == y).float().sum().item()
l = loss(y_hat,y)
opt.zero_grad()
l.backward()
opt.step()
train_l_sum += l.item()
batch += 1
mean_loss = train_l_sum/(batch*batch_size) #计算平均到每张图片的loss
start_batch_end = time.time()
time_batch = start_batch_end - start
print('epoch %d,batch %d,train_loss %.3f,time %.3f' %
(epoch,batch,mean_loss,time_batch))
print('***************************************')
mean_loss = train_l_sum/(batch*batch_size) #计算平均到每张图片的loss
train_acc = acc_sum/(batch*batch_size) #计算训练准确率
test_acc = test() #计算测试准确率
end = time.time()
time_per_epoch = end - start
print('epoch %d,train_loss %f,train_acc %f,test_acc %f,time %f' %
(epoch + 1,mean_loss,train_acc,test_acc,time_per_epoch))
train()
全连接层4096个神经元,参数太多,训练缓慢.4G的GTX 1050显卡,训练一个epoch大概一个多小时.
完整代码:https://github.com/sdu2011/learn_pytorch
batch=4,收敛极慢,迭代次数不够的话,欠拟合严重.在训练集上的train accuracy也很低.
由于全连接层的存在,参数极多,造成训练慢,显存占用多,导致batch_size调不大.模型修改为
class VGG(nn.Module):
def __init__(self,input_channels,cfg,num_classes=10, init_weights=True):
super(VGG, self).__init__()
self.conv = make_layers(input_channels,cfg) # torch.Size([1, 512, 7, 7])
self.fc = nn.Sequential(
nn.Linear(512*7*7,512),
nn.ReLU(inplace=True), #inplace作用:节省显存 https://www.cnblogs.com/wanghui-garcia/p/10642665.html
nn.Dropout(p=0.5),
nn.Linear(512,512),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5),
nn.Linear(512,num_classes)
)
def forward(self, img):
feature = self.conv(img)
output = self.fc(feature.view(img.shape[0], -1))
return output
全连接层调整为512个神经元.batch_size调到16.训练快多了.
从头学pytorch(十六):VGG NET的更多相关文章
- 从头学pytorch(十二):模型保存和加载
模型读取和存储 总结下来,就是几个函数 torch.load()/torch.save() 通过python的pickle完成序列化与反序列化.完成内存<-->磁盘转换. Module.s ...
- 从头学pytorch(十五):AlexNet
AlexNet AlexNet是2012年提出的一个模型,并且赢得了ImageNet图像识别挑战赛的冠军.首次证明了由计算机自动学习到的特征可以超越手工设计的特征,对计算机视觉的研究有着极其重要的意义 ...
- 从头学pytorch(十八):GoogLeNet
GoogLeNet GoogLeNet和vgg分别是2014的ImageNet挑战赛的冠亚军.GoogLeNet则做了更加大胆的网络结构尝试,虽然深度只有22层,但大小却比AlexNet和VGG小很多 ...
- 从头学pytorch(十九):批量归一化batch normalization
批量归一化 论文地址:https://arxiv.org/abs/1502.03167 批量归一化基本上是现在模型的标配了. 说实在的,到今天我也没搞明白batch normalize能够使得模型训练 ...
- 从头学pytorch(十四):lenet
卷积神经网络 在之前的文章里,对28 X 28的图像,我们是通过把它展开为长度为784的一维向量,然后送进全连接层,训练出一个分类模型.这样做主要有两个问题 图像在同一列邻近的像素在这个向量中可能相距 ...
- 从头学pytorch(一):数据操作
跟着Dive-into-DL-PyTorch.pdf从头开始学pytorch,夯实基础. Tensor创建 创建未初始化的tensor import torch x = torch.empty(5,3 ...
- 从头学pytorch(六):权重衰减
深度学习中常常会存在过拟合现象,比如当训练数据过少时,训练得到的模型很可能在训练集上表现非常好,但是在测试集上表现不好. 应对过拟合,可以通过数据增强,增大训练集数量.我们这里先不介绍数据增强,先从模 ...
- 从头学pytorch(二十):残差网络resnet
残差网络ResNet resnet是何凯明大神在2015年提出的.并且获得了当年的ImageNet比赛的冠军. 残差网络具有里程碑的意义,为以后的网络设计提出了一个新的思路. googlenet的思路 ...
- 从头学pytorch(二十二):全连接网络dense net
DenseNet 论文传送门,这篇论文是CVPR 2017的最佳论文. resnet一文里说了,resnet是具有里程碑意义的.densenet就是受resnet的启发提出的模型. resnet中是把 ...
随机推荐
- 通过Ajax提交form表单来提交上传文件
Ajax 提交form方式可以将form表单序列化 然后将数据通过data提交至后台,例如: $.ajax({ url : "http://localhost:8080/" ...
- vue tab栏缓存解决跳转页面后返回的状态保持
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8& ...
- 网易大数据平台的Spark技术实践
网易大数据平台的Spark技术实践 作者 王健宗 网易的实时计算需求 对于大多数的大数据而言,实时性是其所应具备的重要属性,信息的到达和获取应满足实时性的要求,而信息的价值需在其到达那刻展现才能利益最 ...
- Python--day22--面向对象的交互
Python里面自带的类和对象: 类名的作用: 类里面的与属性相关的对象self的运用: 实例化:就是创建一个对象 调用方法,类名.方法名(对象名) 执行步骤: 简写:alex.walk()等价于Pe ...
- 【js】vue 2.5.1 源码学习 (九) 响应数组对象的变
大体思路(八) 本节内容: 1.Observe 如何响应数组的变化 代理原型 数组变异方法 shell cacheArrProto methods 新添加的数组需要加到显示系统里面,拦截 push等的 ...
- js基础——function类型
1.函数声明方式 1)普通声明方式 function box(num1,num2){ return num1 + num2; } 2)使用变量初始化函数 var box = funct ...
- H3C 端口隔离配置举例
- Java中try catch finally执行
直接上代码实例: public static void main(String[] args) { System.out.println(test1()); } static int test1 ...
- 【b503】篝火晚会
Time Limit: 1 second Memory Limit: 50 MB [问题描述] 佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了"小教官" ...
- 牛客多校第三场 F Planting Trees
牛客多校第三场 F Planting Trees 题意: 求矩阵内最大值减最小值大于k的最大子矩阵的面积 题解: 矩阵压缩的技巧 因为对于我们有用的信息只有这个矩阵内的最大值和最小值 所以我们可以将一 ...