参考的书目为《深度学习之pytorch实战计算机视觉》
将猫狗大战中写好的VGGNet模型替换为VGG16,ResNet模型,前面首先给出完整的VGGNet模型代码,之后分别给出最另外两个模型的修改位置,并进行标注说明:

import torch
import torchvision
from torchvision import datasets, transforms
import torch.utils.data as da#后面调用时出不来自动提示,故重命名了下
from torch.autograd import Variable
import os
import matplotlib.pyplot as plt
import time
data_dir = "G:\pytorch\DogsVSCats"
data_transform = {
    x:transforms.Compose([
        transforms.Scale([64, 64]),#放缩至64*64
        transforms.ToTensor()#类型转换
    ])
    for x in ["train", "test"]
}
image_datasets = {
    x:datasets.ImageFolder(root=os.path.join(data_dir, x),
                           transform= data_transform[x])
    #os.path.join将两个名字拼接成一个完整的文件路径
    for x in ["train","test"]
}
dataloader = {
    x:da.DataLoader(dataset=image_datasets[x],
                    batch_size= 16,
                    shuffle= True)
    for x in ["train", "test"]
}
X_example, Y_example = next(iter(dataloader["train"]))
#为减少计算量,在模型中删除了最后三个卷积层和池化层
class Models_VGG(torch.nn.Module):
    def __init__(self):
        super(Models_VGG, self).__init__()
        self.Conv = torch.nn.Sequential(
            torch.nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2),

            torch.nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2),

            torch.nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2),

            torch.nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1),
            torch.nn.ReLU(),
            torch.nn.MaxPool2d(kernel_size=2, stride=2)
        )
        #全连接层优化
        self.Classes = torch.nn.Sequential(
            torch.nn.Linear(4*4*512, 1024),
            torch.nn.ReLU(),
            torch.nn.Dropout(p = 0.5),
            torch.nn.Linear(1024, 1024),
            torch.nn.ReLU(),
            torch.nn.Dropout(p = 0.5),
            torch.nn.Linear(1024, 2)
        )

    def forward(self, input):
        x = self.Conv(input)
        x = x.view(-1, 4*4*512)#扁平化处理
        x = self.Classes(x)
        return x
model = Models_VGG()
use_gpu = torch.cuda.is_available()#判断GPU是否可用
#对模型进行优化
loss_fuction = torch.nn.CrossEntropyLoss()#采用交叉嫡
optimizer = torch.optim.Adam(model.parameters(), lr=0.00001)
if use_gpu:
	model = model1.cuda()
epoch_n = 10
time_start = time.time()
for epoch in range(epoch_n):#训练次数
    print("Epoch {}/{}".format(epoch, epoch_n-1))
    print("-"*20)

    for phase in ["train", "test"]:#选择数据集
        if phase is "train":
            print("Traing...")
            model.train(True)
        else:
            print("Validing...")
            model.train(False)
        running_loss = 0.0
        running_corrects = 0
#下面对数据集中的数据进行训练或验证
        for batch, data in enumerate(dataloader[phase], 1):
            X, y = data
            #如果是GPU
            if use_gpu:
           	    X, y = Variable(X.cuda()), Variable(y.cuda())
           	else:
            	X, y = Variable(X), Variable(y)
            y_pred = model(X)
            _,pred = torch.max(y_pred.data, 1)
            optimizer.zero_grad()
            loss = loss_fuction(y_pred, y)
            if phase is "train":
                loss.backward()
                optimizer.step()
            running_loss += loss.data
            running_corrects += torch.sum(pred == y.data)
            if batch%500 is 0 and phase is "train":
                print("Batch {}, Tarin Loss{:.4f}, Train Accur{:.4f}".format(batch, running_loss/batch, 100*running_corrects/(16*batch)))
        epoch_loss = running_loss*16/len(image_datasets[phase])
        epoch_acc = 100*running_corrects/len(image_datasets[phase])
        print("{} Loss:{:.4f} Acc {:.4f}%".format(phase, epoch_loss, epoch_acc))
    time_use = time.time() - time_start
print(time_use)

在CPU上运行耗时比较旧,我的电脑是X220 i5-2520m,跑一个epoch用了四十五分钟…
——————————————————————————————
下面是模型迁移代码:
1)迁移到VGG16

#将VGGNet上的模型迁移到VGG16中,下载的模型已经优化好了
model = models.vgg16(pretrained= True)
#冻结卷积神经网络中全连接层之前的网络层次,即梯度不修改
for parma in model.parameters():
    parma.requires_grad = False
#调参只需要在全连接层进行
model.classifier = torch.nn.Sequential(
    torch.nn.Linear(25088, 4096),
    torch.nn.ReLU(),
    torch.nn.Dropout(p=0.5),
    torch.nn.Linear(4096, 4096),
    torch.nn.ReLU(),
    torch.nn.Dropout(p=0.5),
    torch.nn.Linear(4096, 2)
)

在VGG16中输出的结果是1000个,但猫狗大战这里只需输出2个,所以做了修该。
2)迁移到ResNet中:

#将VGGNet上的模型迁移到ResNet50中,下载的模型已经优化好了
model = models.resnet50(pretrained= True)
#冻结卷积神经网络中全连接层之前的网络层次
for parma in model.parameters():
    parma.requires_grad = False
#对全连接层进行调整,只有一行
model.fc = torch.nn.Linear(2048, 2)

输出结果只有两个,所以全连接层是个2

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐