【小白学习PyTorch教程】十三、迁移学习:微调Alexnet实现ant和bee图像分类

2023-11-17

「@Author:Runsen」

上次微调了VGG19,这次微调Alexnet实现ant和bee图像分类。

多年来,CNN许多变体已经发展起来,从而产生了几种 CNN 架构。其中最常见的是:

  1. LeNet-5 (1998)

  2. AlexNet (2012)

  3. ZFNet (2013)

  4. GoogleNet / Inception(2014)

  5. VGGNet (2014)

  6. ResNet (2015)

这篇博客是 关于AlexNet 教程,AlexNet 也是之前受欢迎的 CNN 架构之一。

AlexNet

AlexNet主要由 Alex Krizhevsky 设计。它由 Ilya Sutskever 和 Krizhevsky 的博士生导师 Geoffrey Hinton 共同发表,是卷积神经网络或 CNN。

在参加 ImageNet 大规模视觉识别挑战赛后,AlexNet 一举成名。Alexnet在分类任务中实现了 84.6% 的前 5 名准确率,而排名第二的团队的前 5 名准确率为 73.8%。由于 2012 年的计算能力非常有限,Alex 在 2 个 GPU 上对其进行了训练。

2012 Imagenet 挑战赛的 Alexnet 架构。=

上图是2012 Imagenet 挑战赛的 Alexnet 架构

224x224x3
227x227x3
  1. AlexNet 架构由 5 个卷积层、3 个最大池化层、2 个归一化层、2 个全连接层和 1 个 softmax 层组成。

  2. 每个卷积层由卷积滤波器和非线性激活函数ReLU组成。

  3. 池化层用于执行最大池化。

  4. 由于全连接层的存在,输入大小是固定的。

  5. 输入大小之前在大多数被提及为 224x224x3,但由于一些填充,变成了 227x227x3

  6. AlexNet 总共有 6000 万个参数。

下面是Alexnet中的 227x227x3 模型参数

Size / Operation Filter Depth Stride Padding Number of Parameters Forward Computation
3* 227 * 227





Conv1 + Relu 11 * 11 96 4
(11 * 11 *3  + 1) * 96=34944 (11113 + 1) * 96 * 55 * 55=105705600
96 * 55 * 55





Max Pooling 3 * 3
2


96 * 27 * 27





Norm





Conv2 + Relu 5 * 5 256 1 2 (5 * 5 * 96 + 1) * 256=614656 (5 * 5 * 96 + 1) * 256 * 27 * 27=448084224
256 * 27 * 27





Max Pooling 3 * 3
2


256 * 13 * 13





Norm





Conv3 + Relu 3 * 3 384 1 1 (3 * 3 * 256 + 1) * 384=885120 (3 * 3 * 256 + 1) * 384 * 13 * 13=149585280
384 * 13 * 13





Conv4 + Relu 3 * 3 384 1 1 (3 * 3 * 384 + 1) * 384=1327488 (3 * 3 * 384 + 1) * 384 * 13 * 13=224345472
384 * 13 * 13





Conv5 + Relu 3 * 3 256 1 1 (3 *  3 *  384 + 1) * 256=884992 (3 * 3 * 384 + 1) * 256 * 13 * 13=149563648
256 * 13 * 13





Max Pooling 3 * 3
2


256 * 6 * 6





Dropout (rate 0.5)





FC6 + Relu



256 * 6 * 6 * 4096=37748736 256 * 6 * 6 * 4096=37748736
4096





Dropout (rate 0.5)





FC7 + Relu



4096 * 4096=16777216 4096 * 4096=16777216
4096





FC8 + Relu



4096 * 1000=4096000 4096 * 1000=4096000
1000 classes





Overall



62369152=62.3 million 1135906176=1.1 billion
Conv VS FC



Conv:3.7million (6%) , FC: 58.6 million (94% ) Conv: 1.08 billion (95%) , FC: 58.6 million (5%)

数据集介绍

本数据集中存在PyTorch相关入门的数据集ant和bee案例,每一个ant和bee

数据来源:PyTorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】

「关于数据集和代码见文末」

  1. 读取数据

这里选择将数据reshape成224*224。

import torch
import numpy as np
import matplotlib.pyplot as plt
import torch.nn.functional as F
from torch import nn
from torchvision import datasets, transforms, models

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

#transforms
transform_train = transforms.Compose([transforms.Resize((224, 224)),
                                      transforms.RandomHorizontalFlip(),
                                      transforms.RandomAffine(0, shear=10, scale=(0.8, 1.2)),
                                      transforms.ColorJitter(brightness=1, contrast=1, saturation=1),
                                      transforms.ToTensor(),
                                      transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
                                    ])

transform = transforms.Compose([transforms.Resize((224, 224)),
                               transforms.ToTensor(),
                               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
                               ])
root_train = 'ants_and_bees/train'
root_val = 'ants_and_bees/val'

training_dataset = datasets.ImageFolder(root=root_train, transform=transform)
validation_dataset = datasets.ImageFolder(root=root_val, transform=transform)
training_loader = torch.utils.data.DataLoader(training_dataset, batch_size=20, shuffle=True)
validation_loader = torch.utils.data.DataLoader(validation_dataset, batch_size = 20, shuffle=False)
  1. 展示数据

dataiter = iter(training_loader)
images, labels = dataiter.next()
fig = plt.figure(figsize=(25,6))

def im_convert(tensor):
  image = tensor.cpu().clone().detach().numpy()
  image = image.transpose(1, 2, 0) #shape 32 x 32 x 1
  #de-normalisation - multiply by std and add mean
  image = image * np.array((0.5, 0.5, 0.5)) + np.array((0.5, 0.5, 0.5))
  image = image.clip(0, 1)
  return image

for idx in np.arange(20):
  ax = fig.add_subplot(2, 10, idx+1, xticks=[], yticks=[])
  plt.imshow(im_convert(images[idx]))
  #print(labels[idx].item())
  ax.set_title(classes[labels[idx].item()])
plt.show()
  1. 微调Alexnet

model = models.alexnet(pretrained=True)
print(model)

AlexNet(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(11, 11), stride=(4, 4), padding=(2, 2))
    (1): ReLU(inplace=True)
    (2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
    (3): Conv2d(64, 192, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (4): ReLU(inplace=True)
    (5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
    (6): Conv2d(192, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (7): ReLU(inplace=True)
    (8): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (9): ReLU(inplace=True)
    (10): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU(inplace=True)
    (12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(6, 6))
  (classifier): Sequential(
    (0): Dropout(p=0.5, inplace=False)
    (1): Linear(in_features=9216, out_features=4096, bias=True)
    (2): ReLU(inplace=True)
    (3): Dropout(p=0.5, inplace=False)
    (4): Linear(in_features=4096, out_features=4096, bias=True)
    (5): ReLU(inplace=True)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

通过转移学习,我们将使用从卷积层中提取的特征 需要把最后一层的out_features=1000,改为out_features=2

因为我们的模型只对蚂蚁和蜜蜂进行分类,所以输出应该是2,而不是AlexNet的输出层中指定的1000。因此,我们改变了AlexNet中的classifier第6个元素的输出。

for param in model.features.parameters():
  `param.requires_grad = False                     

import torch.nn as nn

n_inputs = model.classifier[6].in_features      #4096
last_layer = nn.Linear(n_inputs, len(classes))
model.classifier[6] = last_layer
model.to(device)

print(model)

AlexNet(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(11, 11), stride=(4, 4), padding=(2, 2))
    (1): ReLU(inplace=True)
    (2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
    (3): Conv2d(64, 192, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (4): ReLU(inplace=True)
    (5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
    (6): Conv2d(192, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (7): ReLU(inplace=True)
    (8): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (9): ReLU(inplace=True)
    (10): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU(inplace=True)
    (12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(6, 6))
  (classifier): Sequential(
    (0): Dropout(p=0.5, inplace=False)
    (1): Linear(in_features=9216, out_features=4096, bias=True)
    (2): ReLU(inplace=True)
    (3): Dropout(p=0.5, inplace=False)
    (4): Linear(in_features=4096, out_features=4096, bias=True)
    (5): ReLU(inplace=True)
    (6): Linear(in_features=4096, out_features=2, bias=True)
  )
)
  1. 训练和测试模型

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001)

epochs = 5
losses = []
accuracy = []
val_losses = []
val_accuracies = []

for e in range(epochs):
  running_loss = 0.0
  running_accuracy = 0.0
  val_loss = 0.0
  val_accuracy = 0.0

  for images, labels in training_loader:
    images = images.to(device)
    labels = labels.to(device)
    outputs = model(images)   
    loss = criterion(outputs, labels)

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    _, preds = torch.max(outputs, 1)
    running_accuracy += torch.sum(preds == labels.data)
    running_loss += loss.item() 

    #不必为验证集执行梯度
    with torch.no_grad():       
      for val_images, val_labels in validation_loader:
        val_images = val_images.to(device)
        val_labels = val_labels.to(device)
        val_outputs = model(val_images)
        val_loss = criterion(val_outputs, val_labels)

        _, val_preds = torch.max(val_outputs, 1)
        val_accuracy += torch.sum(val_preds == val_labels.data)
        val_loss += val_loss.item() 
    # metrics for training data
    epoch_loss = running_loss/len(training_loader.dataset)
    epoch_accuracy = running_accuracy.float()/len(training_loader.dataset)
    losses.append(epoch_loss)
    accuracy.append(epoch_accuracy)
    # metrics for validation data
    val_epoch_loss = val_loss/len(validation_loader.dataset)
    val_epoch_accuracy = val_accuracy.float()/len(validation_loader.dataset)
    val_losses.append(val_epoch_loss)
    val_accuracies.append(val_epoch_accuracy)
    #print the training and validation metrics
    print("epoch:", e+1)
    print('training loss: {:.6f}, acc {:.6f}'.format(epoch_loss, epoch_accuracy.item()))
    print('validation loss: {:.6f}, acc {:.6f}'.format(val_epoch_loss, val_epoch_accuracy.item()))
plt.plot(losses, label='training loss')
plt.plot(val_losses, label='validation loss')
plt.legend()
plt.show()
plt.plot(accuracy, label='training accuracy')
plt.plot(val_accuracies, label = 'validation accuracy')
plt.legend()
plt.show()
dataiter = iter(validation_loader)
images, labels = dataiter.next()
images = images.to(device)
labels = labels.to(device)
output = model(images)
_, preds = torch.max(output, 1)

fig = plt.figure(figsize=(25, 4))

for idx in np.arange(20):
  ax = fig.add_subplot(2, 10, idx+1, xticks=[], yticks=[])
  plt.imshow(im_convert(images[idx]))
  ax.set_title("{} ({})".format(str(classes[preds[idx].item()]), str(classes[labels[idx].item()])), color=("green" if preds[idx]==labels[idx] else "red"))

plt.show()

PyTorch中使用alexnet的官方文档:

  • https://pytorch.org/hub/pytorch_vision_alexnet/

代码和数据下载:

链接:https://pan.baidu.com/s/1KKcl4I97kIcv83HLZVoHDg 提取码:tun1


往期精彩回顾



适合初学者入门人工智能的路线及资料下载机器学习及深度学习笔记等资料打印机器学习在线手册深度学习笔记专辑《统计学习方法》的代码复现专辑
AI基础下载机器学习的数学基础专辑黄海广老师《机器学习课程》课件合集
本站qq群851320808,加入微信群请扫码:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【小白学习PyTorch教程】十三、迁移学习:微调Alexnet实现ant和bee图像分类 的相关文章

随机推荐

  • json数组如何转换成string类型(超级好用)

    先上代码 下面解释 这个jar包地址之后更新的时候再给出来的 包的地址 JSONObject job ace text a 此时job里面的数据格式为 logid 2075 words result words acb words and
  • Using / for division outside of calc() is deprecated and will be removed in Dart Sass 2.0.0

    项目 taro3 vue3 描述 运行时警告 Deprecation Warning Using for division outside of calc is deprecated and will be removed in Dart
  • LeetCode 102. 二叉树的层序遍历BFS

    LeetCode 102 二叉树的层序遍历BFS 给你二叉树的根节点 root 返回其节点值的 层序遍历 即逐层地 从左到右访问所有节点 示例 1 输入 root 3 9 20 null null 15 7 输出 3 9 20 15 7 示
  • 机器学习:正则化

    正则化 引入正则化的目的是为了解决过拟合问题 左边的图中蓝色的线是目标函数 随机产生五个带噪声的点 我们理想的拟合曲线为红色的线 虽然有些许误差 但是整体拟合情况和目标函数接近 但是 事先不知道需要用二次曲线来拟合这些点 如果使用了更高次方
  • Vue2/Vue3 响应式原理

    Vue 2 x 版本与 Vue 3 x 版本的响应式实现有所不同 Vue 2 x 响应式基于 ES5 的 Object defineProperty 实现 Vue 3 x 响应式基于 ES6 的 Proxy 实现 Vue 2 响应式原理 V
  • Halcon与WPF联合编程

    环境 VS2017 halcon12 1 新建WPF应用程序完成后 解决方案资源管理器 引用处右键 添加引用如下两个dll 只引入第一个也可以 2 工具箱 空白处右键 选择项 只添加halcondotnet dll 文件位置同上 这样hal
  • 【TVM帮助文档学习】开始使用TVMC Python: TVM的高级API

    本文翻译自Getting Starting using TVMC Python a high level API for TVM tvm 0 9 dev0 documentation 首先我们需要准备好示例使用resnet模型 如果你还没有
  • [技术分享]Android平台实时音视频录像模块设计之道

    实现背景 录像有什么难的 无非就是数据过来 编码保存mp4而已 这可能是好多开发者在做录像模块的时候的思考输出 是的 确实不难 但是做好 或者和其他模块有非常好的逻辑配合 确实不容易 好多开发者希望聊聊录像模块 实际上录像这块 需求层面的东
  • 浏览器缓存机制及其分类

    聚沙成塔 每天进步一点点 专栏简介 强缓存 Cache Control 和 Expires 协商缓存 ETag 和 Last Modified 写在最后 专栏简介 前端入门之旅 探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦
  • 解决ros安装 使用roscore命令测试问题

    本人安装教程完成ROS的安装后 在进行测试如图1命令 出现 解决办法输入完命令1后要输入命令2才行 即可测试成功 测试成功的界面如下
  • caxa线切割怎样画链轮,收藏:Autocad实战教程-线切割画链轮

    Autocad实战教程 线切割画链轮 今天小编为各位朋友准备的内容是Autocad实战教程 线切割画链轮 希望能对各位朋友有所帮助 用AutoCAD绘制链轮首先要知道一些参数 d1为链条滚子直径 套铜直径 p为节距 链条两孔中心的距离也是链
  • c/c++开发时的VsCode插件

    Name Align Spaces Id OldStarchy align spaces Description Align operators without modifying the code 在不修改代码的情况下对齐操作符 Vers
  • 华为杯数学建模(准备)<2018 - 2022>

    前言 这里简单总结一些资料 为后期个人参赛做准备 其中的优秀案例皆以博客 链接的形式总结归纳 详细见对应原作者博客 基础知识 一些需要提前掌握的算法 1 时间序列算法 拟合插值算法 基础的图论算法 2 多元线性回归 3 整数规划 线性规划
  • 8. 让java性能提升的JIT深度解剖

    JVM性能调优 1 C1 C2与Graal编译器 1 1 C1编译器 1 2 C2编译器 1 3 分层编译 2 热点代码 3 热点探测 4 方法调用计数器 5 回边计数器 6 编译优化技术 6 1 方法内联 7 锁消除 8 栈上分配 9 逃
  • qt多文档

    http blog csdn net siren0203 article details 5661541 转载于 https www cnblogs com tiandsp p 7580571 html
  • 如何将照片中的文字转变成可编辑的文章(如何将书上的文字转变为可编辑的文字)

    在工作中 我常常在想 要是能把纸上有用的文字快速输入到电脑中 不用打字录入便可以大大提高工作效率该有多好呀 随着科技的发展 这个问题在不断的解决 例如 现在市场上的扫描仪就带有OCR软件 可以把扫描的文字转换到电脑中进行编辑 但是 对于我们
  • HwBinder入门篇-Android10.0 HwBinder通信原理(一)

    Android取经之路 的源码都基于Android Q 10 0 进行分析 Android取经之路 系列文章 系统启动篇 Android系统架构Android是怎么启动的Android 10 0系统启动之init进程Android10 0系
  • PHP模拟上传文件使用CURLFile函数 加精!!!

    一 CURLFile 介绍 CURLFile construct PHP 5 gt 5 5 0 PHP 7 CURLFile construct curl file create 创建 CURLFile 对象 说明 面向对象风格 publi
  • vb调用python程序_VB_Python代码对照算法百题(018)

    VB代码 2018年4月浙江 17 分析数组a中各元素依次变化的情况 进行如下定义 变化段 数组中相邻两个元素构成一个变化段 变化段有上升段 a i gt a i 1 下降段 a i 波峰 从上升段到下降段形成一个波峰 波峰的起点是峰顶前所
  • 【小白学习PyTorch教程】十三、迁移学习:微调Alexnet实现ant和bee图像分类

    Author Runsen 上次微调了VGG19 这次微调Alexnet实现ant和bee图像分类 多年来 CNN许多变体已经发展起来 从而产生了几种 CNN 架构 其中最常见的是 LeNet 5 1998 AlexNet 2012 ZFN