Pytorch袖珍手册之六

pytorch pocket reference

原书下载地址:
我用阿里云盘分享了「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')
image.png

示例也可参考Pytorch官方文档:
https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容