原书下载地址:
我用阿里云盘分享了「OReilly.PyTorch.Pocket.R...odels.149209000X.pdf」,你可以不限速下载🚀
复制这段内容打开「阿里云盘」App 即可获取
链接:https://www.aliyundrive.com/s/NZvnGbTYr6C
第四章 基于已有网络设计进行神经网络应用开发
这一章主要通过三个例子来表现Pytorch在神经网络开发应用的便捷性及高效性。
- 基于迁移学习的图片分类
- 自然语言处理里的情感分析
- GAN,文字生成图片
迁移学习实现图片分类
在前面的章节中我们发现对于图片的处理已有很多模型,如AlexNet,VGG等,且这些模型大部分是基于ImageNet数据集(其有1000种分类),但在实际应用中,我们可能面对的分类问题并不在这一千类别中,这就需要我们对模型进行微调,即可通过迁移学习进行实际项目开发。
示例:对蜜蜂与蚂蚁分类
基于ResNet18进行参数微调对蜜蜂与蚂蚁图片进行分类处理。
- 数据预处理
加载数据,定义转换操作,设置数据加载规则
本示例中用到的数据下载程序如下:
from io import BytesIO
from urllib.request import urlopen
from zipfile import ZipFile
zipurl = 'https://pytorch.tips/bee-zip'
with urlopen(zipurl) as zipresp:
with ZipFile(BytesIO(zipresp.read())) as zfile:
zfile.extractall('./data')
模型设计
训练及验证模型
示例代码
%matplotlib inline
import os
import matplotlib.pyplot as plt
import numpy as np
from io import BytesIO
from zipfile import ZipFile
import torch
import torch.nn as nn
import torchvision
from torchvision import datasets, models
from torchvision import transforms
from torch.optim.lr_scheduler import StepLR
device = 'cuda' if torch.cuda.is_available() else 'cpu'
# windows系统下不使用多进程
workers = 0 if os.name=='nt' else 4
# 网上下载所要用到的zip文件数据,并解压文件
data_path_zip = 'hymenoptera_data.zip'
with ZipFile(data_path_zip) as zfile:
zfile.extractall('./data')
# 定义训练数据的transforms
train_transforms = transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize(
[0.485, 0.456,0.406],
[0.229, 0.224, 0.225]
),
])
# 定义验证数据的transforms
val_transforms = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(
[0.485, 0.456,0.406],
[0.229, 0.224, 0.225]
),
])
# 实例化各dataset
train_dataset = datasets.ImageFolder(
root='data/hymenoptera_data/train',
transform=train_transforms
)
val_dataset = datasets.ImageFolder(
root='data/hymenoptera_data/val',
transform=val_transforms
)
# 定义各数据加载器
train_loader = torch.utils.data.DataLoader(
train_dataset,
batch_size=4,
shuffle=True,
num_workers=workers
)
val_loader = torch.utils.data.DataLoader(
val_dataset,
batch_size=4,
shuffle=True,
num_workers=workers
)
# 模型设计与构建
model = models.resnet18(pretrained=True)
print(model.fc)
# 对最后全连接层进行改动,即变成二分类
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 2)
print(model.fc)
# 训练及验证
model = model.to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
# 学习率根据epoch增加做相应的调整
exp_lr_scheduler = StepLR(optimizer, step_size=7, gamma=0.1)
num_epochs = 25
for epoch in range(num_epochs):
model.train()
running_loss = 0.0
running_corrects = 0
for inputs, labels in train_loader:
inputs = inputs.to(device)
labels = labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
_, preds = torch.max(outputs, 1)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item() / inputs.size(0)
running_corrects += torch.sum(preds==labels.data) / inputs.size(0)
exp_lr_scheduler.step()
train_epoch_loss = running_loss / len(train_loader)
train_epoch_acc = running_corrects / len(train_loader)
# 验证
model.eval()
val_running_loss = 0.0
val_running_corrects = 0
for inputs, labels in val_loader:
inputs = inputs.to(device)
labels = labels.to(device)
outputs = model(inputs)
_, preds = torch.max(outputs, 1)
loss = criterion(outputs, labels)
val_running_loss += loss.item() / inputs.size(0)
val_running_corrects += torch.sum(preds==labels.data) / inputs.size(0)
epoch_loss = val_running_loss / len(val_loader)
epoch_acc = val_running_corrects.double() / len(val_loader)
print("Train: Loss: {:.4f} Acc: {:.4f} Val: Loss: {:.4f} Acc: {:.4f}".format(
train_epoch_loss,train_epoch_acc,epoch_loss,epoch_acc)
)
- 测试及保存模型
# 画图函数
def imshow(inp, title=None):
inp = inp.numpy().transpose((1, 2, 0))
mean = np.array([0.485, 0.456, 0.406])
std = np.array([0.229, 0.224, 0.225])
inp = std * inp + mean
inp = np.clip(inp, 0, 1)
plt.imshow(inp)
if title is not None:
plt.title(title)
inputs, classes = next(iter(val_loader))
out = torchvision.utils.make_grid(inputs)
class_name = val_dataset.classes
outputs = model(inputs.to(device))
_, preds = torch.max(outputs, 1)
imshow(out, title=[class_name[x] for x in preds])
# 保存模型参数
torch.save(model.state_dict(), './restnet18_demo.pt')
示例也可参考Pytorch官方文档:
https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html