目录

加载和预处理数据

转换数据

数据加载器和数据可视化

定义模型

最终分类器层

指定损失函数和优化器

训练

测试

可视化样本测试结果


大多数时候,你不会想自己训练一个完整的卷积网络。像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:迁移学习相关推荐

  1. 优达学城《无人驾驶入门》学习笔记——卡尔曼滤波器实现详解

    优达学城<无人驾驶入门>的第二个项目是实现矩阵类,要求通过python编写一个用来计算矩阵的类Matrix.编写这个类并不难,涉及到的线性代数方面的知识也不多,比如矩阵的加法.减法.乘法, ...

  2. 优达学城(Udacity)深度学习笔记-1.Pythonos学习

    欢迎使用Markdown编辑器写博客 Python对于文件操作非常方便,很大一部分是因为os这个库,在做优达城深度学习作业的时候里面有一堆os,各种列表推导式混合os.path,一下就绕晕了.这里做点 ...

  3. 来自优达学城毕业生和导师的学习建议

    时刻牢记你的目标: "找不到学习动力? 时刻明确自己前行的目标.多看一些技术大牛的访谈和f分享,关注他们的社交媒体,你会发现他们也都曾和你一样,从零做起,日夜兼程." 拆分学习计划 ...

  4. 优达学城《DeepLearning》大纲和学习愿景

    目的: 查漏补缺深度学习体系,精益求精的深刻理解体系中各种核心的技术原理,感受技术思想背后的精髓魅力,做到能够脱口而出. 计划: 2021年5月.6月,完成课程中所有核心知识的深刻理解(通过撰写博客, ...

  5. 优达学城 深度学习 任务1

    这几天刚好有环境,打算学习一下深度学习 看了一圈介绍,发现优达学城的深度学习课程作为入门课程还是不错的 今天看了第一章节的视频,顺便做了任务1 任务1难度不大,按照网站上的说明可以完成下载.打包等工作 ...

  6. 优达学城计算机视觉pkl,优达学城机器学习工程师纳米学位项目介绍

    本文由 meelo 原创,请务必以链接形式注明 本文地址,简书同步更新地址 一对一的项目辅导是优达学城纳米学位的一大亮点.本文将简要介绍优达学城机器学习工程师纳米学位的6个项目.项目覆盖了机器学习的主 ...

  7. 无人驾驶8: 粒子滤波定位(优达学城项目)

    优达学城无人车定位的项目实现: 粒子滤波算法流程图 粒子滤波的伪代码: step1:初始化 理论上说,当粒子数量足够多时,能准确地呈现贝叶斯后验分布,如果粒子太少,可能漏掉准确位置,粒子数量太多,会拖 ...

  8. 优达学城无人驾驶工程师——P5车辆检测功能

    这次讲的是优达学城无人驾驶工程师第一期的最后一个项目,车辆检测功能,代码如下. 导包 import cv2 import numpy as np import matplotlib.pyplot as ...

  9. 优达学城无人驾驶工程师——P4车道线检测功能

    这次讲的是优达学城的无人驾驶工程师的P4项目,利用车前方的摄像头检测车道线,下面开始我们的代码部分. import numpy as np import cv2 import glob import ...

  10. 【多传感融合】优达学城多传感融合学习笔记(二)——将激光雷达点云俯视图映射到二维图像

    将激光雷达点云俯视图映射到二维图像 目录 将激光雷达点云俯视图映射到二维图像 简介 实现方法 参考代码 简介 本节讲解如何将激光雷达点云俯视图(仅考虑水平坐标)映射到二维图像中,其中涉及到激光雷达点云 ...

最新文章

  1. .net System.Web.Caching.Cache缓存类使用详解(转载)
  2. 如何让PhpStorm同时打开多个项目?(多项目并存的问题)
  3. android edittext不可复制_Android EditText禁止复制粘贴
  4. 如何在keil下实现单工程多目标的设置(选择性自动编译)
  5. 【IT笔试面试题整理】反转链表
  6. 史上最简单的SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon)(Finchley版本)
  7. jlabel字怎么变化_疫情在家烦躁不如学习怎样练好字吧
  8. 嵌入式linux基础学习全套精品视频教程
  9. python调用 ole:win32com用法详解
  10. STM32+AD7705实现电压采集
  11. Android音视频——Libyuv使用实战
  12. 代码精进之路 码农到工匠pdf_专访张建飞:阿里技术也提倡,优雅代码和整洁架构...
  13. 服务器多开虚拟,个人服务器多开虚拟主机
  14. MATLAB数学建模 回归与内插
  15. 安防巡逻机器人在不同应用场景下的作用是什么?
  16. 网站访问量等数据统计
  17. 手把手带你写一个中断输入设备驱动~
  18. 华擎主板设置来电开机_主板四大品牌BIOS设置开机第一启动项图文教程
  19. 计算机科学技术考研内容,计算机科学与技术考研考什么 具体内容有哪些
  20. 三聚氰胺,究竟是谁的错?

热门文章

  1. [认证授权] 6.Permission Based Access Control
  2. Java动态代理和静态代理区别
  3. 使用hibernate与mysql时数据不能插入的原因及解决办法
  4. Matlab-bp神经网络
  5. Beta阶段总结博客(麻瓜制造者)
  6. 结队编程-基于gui的四则运算生成器
  7. STM8S103 解决Rom空间不足 Map文件分析
  8. innodb force recovery
  9. 判断两直线段是否相交
  10. 逻辑回归算法原理简介