利用迁移学习加速深度学习:PyTorch Playbook
介绍
是的!如果你已经会弹原声吉他,那么学习弹电子吉他会更容易。你不必从头开始重新学习电吉他的基础知识。我们人类可以聪明地将以前学到的知识应用到不同的任务或领域,并利用这些知识有效地解决新问题。
机器可以模仿人脑这种知识转移的能力吗?是的,这要归功于迁移学习(TL)。
本指南将介绍 TL 的动机和类型。有关预训练模型的简要介绍和实际示例,请查看 Kaggel 竞赛“狗与猫”。由于它是二分类,因此在机器学习术语中它被称为二元分类问题。
动机
迁移学习强调将解决一项任务时获得的知识存储在数据库中,并将其应用于不同但相关的任务。基本的学习过程如下所示。
图片来源
传统上,CNN和深度学习算法用于解决特定任务。一旦特征空间分布发生变化,就需要从头开始构建模型。卷积网络中的初始层检测强度、颜色、边缘等低级特征。无论您检测的是汽车、人类还是动物,这些层都很常见。更深的层将检测更复杂的特征,如形状、面部、图案等。
训练数据越大,预测准确率就越高。在处理复杂问题时,需要大量的训练图像数据。这意味着堆叠越来越多的层来使网络更深。但假设堆叠 1000 个神经网络 (NN) 层不会产生良好的结果,并使情况变得更糟。
迁移学习来救援!
该模型无需从头开始创建整个网络,而是可以学习一项任务的特征并将其应用于另一项任务。通常使用预先训练的模型。最常见的是,这些模型在 ImageNet 上进行了训练——120 万张图像,1000 个类别。
记住将分类层(FC)更改为与您需要预测的类别数量相同。
迁移学习技术的类型
TL 技术有三种类型:归纳式、传导式和无监督式。以下是不同传输设置的概述。
下面给出它们的定义和区别。
下图展示了从源域到目标域实现 TL 的不同方法
图片来源
应用迁移学习
什么
了解源和目标域/任务之间的共同知识,以提高目标任务的性能。
什么时候
如果您的目标数据集与训练数据集(ImageNet)不同,则建议不要使用 TL,考虑到图像的多样性,通常情况并非如此。这种类型的知识迁移称为负迁移。如果目标图像超出其范围,例如医学图像或望远镜图像,ImageNet 权重将无济于事。
如何
当源域和目标域和任务相关时,识别不同的迁移学习技术。
按照下表并满足您的要求。
图片来源
现在您将学习如何将这些 TL 技术应用于深度学习。
迁移学习在深度学习中的应用
预训练模型
与机器学习(计算机视觉)相比,深度学习需要大量的训练时间和数据。你可以使用预先训练的模型来提取特征、微调权重、保存它们并让其他人使用,从而节省一些时间。这也称为深度迁移学习
以下是一些可在Pytorch API下载的著名预训练模型类型。
- 残差网络
- 密集网络
- VGG-16
- 移动网络
预先训练的模型将带来高精度和高速度的优势,从而节省您数周从头开始训练和创建这些模型的工作量。
微调
预训练模型的较深层用于学习特征并进行微调。为了实现带微调的迁移学习,在添加可训练层时会替换最后的层。
图片来源
即使数据较新且较小,较早的层也更具通用性。即使冻结初始层并保留其余层,结果也绝对会很好。对于较大的数据集,您可以保留具有初始权重的完整网络。
本指南将使用 DenseNet121 预训练模型作为特征提取器。数据有一个限制,即每个类别的训练样本较少。即使输入图像是新的并且从未在 ImageNet 中存在过,模型也必须提取适当的特征并预测结果。
Python 中的实现
导入重要的库。
import torchvision
import torch.nn as nn
import torch
import torch.nn.functional as F
from torchvision import transforms,models,datasets
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
from torch import optim
调用图像并使用transform.Compose函数进行转换。
train_data_dir = '/input/cat-and-dog/training_set/training_set'
transform = transforms.Compose([transforms.Resize(255),
transforms.CenterCrop(224),
transforms.ToTensor()])
dataset = torchvision.datasets.ImageFolder(train_data_dir, transform= transform)
train_loader = torch.utils.data.DataLoader(dataset, batch_size=400 ,shuffle=True)
test_data_dir = '/input/cat-and-dog/test_set/test_set'
transform = transforms.Compose([transforms.Resize(255),
transforms.CenterCrop(224),
transforms.ToTensor()])
test_dataset = torchvision.datasets.ImageFolder(test_data_dir, transform= transform)
test_loader = torch.utils.data.DataLoader(dataset, batch_size=400 ,shuffle=True)
def imshow(inp, title=None):
"""Imshow for Tensor."""
inp = inp.numpy().transpose((1, 2, 0))
plt.figure(figsize=(20,150))
plt.imshow(inp)
inputs, classes = next(iter(train_loader))
# Make a grid from batch
out = torchvision.utils.make_grid(inputs, scale_each= True)
imshow(out)
下载预先训练的模型。
model = models.densenet121(pretrained = True)
model
使用Logsoftmax()的激活层更改输出层。
for params in model.parameters():
params.requires_grad = False
from 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
训练模型。
model = model.cuda()
optimizer= optim.Adam(model.classifier.parameters())
criterian= nn.NLLLoss()
list_train_loss=[]
list_test_loss=[]
for epoch in range(10):
train_loss= 0
test_loss= 0
for bat,(img,label) in enumerate(train_loader):
# moving batch and labels to gpu
img = img.to('cuda:0')
label = label.to('cuda:0')
model.train()
optimizer.zero_grad()
output = model(img)
loss = criterian(output,label)
loss.backward()
optimizer.step()
train_loss = train_loss+loss.item()
accuracy=0
for bat,(img,label) in enumerate(test_loader):
img = img.to('cuda:0')
label = label.to('cuda:0')
model.eval()
logps= model(img)
loss = criterian(logps,label)
test_loss+= loss.item()
ps=torch.exp(logps)
top_ps,top_class=ps.topk(1,dim=1)
equality=top_class == label.view(*top_class.shape)
accuracy +=torch.mean(equality.type(torch.FloatTensor)).item()
list_train_loss.append(train_loss/20)
list_test_loss.append(test_loss/20)
print('epoch: ',epoch,' train_loss: ',train_loss/20,' test_loss: ',test_loss/20,' accuracy: ', accuracy/len(test_loader))
samples, _ = iter(test_loader).next()
samples = samples.to('cuda:0')
fig = plt.figure(figsize=(24, 16))
fig.tight_layout()
output = model(samples[:24])
pred = torch.argmax(output, dim=1)
pred = [p.item() for p in pred]
ad = {0:'I guess it\'s a cat', 1:'I guess it\'s a dog'}
for num, sample in enumerate(samples[:24]):
plt.subplot(4,6,num+1)
plt.title(ad[pred[num]])
plt.axis('off')
sample = sample.cpu().numpy()
plt.imshow(np.transpose(sample, (1,2,0)))
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~