优达学城《DeepLearning》2-2:迁移学习
目录
加载和预处理数据
转换数据
数据加载器和数据可视化
定义模型
最终分类器层
指定损失函数和优化器
训练
测试
可视化样本测试结果
大多数时候,你不会想自己训练一个完整的卷积网络。像ImageNet这样的大型数据集上的现代卷积网络训练需要在多个gpu上花费数周时间。
作为替代,大多数人使用预先训练好的网络作为固定的特征提取器,或者作为初始网络进行微调。
在本笔记本中,您将使用在ImageNet数据集上训练的VGGNet作为特征提取器。下面是VGGNet体系结构的示意图,有一系列卷积层和最大池层,最后是三个完全连接的层,它们对ImageNet数据库中的1000个类进行了分类。
VGGNet之所以伟大,是因为它简单且性能优异,在ImageNet的竞争中曾名列第二。这里的想法是我们保留所有的卷积层,但是用我们自己的分类器替换最后一个完全连接的层。通过这种方式,我们可以使用VGGNet作为图像的固定特征提取器,然后在此基础上轻松地训练一个简单的分类器。
- 使用除最后一个全连接层以外的所有层作为固定的特征提取器。
- 定义一个新的、最终的分类层,并将其应用到我们选择的任务中!
你可以从CS231n斯坦福课程笔记中关于迁移学习的内容。
这里我们将使用VGGNet对花的图像进行分类。我们将像往常一样,从导入我们通常的数据集开始。然后检查是否可以在GPU上训练我们的模型。
加载和预处理数据
我们将使用PyTorch的ImageFolder类,这使得从目录加载数据非常容易。例如,训练图像都存储在如下目录路径中:
其中,在本例中,training的根文件夹是flower_photos/train/,类别名是花类型的名称。
转换数据
当我们进行迁移学习时,我们必须将输入数据改造成预先训练好的模型所期望的形状。VGG16需要224维度的正方形图像作为输入,因此,我们调整每个花图像的大小以适应这个模型。
数据加载器和数据可视化
定义模型
为了定义一个训练模型,我们将遵循以下步骤:
- 1.加载一个预先训练过的VGG16模型
- 2.冻结所有参数,使网络充当一个固定的特征提取器
- 3.删除最后一层
- 4.用我们自己的线性分类器替换最后一层
冻结仅仅意味着预训练模型中的参数在训练过程中不会改变。
打印结果:
Downloading: "https://download.pytorch.org/models/vgg16-397923af.pth" to C:\Users\yinm/.cache\torch\hub\checkpoints\vgg16-397923af.pth
100%|██████████| 528M/528M [03:56<00:00, 2.34MB/s]
VGG((features): Sequential((0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(1): ReLU(inplace=True)(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(3): ReLU(inplace=True)(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(6): ReLU(inplace=True)(7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(8): ReLU(inplace=True)(9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(11): ReLU(inplace=True)(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(13): ReLU(inplace=True)(14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(15): ReLU(inplace=True)(16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(18): ReLU(inplace=True)(19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(20): ReLU(inplace=True)(21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(22): ReLU(inplace=True)(23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(25): ReLU(inplace=True)(26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(27): ReLU(inplace=True)(28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(29): ReLU(inplace=True)(30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False))(avgpool): AdaptiveAvgPool2d(output_size=(7, 7))(classifier): Sequential((0): Linear(in_features=25088, out_features=4096, bias=True)(1): ReLU(inplace=True)(2): Dropout(p=0.5, inplace=False)(3): Linear(in_features=4096, out_features=4096, bias=True)(4): ReLU(inplace=True)(5): Dropout(p=0.5, inplace=False)(6): Linear(in_features=4096, out_features=1000, bias=True))
)
最终分类器层
您可以通过名称和(有时)编号访问预训练网络中的任何层,例如:vgg16.classifier[6]是名为 “classifier” 层组中的第六层。
TODO:将最后一个全连接的层替换为适当数量的类输出层。
指定损失函数和优化器
下面我们将使用交叉熵损失和小学习率的随机梯度下降。注意,优化器只接受可训练参数vgg.classifier.parameters()作为输入。
训练
在这里,我们将训练网络。
练习:到目前为止,我们已经为您提供了训练代码。在这里,我将给你一个更大的挑战,让你写代码来训练网络。当然,如果你需要帮助,你可以看到我的解决方案。
# number of epochs to train the model
n_epochs = 2## TODO complete epoch and training batch loops
## These loops should update the classifier-weights of this model
## And track (and print out) the training loss over timefor epoch in range(1, n_epochs + 1):train_loss = 0.0 # 每n个batch的平均损失for batch_i, (data, target) in enumerate(train_loader):if train_on_gpu:data, target = data.cuda(), target.cuda()optimizer.zero_grad() #清除优化器中梯度output = vgg16(data) #前向传播loss = criterion(output, target)#计算损失loss.backward() #反向传播optimizer.step() # 参数更新train_loss += loss.item() #累计本批次损失if batch_i % 20 == 19:print('Epoch %d, Batch %d loss: %.16f' % (epoch, batch_i + 1, train_loss/20))train_loss = 0.0
结果:
测试
下面是每个flower类的测试精度。
# track test loss
# over 5 flower classes
test_loss = 0.0
class_correct = list(0. for i in range(5))
class_total = list(0. for i in range(5))vgg16.eval() # eval mode# iterate over test data
for data, target in test_loader:# move tensors to GPU if CUDA is availableif train_on_gpu:data, target = data.cuda(), target.cuda()# forward pass: compute predicted outputs by passing inputs to the modeloutput = vgg16(data)# calculate the batch lossloss = criterion(output, target)# update test loss test_loss += loss.item()*data.size(0)# convert output probabilities to predicted class_, pred = torch.max(output, 1) # compare predictions to true labelcorrect_tensor = pred.eq(target.data.view_as(pred))correct = np.squeeze(correct_tensor.numpy()) if not train_on_gpu else np.squeeze(correct_tensor.cpu().numpy())# calculate test accuracy for each object classfor i in range(batch_size):if i >= len(target): #防止最后一个batch不够20个。continuelabel = target.data[i]class_correct[label] += correct[i].item()class_total[label] += 1# calculate avg test loss
test_loss = test_loss/len(test_loader.dataset)
print('Test Loss: {:.6f}\n'.format(test_loss))for i in range(5):if class_total[i] > 0:print('Test Accuracy of %5s: %2d%% (%2d/%2d)' % (classes[i], 100 * class_correct[i] / class_total[i],np.sum(class_correct[i]), np.sum(class_total[i])))else:print('Test Accuracy of %5s: N/A (no training examples)' % (classes[i]))print('\nTest Accuracy (Overall): %2d%% (%2d/%2d)' % (100. * np.sum(class_correct) / np.sum(class_total),np.sum(class_correct), np.sum(class_total)))
结果:
可视化样本测试结果
优达学城《DeepLearning》2-2:迁移学习相关推荐
- 优达学城《无人驾驶入门》学习笔记——卡尔曼滤波器实现详解
优达学城<无人驾驶入门>的第二个项目是实现矩阵类,要求通过python编写一个用来计算矩阵的类Matrix.编写这个类并不难,涉及到的线性代数方面的知识也不多,比如矩阵的加法.减法.乘法, ...
- 优达学城(Udacity)深度学习笔记-1.Pythonos学习
欢迎使用Markdown编辑器写博客 Python对于文件操作非常方便,很大一部分是因为os这个库,在做优达城深度学习作业的时候里面有一堆os,各种列表推导式混合os.path,一下就绕晕了.这里做点 ...
- 来自优达学城毕业生和导师的学习建议
时刻牢记你的目标: "找不到学习动力? 时刻明确自己前行的目标.多看一些技术大牛的访谈和f分享,关注他们的社交媒体,你会发现他们也都曾和你一样,从零做起,日夜兼程." 拆分学习计划 ...
- 优达学城《DeepLearning》大纲和学习愿景
目的: 查漏补缺深度学习体系,精益求精的深刻理解体系中各种核心的技术原理,感受技术思想背后的精髓魅力,做到能够脱口而出. 计划: 2021年5月.6月,完成课程中所有核心知识的深刻理解(通过撰写博客, ...
- 优达学城 深度学习 任务1
这几天刚好有环境,打算学习一下深度学习 看了一圈介绍,发现优达学城的深度学习课程作为入门课程还是不错的 今天看了第一章节的视频,顺便做了任务1 任务1难度不大,按照网站上的说明可以完成下载.打包等工作 ...
- 优达学城计算机视觉pkl,优达学城机器学习工程师纳米学位项目介绍
本文由 meelo 原创,请务必以链接形式注明 本文地址,简书同步更新地址 一对一的项目辅导是优达学城纳米学位的一大亮点.本文将简要介绍优达学城机器学习工程师纳米学位的6个项目.项目覆盖了机器学习的主 ...
- 无人驾驶8: 粒子滤波定位(优达学城项目)
优达学城无人车定位的项目实现: 粒子滤波算法流程图 粒子滤波的伪代码: step1:初始化 理论上说,当粒子数量足够多时,能准确地呈现贝叶斯后验分布,如果粒子太少,可能漏掉准确位置,粒子数量太多,会拖 ...
- 优达学城无人驾驶工程师——P5车辆检测功能
这次讲的是优达学城无人驾驶工程师第一期的最后一个项目,车辆检测功能,代码如下. 导包 import cv2 import numpy as np import matplotlib.pyplot as ...
- 优达学城无人驾驶工程师——P4车道线检测功能
这次讲的是优达学城的无人驾驶工程师的P4项目,利用车前方的摄像头检测车道线,下面开始我们的代码部分. import numpy as np import cv2 import glob import ...
- 【多传感融合】优达学城多传感融合学习笔记(二)——将激光雷达点云俯视图映射到二维图像
将激光雷达点云俯视图映射到二维图像 目录 将激光雷达点云俯视图映射到二维图像 简介 实现方法 参考代码 简介 本节讲解如何将激光雷达点云俯视图(仅考虑水平坐标)映射到二维图像中,其中涉及到激光雷达点云 ...
最新文章
- .net System.Web.Caching.Cache缓存类使用详解(转载)
- 如何让PhpStorm同时打开多个项目?(多项目并存的问题)
- android edittext不可复制_Android EditText禁止复制粘贴
- 如何在keil下实现单工程多目标的设置(选择性自动编译)
- 【IT笔试面试题整理】反转链表
- 史上最简单的SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon)(Finchley版本)
- jlabel字怎么变化_疫情在家烦躁不如学习怎样练好字吧
- 嵌入式linux基础学习全套精品视频教程
- python调用 ole:win32com用法详解
- STM32+AD7705实现电压采集
- Android音视频——Libyuv使用实战
- 代码精进之路 码农到工匠pdf_专访张建飞:阿里技术也提倡,优雅代码和整洁架构...
- 服务器多开虚拟,个人服务器多开虚拟主机
- MATLAB数学建模 回归与内插
- 安防巡逻机器人在不同应用场景下的作用是什么?
- 网站访问量等数据统计
- 手把手带你写一个中断输入设备驱动~
- 华擎主板设置来电开机_主板四大品牌BIOS设置开机第一启动项图文教程
- 计算机科学技术考研内容,计算机科学与技术考研考什么 具体内容有哪些
- 三聚氰胺,究竟是谁的错?