目录
n层是指可以有N个窗口3*3,填充为1的卷积层。有m个通道,这里输入和输出都是一样的。
VGG就是替换掉AlexNet整个卷积层的架构。
直径大小表示占内存,横坐标表示速度,纵坐标表示精确度。
import torch
from torch import nn
fron d2l import torch as d2l
"""VGG块"""
#该函数有三个参数,分别对应于卷积层的数量num_convs、输入通道的数量in_channels
#和输出通道的数量out_channels.
def vgg_block(num_convs,in_channels,out_channels):
layers=[]
for _ in range(convs):
layers.append(nn.Conv2d(in_channels,out_channels,kernel_size=3,padding=1))
layers.append(nn.ReLU())
in_channels=out_channels
# in channels=out channels 是为了让除了第一个的in channels外,其他的层的
#in都等于out
layers.append(nn.MaxPool2d(kernel_size=2,stride=2))
#假如输入为10,(10-2+2)/2=5每经过一个卷积块输出大小都减半。
return nn.Sequential(*layers)
#nn.Sequential的定义来看,输入要么是orderdict,要么是一系列的模型,遇到list,
#必须用*号进行转化,否则会报错
"""VGG网络"""
#原始VGG网络有5个卷积块,其中前两个块各有一个卷积层,后三个块各包含两个卷积层。
#第一个模块有64个输出通道,每个后续模块将输出通道数量翻倍,直到该数字达到512。
#由于该网络使用8个卷积层和3个全连接层,因此它通常被称为VGG-11。
#每一块可以认为是高宽减半。因为有个maxpooling,为什么有5个块呢?因为224除以5次2等于7就除不动了
conv_arch=((1,64),(1,128),(2,256),(2,512),(2,512))
#下面的代码实现了VGG-11。可以通过在conv_arch上执行for循环来简单实现。
def vgg(conv_arch):
conv_blks=[]
in_channels=1
#卷积部分
for(num_convs,out_channels) in conv_arch:
conv_blks.append(vgg_block(num_convs,in_channels,out_channels))
in_channels=out_channels
return nn.Sequential(
*conv_blks,nn.Flatten(),
#全连接部分
nn.Linear(out_channels*7*7,4096),nn.ReLU(),nn.Dropout(0.5),
#7*7是因为224除以5次后就变成了7*7
nn.Linear(4096,4096),nn.ReLU(),nn.Dropout(0.5),
nn.Linear(4096,10))
net=vgg(conv_arch)
#构建一个高度和宽度为224的单通道数据样本,以观察每个层输出的形状。
X=torch.randn(size=(1,1,224,224))
for blk in net:
X=blk(X)
print(blk.__class__.__name__,'output shape\t',X.shape)
"""结果输出:
Sequential output shape: torch.Size([1, 64, 112, 112])
Sequential output shape: torch.Size([1, 128, 56, 56])
Sequential output shape: torch.Size([1, 256, 28, 28])
Sequential output shape: torch.Size([1, 512, 14, 14])
Sequential output shape: torch.Size([1, 512, 7, 7])
Flatten output shape: torch.Size([1, 25088])
Linear output shape: torch.Size([1, 4096])
ReLU output shape: torch.Size([1, 4096])
Dropout output shape: torch.Size([1, 4096])
Linear output shape: torch.Size([1, 4096])
ReLU output shape: torch.Size([1, 4096])
Dropout output shape: torch.Size([1, 4096])
Linear output shape: torch.Size([1, 10])"""
#每个块的高度和宽度减半,最终高度和宽度都为7。最后再展平表示,送入全连接层处理。
"""训练模型"""
#由于VGG-11比AlexNet计算量更大,因此我们构建了一个通道数较少的网络,足够用于训练
#Fashion-MNIST数据集。
ratio=4
small_conv_arch=[(pair[0],pair[1]//ratio) for pair in conv_arch]
#conv_arch里面的参数就是需要的卷积层数和输出通道,small_conv_arch就是把输出通道数
#除以4
net=vgg(small_conv_arch)
lr,num_epochs,batch_size=0.05,10,128
train_iter,test_iter=d2l.load_data_fashion_mnist(batch_size,resize=224)
d2l.train_ch6(net,train_iter,test_iter,num_epochs,lr,d2l.try_gpu())
"""结果输出:
loss 0.178, train acc 0.935, test acc 0.920
2463.7 examples/sec on cuda:0"""
#精度比AlexNet有提升
参考:
for _ in range(10)的作用和python的range()函数_for i in range(10)循环几次-CSDN博客
[[] for _ in range(10)]详解 - python-CSDN博客
【python】*号用法 如nn.Sequential(*layers)_nn.sequential里面的*-CSDN博客