迁移学习 在开始这部分内容之前,请回顾上一次的内容。
在这部分内容中,您将学习如何使用预训练的网络来解决计算机视觉中的难题。 具体来说,您将使用torchvision
提供的ImageNet
训练的网络。
ImageNet是一个庞大的数据集,在1000个类别中有超过100万张带标签的图像。 它用于使用称为卷积层的体系结构训练深度神经网络。 在这里,我将不涉及卷积网络的详细信息,但是如果您想了解更多有关卷积网络的信息,请观看此 内容。
一旦训练完成,这些模型就可以像未经检测的图像特征检测器一样出色地工作。 对不在训练集中的图像使用预先训练的网络称为转移学习。 在这里,我们将使用转移学习来训练一个网络,该网络可以以近乎完美的准确性对猫和狗的照片进行分类。
借助torchvision.models
,您可以下载这些经过预训练的网络,并在您的应用程序中使用它们。 现在,我们将在我们的导入中包含 models
。
%matplotlib inline
%config InlineBackend.figure_format = 'retina'import matplotlib.pyplot as pltimport torch
from torch import nn
from torch import optim
import torch.nn.functional as F
from torchvision import datasets, transforms, models
大多数经过预训练的模型都要求输入为
224x224
图像。 另外,我们需要匹配训练模型时使用的归一化。 每个颜色通道分别进行归一化,平均值为[0.485,0.456,0.406]
,标准偏差为[0.229,0.224,0.225]
。data_dir = 'Cat_Dog_data/Cat_Dog_data'# TODO: Define transforms for the training data and testing data
train_transforms = transforms.Compose([transforms.RandomRotation(30),
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485,0.456,0.406],
[0.229,0.224,0.225])])test_transforms = transforms.Compose([transforms.Resize(255),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485,0.456,0.406],
[0.229,0.224,0.225])])# Pass transforms in here, then run the next cell to see how the transforms look
train_data = https://www.it610.com/article/datasets.ImageFolder(data_dir +'/train', transform=train_transforms)
test_data = https://www.it610.com/article/datasets.ImageFolder(data_dir +'/test', transform=test_transforms)trainloader = torch.utils.data.DataLoader(train_data, batch_size=64, shuffle=True)
testloader = torch.utils.data.DataLoader(test_data, batch_size=64)
我们可以加载诸如DenseNet的模型。 让我们打印出模型架构,以便我们了解发生了什么。
model = models.densenet121(pretrained=True)
model
该模型由两个主要部分构建,即特征和分类器。 特征部分是卷积层的堆栈,总体上可以作为特征检测器使用,可以输入到分类器中。 分类器部分是单个完全连接的层
(classifier): Linear(in_features=1024, out_features=1000)
。 该层是在ImageNet数据集上进行训练的,因此不适用于我们的特定问题。 这意味着我们需要替换分类器,但是这些特征可以完美地自己运行。 总的来说,我认为预训练网络是出色的特征检测器,可以用作简单前馈分类器的输入。# Freeze parameters so we don't backprop through them
for param in model.parameters():
param.requires_grad = Falsefrom collections import OrderedDict
classifier = nn.Sequential(OrderedDict([
('fc1', nn.Linear(1024, 500)),
('relu', nn.ReLU()),
('fc2', nn.Linear(500, 2)),
('output', nn.LogSoftmax(dim=1))
]))model.classifier = classifier
建立模型后,我们需要训练分类器。 但是,现在我们使用的是真正的深度神经网络。 如果您尝试像通常那样在CPU上进行训练,这将需要很长时间。 相反,我们将使用GPU进行计算。 线性代数计算在GPU上并行完成,从而使训练速度提高了100倍。 还可以在多个GPU上进行训练,从而进一步减少了训练时间。
PyTorch与几乎所有其他深度学习框架一起,使用CUDA来有效地计算GPU上的前向和后向传递。 在PyTorch中,您可以使用
model.to('cuda')
将模型参数和其他张量移动到GPU内存中。 您可以使用model.to('cpu')
将它们从GPU中转移CPU,这通常需要在PyTorch外部的网络输出上进行操作时使用。 为了说明速度的提高,我将比较在有和没有GPU的情况下执行向前和向后传递所需的时间。import time
for device in ['cpu', 'cuda']:criterion = nn.NLLLoss()
# Only train the classifier parameters, feature parameters are frozen
optimizer = optim.Adam(model.classifier.parameters(), lr=0.001)model.to(device)for ii, (inputs, labels) in enumerate(trainloader):# Move input and label tensors to the GPU
inputs, labels = inputs.to(device), labels.to(device)start = time.time()outputs = model.forward(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()if ii==3:
breakprint(f"Device = {device};
Time per batch: {(time.time() - start)/3:.3f} seconds")
Device = cpu;
Time per batch: 3.714 seconds
Device = cuda;
Time per batch: 0.021 seconds
您可以编写与
device
相关的代码,如果启用了该代码,它将自动使用CUDA,如下所示:# at beginning of the script
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")...# then whenever you get a new Tensor or Module
# this won't copy if they are already on the desired device
input = data.to(device)
model = MyModule(...).to(device)
从这里,我将让您完成模型的训练。 除了现在您的模型功能更强大之外,该过程与之前相同。 您应该轻松获得优于95%的精度。
【pytorch迁移学习】练习:训练预训练的模型对猫和狗的图像进行分类。 继续使用DenseNet模型,或尝试使用ResNet,这也是首先尝试的好模型。 确保仅在训练分类器,并且特征部分的参数已冻结。
# Use GPU if it's available
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")model = models.densenet121(pretrained=True)# Freeze parameters so we don't backprop through them
for param in model.parameters():
param.requires_grad = Falsemodel.classifier = nn.Sequential(nn.Linear(1024, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, 2),
nn.LogSoftmax(dim=1))criterion = nn.NLLLoss()# Only train the classifier parameters, feature parameters are frozen
optimizer = optim.Adam(model.classifier.parameters(), lr=0.003)model.to(device);
epochs = 1
steps = 0
running_loss = 0
print_every = 5
for epoch in range(epochs):
for inputs, labels in trainloader:
steps += 1
# Move input and label tensors to the default device
inputs, labels = inputs.to(device), labels.to(device)optimizer.zero_grad()logps = model.forward(inputs)
loss = criterion(logps, labels)
loss.backward()
optimizer.step()running_loss += loss.item()if steps % print_every == 0:
test_loss = 0
accuracy = 0
model.eval()
with torch.no_grad():
for inputs, labels in testloader:
inputs, labels = inputs.to(device), labels.to(device)
logps = model.forward(inputs)
batch_loss = criterion(logps, labels)test_loss += batch_loss.item()# Calculate accuracy
ps = torch.exp(logps)
top_p, top_class = ps.topk(1, dim=1)
equals = top_class == labels.view(*top_class.shape)
accuracy += torch.mean(equals.type(torch.FloatTensor)).item()print(f"Epoch {epoch+1}/{epochs}.. "
f"Train loss: {running_loss/print_every:.3f}.. "
f"Test loss: {test_loss/len(testloader):.3f}.. "
f"Test accuracy: {accuracy/len(testloader):.3f}")
running_loss = 0
model.train()
Epoch 1/1.. Train loss: 0.660.. Test loss: 0.245.. Test accuracy: 0.951
Epoch 1/1.. Train loss: 0.313.. Test loss: 0.112.. Test accuracy: 0.970
Epoch 1/1.. Train loss: 0.258.. Test loss: 0.074.. Test accuracy: 0.974
Epoch 1/1.. Train loss: 0.297.. Test loss: 0.062.. Test accuracy: 0.979
Epoch 1/1.. Train loss: 0.306.. Test loss: 0.058.. Test accuracy: 0.980Epoch 1/1.. Train loss: 0.153.. Test loss: 0.063.. Test accuracy: 0.976
Epoch 1/1.. Train loss: 0.169.. Test loss: 0.042.. Test accuracy: 0.984
Epoch 1/1.. Train loss: 0.246.. Test loss: 0.051.. Test accuracy: 0.978
推荐阅读
- pytorch|使用pytorch从头实现多层LSTM
- SG平滑轨迹算法的原理和实现
- pytorch|YOLOX 阅读笔记
- Keras|将Pytorch模型迁移到android端(android studio)【未实现】
- Android|将Pytorch模型部署到Android端
- nvidia|nvidia jetson xavier nx安装pytorch
- python|PyTorch单机多卡分布式训练教程及代码示例
- 深度瞎搞|PyTorch单机多卡训练(DDP-DistributedDataParallel的使用)备忘记录
- Pytorch图像分割实践|Pytorch自定义层或者模型类
- 安装问题|win10+cuda11.1+anaconda+pytorch+pycharm配置环境