知识点0、 VGG网络结构要点
知识点1、VGG卷积层 vgg_block 的第一个卷积层需要单独定义
知识点2、利用append 与 for 构建 vgg_block
知识点3、利用 append 、for、zip 构建vgg_stack
知识点4、zip的作用
知识点5、Sequential[0]
知识点6、不是调用vgg_stack而是引用
知识点0
VGG网络可以看做是由很多个vgg_block和多个全连接层组成,每个vgg_block由多个卷积层和一个池化层组成。除了第一个卷积层的input_channels 与 output_channels 不一样以外,其余的卷积层都是一样的,用kernel_size=3, padding=1可以使得卷积后图像大小保持不变,池化层kernel_size=2, stride=2 使得图片宽度减半。
import numpy as np
import torch
from torch.autograd import Variable
from torchvision.datasets import CIFAR10
from torch import nn
知识点1
由于第一个卷积层的input_channels不一定和output_channels一样,所以不应该写在循环当中
知识点2
这个操作记住,先用一个net[]的 ’list’ 储存vgg_block的结构,然后再转化为nn.Sequential(*net)
def vgg_block(num_convs, input_channles, ouput_channels):
net = [ nn.conv2d(input_channels, output_channels, kernel_size=3, padding=1), nn.ReLU(True)]
for i in range(num_cons - 1):
net.append(nn.conv2d(output_channels, output_channels, kernel_size=3, padding=1)
net.append(nn.ReLU(True))
net.append(nn.MaxPool2d(2, 2))
return nn.Sequential(*net)
测试
block_demo = vgg_block(3, 64, 128)
print(block_demo)
input_demo = Variable(torch.zeros(1, 64, 300, 300))
output_demo = block_demo(input_demo)
print(output_demo.shape)
知识点3
这个操作记住,利用net.append()多次调用vgg_block,串成一个整体
知识点4
zip 可以把两个iterable融合 a = [1,2,3]——>b = [4,5,6]——>zipped = zip(a,b)——>[(1, 4), (2, 5), (3, 6)] 利用这个技巧,可以实现for 2个参数迭代
def vgg_stack(num_convs, channels):
net=[]
for n,c in zip(num_convs, channels):
in_c = c[0]
out_c = c[1]
net.append(vgg_block(n, in_c, out_c)
return nn.Sequential(*net)
知识点5
Sequential 套着 Sequential 可以用索引直接调出里面的Sequential
vgg_net = vgg_stack((1, 1, 2, 2, 2), ((3, 64), (64, 128), (128, 256), (256, 512), (512, 512)))
print(vgg_net)
print(vgg_net[0])
Variable(torch.zeros(1, 3, 256, 256))
test_y = vgg_net(test_x)
print(test_y.shape)
知识点6
self.feature = vgg_net 注意这里不需要括号,引用而不是调用
其余的都是基操
class vgg(nn.Module):
def __init__(self):
super(vgg, self).__init__()
self.feature = vgg_net # 注意这里不需要括号,引用而不是调用
self.fc = nn.Sequential(
nn.Linear(512, 100),
nn.ReLU(True),
nn.Linear(100, 10)
)
def forward(self, x):
x = self.feature(x)
x = x.view(shape[0], -1)
x = self.fc(x)
return x
基操,详情请看上一篇AlexNet
def data_tf(x):
x = np.array(x, dtype='float32') / 255
x = (x - 0.5) / 0.5
x = x.transpose((2, 0, 1))
x = torch.from_numpy(x)
return x
from torch.utils.data import DataLoader
from jc_utils import train
train_set = CIFAR10('./data', train=True, transform=data_tf, download=True)
train_data = DataLoader(train_set, batch_size=64, shuffle=True)
test_set = CIFAR10('./data', train=False, transform=data_tf, download=True)
test_data = DataLoader(test_set, batch_size=128, shuffle=False)
net = vgg()
optimizer = torch.optim.SGD(net.parameters(), lr=1e-1)
criterion = nn.CrossEntropyLoss()
train(net, train_data, test_data, 20, optimizer, criterion)