迁移学习的两个主要场景

  1. 微调CNN:使用预训练的网络来初始化自己的网络,而不是随机初始化,然后训练即可
  2. 将CNN看成固定的特征提取器:固定前面的层,重写最后的全连接层,只有这个新的层会被训练

下面修改预训练好的resnet18网络在私人数据集上进行训练来分类蚂蚁和蜜蜂

数据集下载

这里使用的数据集包含ants和bees训练图片各约120张,验证图片各75张。由于数据样本非常少,如果从0初始化一个网络进行训练很难有令人满意的结果,这时候迁移学习就派上了用场。数据集下载地址,下载后解压到项目目录

导入相关包

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import torchvision
import torchvision.transforms as transforms
import time
import os
import copy device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

加载数据

PyTorch提供了 torchvision.datasets.ImageFolder 方法来加载私人数据集:

# 训练数据集需要扩充和归一化
# 验证数据集仅需要归一化
data_transforms = {
'train': transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
} data_dir = 'hymenoptera_data' image_datasets = {
x: torchvision.datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x])
for x in ['train', 'val']
} dataloaders = {
x: torch.utils.data.DataLoader(image_datasets[x], batch_size=4, shuffle=True, num_workers=4)
for x in ['train', 'val']
} dataset_sizes = {
x: len(image_datasets[x])
for x in ['train', 'val']
} class_names = image_datasets['train'].classes

定义一个通用的训练函数,得到最优参数

# 训练模型函数,参数scheduler是一个 torch.optim.lr_scheduler 学习速率调整类对象
def train_model(model, criterion, optimizer, scheduler, num_epochs=2):
since = time.time() best_model_wts = copy.deepcopy(model.state_dict())
best_acc = 0.0 for epoch in range(num_epochs):
print('-' * 20)
print('Epoch {}/{}'.format(epoch+1, num_epochs)) # 每个epoch都有一个训练和验证阶段
for phase in ['train', 'val']:
if phase == 'train':
model.train() # 训练模式
else:
model.eval() # 验证模式 running_loss = 0.0
running_corrects = 0 for inputs, labels in dataloaders[phase]:
inputs = inputs.to(device)
labels = labels.to(device) # 训练阶段开启梯度跟踪
with torch.set_grad_enabled(phase == 'train'):
outputs = model(inputs)
_, preds = torch.max(outputs, 1)
loss = criterion(outputs, labels) # 仅在训练阶段进行后向+优化
if phase == 'train':
optimizer.zero_grad()
loss.backward()
optimizer.step()
scheduler.step() # 统计
running_loss += loss.item() * inputs.size(0)
running_corrects += torch.sum(preds == labels.data) epoch_loss = running_loss / dataset_sizes[phase]
epoch_acc = running_corrects.double() / dataset_sizes[phase] print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc)) # 记录最好的状态
if phase == 'val' and epoch_acc > best_acc:
best_acc = epoch_acc
best_model_wts = copy.deepcopy(model.state_dict()) print('-' * 20)
time_elapsed = time.time() - since
print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed//60, time_elapsed%60))
print('Best val Acc: {:4f}'.format(best_acc)) # 返回最佳参数的模型
model.load_state_dict(best_model_wts)
return model

场景一:微调CNN

这里我们使用resnet18作为我们的初始网络,在自己的数据集上继续训练预训练好的模型,所不同的是,我们修改原网络最后的全连接层输出维度为2,因为我们只需要预测是蚂蚁还是蜜蜂,原网络输出维度是1000,预测了1000个类别:

net = torchvision.models.resnet18(pretrained=True)     # 加载resnet网络结构和预训练参数
num_ftrs = net.fc.in_features # 提取fc层的输入参数
net.fc = nn.Linear(num_ftrs, 2) # 修改输出维度为2 net = net.to(device) # 使用分类交叉熵 Cross-Entropy 作损失函数,动量SGD做优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) # 每5个epochs衰减一次学习率 new_lr = old_lr * gamma ^ (epoch/step_size)
lr_scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1) # 训练模型
net = train_model(net, criterion, optimizer, lr_scheduler, num_epochs=10)

场景二:CNN作为固定特征提取器

这里我们通过设置 requires_grad == False 冻结除最后一层之外的所有网络,这样在反向传播的时候他们的梯度就不会被计算,参数也不会更新:

net = torchvision.models.resnet18(pretrained=True)
# 通过设置requires_grad = False来冻结参数,这样在反向传播的时候他们的梯度就不会被计算
for param in net.parameters():
param.requires_grad = False # 新连接层参数默认requires_grad=True
num_ftrs = net.fc.in_features
net.fc = nn.Linear(num_ftrs, 2) net = net.to(device) criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.fc.parameters(), lr=0.001, momentum=0.9)
lr_scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1) net = train_model(net, criterion, optimizer, lr_scheduler, num_epochs=20)

PyTorch迁移学习-私人数据集上的蚂蚁蜜蜂分类的更多相关文章

  1. NASNet学习笔记——   核心一:延续NAS论文的核心机制使得能够自动产生网络结构;    核心二:采用resnet和Inception重复使用block结构思想;    核心三:利用迁移学习将生成的网络迁移到大数据集上提出一个new search space。

    from:https://blog.csdn.net/xjz18298268521/article/details/79079008 NASNet总结 论文:<Learning Transfer ...

  2. Pytorch迁移学习实现驾驶场景分类

    Pytorch迁移学习实现驾驶场景分类 源代码:https://github.com/Dalaska/scene_clf 1.安装 pytorch 直接用官网上的方法能装上但下载很慢.通过换源安装发现 ...

  3. Pytorch迁移学习

    环境: Pytorch1.1,Python3.6,win10/ubuntu18,GPU 正文 Pytorch构建ResNet18模型并训练,进行真实图片分类: 利用预训练的ResNet18模型进行Fi ...

  4. pytorch 迁移学习[摘自官网]

    迁移学习包含两种:微调和特征提取器. 微调:对整个网络进行训练,更新所有参数 特征提取器:只对最后的输出层训练,其他层的权重保持不变 当然,二者的共性就是需要加载训练好的权重,比如在ImageNet上 ...

  5. 【深度学习系列】迁移学习Transfer Learning

    在前面的文章中,我们通常是拿到一个任务,譬如图像分类.识别等,搜集好数据后就开始直接用模型进行训练,但是现实情况中,由于设备的局限性.时间的紧迫性等导致我们无法从头开始训练,迭代一两百万次来收敛模型, ...

  6. TensorFlow从1到2(九)迁移学习

    迁移学习基本概念 迁移学习是这两年比较火的一个话题,主要原因是在当前的机器学习中,样本数据的获取是成本最高的一块.而迁移学习可以有效的把原有的学习经验(对于模型就是模型本身及其训练好的权重值)带入到新 ...

  7. DLNg[结构化ML项目]第二周迁移学习+多任务学习

    1.迁移学习 比如要训练一个放射科图片识别系统,但是图片非常少,那么可以先在有大量其他图片的训练集上进行训练,比如猫狗植物等的图片,这样训练好模型之后就可以转移到放射科图片上,模型已经从其他图片中学习 ...

  8. tensorflow实现迁移学习

    此例程出自<TensorFlow实战Google深度学习框架>6.5.2小节 卷积神经网络迁移学习. 数据集来自http://download.tensorflow.org/example ...

  9. Python 迁移学习实用指南 | iBooker·ApacheCN

    原文:Hands-On Transfer Learning with Python 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 不要担心自己的形象,只关心如何实现目标.--<原则& ...

随机推荐

  1. luogu P4798 [CEOI2015 Day1]卡尔文球锦标赛 dp 数位dp

    LINK:卡尔文球锦标赛 可以先思考一下合法的序列长什么样子. 可以发现后面的选手可以使用前面出现的编号也可以直接自己新建一个队. 其实有在任意时刻i 序列的mex>max.即要其前缀子序列中1 ...

  2. AutoWired注解和Lazy延迟加载

    一.代码截图: @Lazy是延迟加载的意思, 容器启动时不创建对象, 当从容器中需要获取此对象时才创建. @Lazy//@Lazy注解可以用在类上, 还可以用在普通方法上,还可以用在构造方法上,还可以 ...

  3. HA模式下的java api访问要点

    在非HA架构的HDFS中,客户端要通过java接口调用HDFS时一般是在JobRunner的类中按照下面的方式: 因为nodename只有一个节点所以会在代码中显式的指明要连接哪一个节点:但是在HA模 ...

  4. Go语言系列(三)之数组和切片

    <Go语言系列文章> Go语言系列(一)之Go的安装和使用 Go语言系列(二)之基础语法总结 1. 数组 数组用于存储若干个相同类型的变量的集合.数组中每个变量称为数组的元素,每个元素都有 ...

  5. async和await的使用总结 ~ 竟然一直用错了c#中的async和await的使用。。

    对于c#中的async和await的使用,没想到我一直竟然都有一个错误.. ..还是总结太少,这里记录下. 这里以做早餐为例 流程如下: 倒一杯咖啡. 加热平底锅,然后煎两个鸡蛋. 煎三片培根. 烤两 ...

  6. 关于if语句的细节

    看下面两个语句: if(p->key>key) p=p->left; if(p->key<key)p=p->right; 上面的写法是很有问题的: 如果第一条条件满 ...

  7. IDEA插件配置推荐

    一.配置 [自动编译]如下图配置:推荐指数[***] [忽略大小写]说明:IDEA默认是匹配大小写,此开关如果未关,你输入字符一定要符合大小写.比如敲string是不会出现代码提示或只能补充.但是如果 ...

  8. 太鸡冻了!我用 Python 偷偷查到暗恋女生的名字

    1 目 标 场 景 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识.那么针对这三类人 ...

  9. MySQL百万数据查询优化

    问题来源: 在查询统计的业务中做了一个小型的每隔一分钟的统计服务,实现1分钟,5分钟,1小时,2小时,一天,三天,一月,3月,一年的级联统计.前期数据来源表数据,以及生成的统计表数据都少; 数月之后, ...

  10. 搭建 springboot selenium 网页文件转图片环境

    1. 环境准备 需要有 chrome 浏览器 + chrome driver + selenium 客户端 离线 chrome 下载地址 # 64位 linux 系统 https://dl.googl ...