卷积神经网络CNN入门【pytorch学习】

朴灿烈づ我的快乐病毒、 2022-04-17 00:04 539阅读 0赞

简述

在学习GANs的时候遇到一篇论文DCGANs,说是其中用到了卷积神经网络。
所以,就抽空学习一下,结果,真没想到有那么多的坑。

文章目录

    • 简述
    • 数据配置
      • 配套的代码段
    • 参数设置
    • 训练集批处理构建
    • 测试集
    • 构建CNN框架
    • 训练
    • 测试结果
    • 全部代码
    • 参考

数据配置

第一步配置数据的时候就贼坑了。。。

  • 看下面的这一篇文章就可以解决,就是手动下载之后,放在一个目录下,之后,再修改源码中指定的位置,之后再运行,代码会从本地下载(其实就是转移位置),但是由于它同时也会生成两个c文件。所以,不推荐直接手动的建目录之类的操作
  • pytorch下载mnist超时解决方案

配套的代码段

  1. import torch
  2. import torch.nn as nn
  3. import torchvision
  4. import torch.utils.data as Data
  5. DOWNLOAD_MNIST = True # 已经下载好的话,会自动跳过的
  6. # Mnist 手写数字
  7. train_data = torchvision.datasets.MNIST(
  8. root='./mnist/', # 保存或者提取位置
  9. train=True, # this is training data
  10. transform=torchvision.transforms.ToTensor(), # 转换 PIL.Image or numpy.ndarray 成
  11. # torch.FloatTensor (C x H x W), 训练的时候 normalize 成 [0.0, 1.0] 区间
  12. download=DOWNLOAD_MNIST, # 没下载就下载, 下载了就不用再下了
  13. )
  14. test_data = torchvision.datasets.MNIST(
  15. root='./mnist/',
  16. train=False
  17. )

参数设置

  • 这里只测试一次的原因其实是,训练集有60000个。虽然之后使用批处理的方式,但是我们BATCH_SIZE设置为了50,所以,也有1200次的训练了。所以,只用一次就好了。
  • BATCH_SIZE 就是每一次训练的那个块中的数据数量
  • LR学习率

这些参数在建立GANs的时候也用到了。

  1. # Hyper Parameters
  2. EPOCH = 1 # 训练整批数据多少次, 为了节约时间, 我们只训练一次
  3. BATCH_SIZE = 50
  4. LR = 0.001 # 学习率

训练集批处理构建

  1. # 训练集丢BATCH_SIZE个, 图片大小为28*28
  2. train_loader = Data.DataLoader(
  3. dataset=train_data,
  4. batch_size=BATCH_SIZE,
  5. shuffle=True # 是否打乱顺序
  6. )

测试集

其实这里调用出来是没有什么用,但是任然放出来了,主要是为了跟学习的一份代码中保持一致性。找bug的时候,这样很方便。

但是这里有一个重点(对于新手)

  • torch.unsqueeze()函数,给数组加上一个维度。dim=1表示在添加的这个维度是再哪?
  • 比如dim=1时候
  • (10,20)变成了(10,1,20)

    test_data为 [10000, 28, 28]这样的一个数组,这里就只截取一段就好了

    test_x = torch.unsqueeze(test_data.test_data, dim=1).type(torch.FloatTensor)
    test_y = test_data.test_labels

构建CNN框架

  • nn.Module非常常见的自定义类,所有模型的基类
  • 第一个网络是:先是一个卷积,再是一个ReLU激活函数,最后再来个最大池化

如果真的是新手的话,会发下这里贼多知识点。

  • 先看懂什么是卷积
  • 再搞定padding,stride这些参数什么意思
  • 池化: 这个反而是最简单的。就是给一个矩形(小一点的),然后通过一定的移动方式,在这个区间上找最大值。然后不重复的这样遍历完所有的像素点。得到的一张新图(新的张量)
  • 所以,我在注释的地方表示的是到这里的时候这个数据的shape
  • 通过.view(shape(0),-1) 这样的方式,将数据展开为一个一维向量。之后,再通过一个线性函数,转成10个线性函数的结果来。(表示对应10个数字的概率(其实可能是负数的,但是会逐渐的改善,大致上能拟合出结果来)

    class CNN(nn.Module):

    1. def __init__(self):
    2. super(CNN, self).__init__()
    3. self.layer1 = nn.Sequential(
    4. # (1, 28, 28)
    5. nn.Conv2d(
    6. in_channels=1,
    7. out_channels=16,
    8. kernel_size=5, # 卷积filter, 移动块长
    9. stride=1, # filter的每次移动步长
    10. padding=2,
    11. groups=1
    12. ),
    13. # (16, 28, 38)
    14. nn.ReLU(),
    15. nn.MaxPool2d(kernel_size=2)
    16. # (16, 14, 14)
    17. )
    18. self.layer2 = nn.Sequential(
    19. nn.Conv2d(
    20. in_channels=16,
    21. out_channels=32,
    22. kernel_size=5,
    23. stride=1,
    24. padding=2
    25. ),
    26. nn.ReLU(),
    27. nn.MaxPool2d(kernel_size=2)
    28. )
    29. self.layer3 = nn.Linear(32 * 7 * 7, 10)
    30. def forward(self, x):
    31. # print(x.shape)
    32. x = self.layer1(x)
    33. # print(x.shape)
    34. x = self.layer2(x)
    35. # print(x.shape)
    36. x = x.view(x.size(0), -1)
    37. # print(x.shape)
    38. x = self.layer3(x)
    39. # print(x.shape)
    40. return x

训练

  • 这里的遍历,其实是会把所有的训练集数据都训练过一遍为止。
  • 损失函数调用的是交叉熵。https://blog.csdn.net/zziahgf/article/details/80196376
  • 公式的含义,其实非常简单,就是希望目标数对应下标的那个数值要大一点。但是又不能是因为所有为止上的点的数值都变大导致了。

    cnn = CNN()

    optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)
    loss_function = nn.CrossEntropyLoss()
    for epoch in range(EPOCH):

    1. for step, (b_x, b_y) in enumerate(train_loader):
    2. output = cnn(b_x)
    3. loss = loss_function(output, b_y)
    4. optimizer.zero_grad()
    5. loss.backward()
    6. optimizer.step()

测试结果

  1. print('finished training')
  2. test_out = cnn(test_x)
  3. predict_y = torch.argmax(test_out, 1).data.numpy()
  4. print('Accuracy in Test : %.4f%%' % (sum(predict_y == test_y.data.numpy()) * 100/ len(predict_y)))

我这里跑的一个结果是

  1. finished training
  2. Accuracy in Test : 98.2000%

然后速度其实是有点慢的。之后会再看看其他的实现。

全部代码

  1. import torch
  2. import torch.nn as nn
  3. import torchvision
  4. import torch.utils.data as Data
  5. # Hyper Parameters
  6. EPOCH = 1 # 训练整批数据多少次, 为了节约时间, 我们只训练一次
  7. BATCH_SIZE = 50
  8. LR = 0.001 # 学习率
  9. DOWNLOAD_MNIST = True # 已经下载好的话,会自动跳过的
  10. # Mnist 手写数字
  11. train_data = torchvision.datasets.MNIST(
  12. root='./mnist/', # 保存或者提取位置
  13. train=True, # this is training data
  14. transform=torchvision.transforms.ToTensor(), # 转换 PIL.Image or numpy.ndarray 成
  15. # torch.FloatTensor (C x H x W), 训练的时候 normalize 成 [0.0, 1.0] 区间
  16. download=DOWNLOAD_MNIST, # 没下载就下载, 下载了就不用再下了
  17. )
  18. test_data = torchvision.datasets.MNIST(
  19. root='./mnist/',
  20. train=False
  21. )
  22. # 训练集丢BATCH_SIZE个, 图片大小为28*28
  23. train_loader = Data.DataLoader(
  24. dataset=train_data,
  25. batch_size=BATCH_SIZE,
  26. shuffle=True # 是否打乱顺序
  27. )
  28. # test_data为 [10000, 28, 28]这样的一个数组,这里就只截取一段就好了
  29. test_x = torch.unsqueeze(test_data.test_data, dim=1).type(torch.FloatTensor)
  30. test_y = test_data.test_labels
  31. # cnn
  32. class CNN(nn.Module):
  33. def __init__(self):
  34. super(CNN, self).__init__()
  35. self.layer1 = nn.Sequential(
  36. # (1, 28, 28)
  37. nn.Conv2d(
  38. in_channels=1,
  39. out_channels=16,
  40. kernel_size=5, # 卷积filter, 移动块长
  41. stride=1, # filter的每次移动步长
  42. padding=2,
  43. groups=1
  44. ),
  45. # (16, 28, 38)
  46. nn.ReLU(),
  47. nn.MaxPool2d(kernel_size=2)
  48. # (16, 14, 14)
  49. )
  50. self.layer2 = nn.Sequential(
  51. nn.Conv2d(
  52. in_channels=16,
  53. out_channels=32,
  54. kernel_size=5,
  55. stride=1,
  56. padding=2
  57. ),
  58. nn.ReLU(),
  59. nn.MaxPool2d(kernel_size=2)
  60. )
  61. self.layer3 = nn.Linear(32 * 7 * 7, 10)
  62. def forward(self, x):
  63. # print(x.shape)
  64. x = self.layer1(x)
  65. # print(x.shape)
  66. x = self.layer2(x)
  67. # print(x.shape)
  68. x = x.view(x.size(0), -1)
  69. # print(x.shape)
  70. x = self.layer3(x)
  71. # print(x.shape)
  72. return x
  73. cnn = CNN()
  74. optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)
  75. loss_function = nn.CrossEntropyLoss()
  76. for epoch in range(EPOCH):
  77. for step, (b_x, b_y) in enumerate(train_loader):
  78. output = cnn(b_x)
  79. loss = loss_function(output, b_y)
  80. optimizer.zero_grad()
  81. loss.backward()
  82. optimizer.step()
  83. print('finished training')
  84. test_out = cnn(test_x)
  85. predict_y = torch.argmax(test_out, 1).data.numpy()
  86. print('Accuracy in Test : %.4f%%' % (sum(predict_y == test_y.data.numpy()) * 100/ len(predict_y)))

参考

  • https://morvanzhou.github.io/tutorials/machine-learning/tensorflow/5-03-A-CNN/
  • https://github.com/sunshineatnoon/Paper-Implementations

发表评论

表情:
评论列表 (有 0 条评论,539人围观)

还没有评论,来说两句吧...

相关阅读

    相关 神经网络CNN

    系列文章目录 上一篇文章简单的介绍了卷积神经网络及一些基础知识,比如说步长,填充,互相关运算等,这篇文章讲介绍卷积神经网络的组成及常见的几种神经网络。  [CNN简单介