迁移学习实例

目录

前言

一、什么是迁移学习?

二、特征提取介绍

三、实例介绍

1.获取预训练的网络模型

2.使用数据增强

3.冻结模型参数 

 4.修改最后一层的输出类别数

5.定义损失函数和优化器

 6.训练及验证模型

7.完整的代码:

总结



前言

深度学习一般需要大数据、深网络,但很多情况下我们并不能同时获取这些条件,但我们又想获得一个高性能的网络模型,这个时候,迁移学习就是一个很好的方法。本文将对迁移学习进行简单介绍,并运用实例讲解如何实现迁移学习。


一、什么是迁移学习?

迁移学习是机器学习的一种学习方法,其主要是把在任务A中训练得到的网络模型,通过调整和处理,使用到任务B中。迁移学习在人类生活中很常见,最简单的例子就是我们学完C语言后,再学习python就会感到很容易。

在神经网络迁移学习过程中,主要有两个应用场景:

  • 特征提取:冻结除最后的全连接层之外的所有网络的权重,最后一个全连接层被替换为具有随机权重的新层,并且仅训练新层
  • 微调:使用预训练好的初始化网络,用新数据训练部分或整个网络

 在本文中,我们主要将使用特征提取进行实例训练。

二、特征提取介绍

特征提取是迁移学习的一个重要方法,其主要是先引入预训练好的网络模型,在预训练好的网络模型中添加一个简单的分类器,将原网络作为新任务的特征提取器,只对最后增加的分类器参数进行重新学习。

三、实例介绍

1.获取预训练的网络模型

pytorch中,有很多已经训练好的网络模型,我们可以使用model命令来下载这部分模型 

from torchvision import models
net = models.resnet18(pretrained=True)

这里我下载的是ResNet18模型。除了ResNet18,pytorch还提供的已经训练好的模型有:“

  • AlexNet
  • VGG
  • ResNet
  • SqueezeNet
  • DenseNet
  • Inception v3
  • GoogLeNet
  • ShuffleNet v2” 

关于ResNet的网络模型结构如图:

 

 

2.使用数据增强

在加载数据集之前,我们可以先使用一些数据增强手段对图像进行处理,例如随机的缩放、反转等

trains_train = transforms.Compose(
    [transforms.RandomResizedCrop(224),  # 将给定图像随机裁剪为不同的大小和宽高比,然后缩放所裁剪得到的图像为指定的大小;改成224*224
     transforms.RandomHorizontalFlip(),  # 图像按照一定概率水平翻转
     transforms.ToTensor(),  # 转成tensor数据类型
     transforms.Normalize(mean=[0.485, 0.456, 0.406],  # 归一化处理
                          std=[0.229, 0.224, 0.225])]
)
trains_valid = transforms.Compose(
    [transforms.Resize(256),
     transforms.CenterCrop(224),  # 在图片中间区域进行裁剪
     transforms.ToTensor(),
     transforms.Normalize(mean=[0.485, 0.456, 0.406],  # 归一化处理
                          std=[0.229, 0.224, 0.225])]
)

 

3.冻结模型参数 

将原网络模型中的部分参数冻结,冻结的参数在反向传播中将不会被 更新

for param in net.parameters():
    param.requires_grad = False

 4.修改最后一层的输出类别数

员阿里输出为512*1000,如果是使用CIFAR10数据集, 该数据集一共有10个类别,需要把最后的1000改成10

net.fc = nn.Linear(512, 10)

5.定义损失函数和优化器

loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.to(device)
#loss_fn = loss_fn.to(device),imgs和targets同理
#定义优化器
learning_rate = 0.01
optimizer = torch.optim.SGD(net.parameters(), lr=learning_rate, momentum=0.5)

 6.训练及验证模型

for i in range(epoch):
    print("第{}轮训练开始".format(i+1))
    #训练步骤开始
    for data in train_loader:
        imgs, targets = data
        imgs = imgs.to(device)
        targets = targets.to(device)
        outputs = net(imgs)
        loss = loss_fn(outputs, targets)

        #优化器优化模型
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        total_train_step = total_train_step + 1
        print("训练次数: {}, Loss {}".format(total_train_step, loss))

7.完整的代码:

import torch
from torch import nn
import torchvision

import torchvision.transforms as transforms
from torchvision import models


from torch.utils.data import DataLoader


device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')


trains_train = transforms.Compose(
    [transforms.RandomResizedCrop(224),  # 将给定图像随机裁剪为不同的大小和宽高比,然后缩放所裁剪得到的图像为指定的大小;改成224*224
     transforms.RandomHorizontalFlip(),  # 图像按照一定概率水平翻转
     transforms.ToTensor(),  # 转成tensor数据类型
     transforms.Normalize(mean=[0.485, 0.456, 0.406],  # 归一化处理
                          std=[0.229, 0.224, 0.225])]
)
trains_valid = transforms.Compose(
    [transforms.Resize(256),
     transforms.CenterCrop(224),  # 在图片中间区域进行裁剪
     transforms.ToTensor(),
     transforms.Normalize(mean=[0.485, 0.456, 0.406],  # 归一化处理
                          std=[0.229, 0.224, 0.225])]
)

train_set = torchvision.datasets.CIFAR10("D:\pytorch_train_log\pytorch_train", train=True, download=True,
                                         transform=trains_train)
test_set = torchvision.datasets.CIFAR10("D:\pytorch_train_log\pytorch_train", train=False, download=True,
                                        transform=trains_valid)

#获得数据集的长度
train_data_size = len(train_set)
test_data_size = len(test_set)

train_loader = DataLoader(train_set, batch_size=64)
test_loader = DataLoader(test_set, batch_size=64)

classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')


net = models.resnet18(pretrained=True)


for param in net.parameters():
    param.requires_grad = False

net.fc = nn.Linear(512, 10)


net = net.to(device)

loss_fn = nn.CrossEntropyLoss()
loss_fn = loss_fn.to(device)
#loss_fn = loss_fn.to(device),imgs和targets同理
#定义优化器
learning_rate = 0.01
optimizer = torch.optim.SGD(net.parameters(), lr=learning_rate, momentum=0.5)

#设置训练网络的参数
total_train_step = 0    #记录训练的次数
total_test_step = 0     #记录测试的次数
epoch = 20   #训练的轮数


for i in range(epoch):
    print("第{}轮训练开始".format(i+1))
    #训练步骤开始
    for data in train_loader:
        imgs, targets = data
        imgs = imgs.to(device)
        targets = targets.to(device)
        outputs = net(imgs)
        loss = loss_fn(outputs, targets)

        #优化器优化模型
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        total_train_step = total_train_step + 1
        print("训练次数: {}, Loss {}".format(total_train_step, loss))

#测试步骤
total_test_loss = 0
total_accuracy = 0
with torch.no_grad():
    for data in test_loader:
        imgs, targets = data
        imgs = imgs.to(device)
        targets = targets.to(device)
        outputs = net(imgs)

        loss = loss_fn(outputs, targets)
        total_test_loss = total_test_loss + loss
        accuracy = (outputs.argmax(1) == targets).sum()
        total_accuracy = total_accuracy + accuracy

    print("整体测试集上的Loss:{}".format(total_test_loss))
    print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))
    total_test_step = total_test_step + 1

    torch.save(net, "net_{}.pth".format(i))
    print("模型已保存")

总结

本文主要是对迁移学习进行了简单的介绍,通过使用迁移学习,可以极大的加快训练速度,并且相对普通的模型,迁移学习后的网络模型的精度也有较高的提升。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>