当前位置:   article > 正文

python 使用卷积神经网络处理手写数字识别数据集_如何用python解决神经网络在数字识别中的问题含运行结果

如何用python解决神经网络在数字识别中的问题含运行结果

LeNet-5 网络模型

        LeNet-5神经网络一共五层,其中卷积层和池化层可以考虑为一个整体。网络结构如下:
输入→卷积→池化→卷积→池化→卷积(全连接)→全连接→输出

层数in_channelout_channelkernel_sizestridepadding
卷积层c116512
池化层s266220
卷积层c3616510
池化层s4616220
卷积层c516120
全连接层F612084
输出层8410


使用小批量数据集训练,规模为64。

代码如下:

这里为了绘制一个好看的图,81行和82行参数为20,1自己训练时建议更改

  1. import torchvision as tv # 专门用来处理图像的库
  2. from torchvision import transforms # transforms用来对图片进行变换
  3. import os # 用于加载旧模型使用
  4. import numpy as np
  5. import torch
  6. import torch.nn as nn # 神经网络基本工具箱
  7. import torch.nn.functional as fun
  8. import matplotlib.pyplot as plt # 绘图模块,能绘制 2D 图表
  9. from torchvision.transforms import ToPILImage
  10. import torchvision
  11. # 读取数据
  12. def read_data(file):
  13. # 数据预处理
  14. transform = transforms.Compose([
  15. transforms.ToTensor(), # 将图片类型由 PIL Image 转化成tensor类型。转换时会自动归一化
  16. transforms.Normalize((0.5), (0.5))]) # 对图像进行标准化(均值变为0,标准差变为1
  17. # 从网上下载手写数字识别数据集
  18. train_data = torchvision.datasets.MNIST(root=file, train=True, transform=transform, download=True)
  19. test_data = torchvision.datasets.MNIST(root=file, train=False, transform=transform, download=True)
  20. return train_data, test_data
  21. # 定义卷积神经网络==========================================================
  22. class ConvNet(nn.Module): # 类 ConvNet 继承自 nn.Module
  23. def __init__(self): # 构造方法
  24. # 下式等价于nn.Module.__init__.(self)
  25. super(ConvNet, self).__init__() # 调用父类构造方法
  26. # 使用了三个卷积层,两个全连接层
  27. # 卷积层===========================================================
  28. self.conv1 = nn.Conv2d(1, 6, 5, padding=2) # 输入1通道,输出6通道,卷积核为5*5,两端补2个零
  29. self.conv2 = nn.Conv2d(6, 16, 5) # 输入6通道,输出16通道,卷积核为5*5
  30. self.conv3 = nn.Conv2d(16, 120, 5) # 输入16通道,输出120通道,卷积核为5*5
  31. # 全连接层=========================================================
  32. self.fc1 = nn.Linear(120, 84) # 输入120,输84
  33. self.fc2 = nn.Linear(84, 10) # 输入84,输出10
  34. def forward(self, x):
  35. # 最大池化步长为2
  36. x = fun.max_pool2d(fun.relu(self.conv1(x)), 2) # 1*28*28 -> 6*28*28 -> 6*14*14
  37. x = fun.max_pool2d(fun.relu(self.conv2(x)), 2) # 6*14*14 -> 16*10*10 -> 16*5*5
  38. x = fun.relu(self.conv3(x)) # 16*5*5 -> 120*1*1
  39. x = x.view(x.size()[0], -1) # 展开成一维
  40. x = fun.relu(self.fc1(x)) # 全连接层 120 -> 84
  41. x = self.fc2(x) # 全连接层 84 -> 10
  42. return x
  43. file = 'D:\\python_mnist\mnist\\train' # 数据文件地址
  44. train_start, test_set = read_data(file)
  45. print('训练及图像有:', len(train_start), '张。\n测试集图像有:', len(test_set), '张。')
  46. # 打包数据集 python将多个数据打包处理,能够加快训练速度
  47. batch_size = 64 # 批量大小为
  48. # 将测试集和训练集每 4个 进行打包,并打乱训练集(shuffle)
  49. train_set = torch.utils.data.DataLoader(train_start, batch_size=batch_size, shuffle=True) # 训练集
  50. test_set = torch.utils.data.DataLoader(test_set, batch_size=batch_size, shuffle=False) # 测试集
  51. print("已将将数据集%2d 个打包为一组,加快训练速度" % batch_size)
  52. # 设置卷积神经网络和训练参数=================================
  53. print("正在加载卷积神经网络=========================================")
  54. # 如果设备 GPU 能被调用,则转到 GPU 加快运算,否则使用CPU
  55. device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  56. model = ConvNet().to(device) # 初始化模型
  57. print(device)
  58. print('可使用GPU加速' if (torch.cuda.is_available()) else '无法开启GPU加速')
  59. criterion = nn.CrossEntropyLoss() # 交叉熵损失函数
  60. # 模型加载==========================================
  61. seat = './cnn.pth' # 保存位置(名称)
  62. if os.path.exists(seat): # 如果检测到 seat 文件
  63. print("检测到模型文件,是否加载已训练模型(Y\\N):")
  64. shuru = input()
  65. if shuru == 'Y' or shuru == 'y':
  66. model.load_state_dict(torch.load(seat))
  67. print("已加载已训练模型")
  68. else:
  69. print("未加载已训练模型")
  70. else:
  71. print("未检测到旧模型文件")
  72. # 训练开始==========================================
  73. loop_MAX = 20 # 外循环次数(测试)
  74. loop = 1 # 内循环次数(训练)
  75. print("训练次数为:", loop * loop_MAX)
  76. print("每过 %d 轮执行自动测试以及模型保存" % loop)
  77. print("开始训练===================================================")
  78. Training_accuracy = [] # 记录训练集正确率
  79. Test_accuracy = [] # 记录测试集正确率
  80. process = [] # 记录训练时误差
  81. i = 0 # 函数内使用,提前定义
  82. lentrain = len(train_set)
  83. learning_rate = 0.003 # 基础学习率
  84. print("基础学习率为:", learning_rate)
  85. optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) # 优化器:随机梯度下降算法
  86. for j in range(loop_MAX): # j 测试轮数
  87. for epoch in range(loop): # 训练 loop 次 epoch 当前轮训练次数
  88. running_loss = 0.0 # 训练误差
  89. # 下面这个作用是每轮打乱一次,没什么大用处,不想要可以删去
  90. train_set = torch.utils.data.DataLoader(train_start, batch_size=batch_size, shuffle=True) # 训练集
  91. # enumerate() 函数:用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标。
  92. for i, (images, labels) in enumerate(train_set, 0):
  93. # 转到GPU或CPU上进行运算
  94. images = images.to(device)
  95. labels = labels.to(device)
  96. outputs = model(images) # 正向传播
  97. loss = criterion(outputs, labels) # 计算batch(四个一打包)误差
  98. optimizer.zero_grad() # 梯度清零
  99. loss.backward() # 反向传播
  100. optimizer.step() # 更新参数
  101. # 打印loss信息
  102. running_loss += loss.item() # batch的误差和
  103. print("第%2d/%2d 轮循环,%6d/%6d 组,误差为:%.4f"
  104. % (epoch + 1, loop, i + 1, lentrain, running_loss / i))
  105. process.append(running_loss)
  106. running_loss = 0.0 # 误差归零
  107. # 模型测试==========================================
  108. print("开始第%2d次测试===================================================" % (j + 1))
  109. # 在训练集上测试====================================
  110. correct = 0 # 预测正确图片数
  111. total = 0 # 总图片数
  112. ii = 0
  113. for images, labels in train_set:
  114. if ii > int(i / 10): # 训练集太多了,挑一点测试
  115. break
  116. ii = ii + 1
  117. images = images.to(device)
  118. labels = labels.to(device)
  119. outputs = model(images)
  120. # 返回得分最高的索引(一组 64 个)
  121. _, predicted = torch.max(outputs.data, 1)
  122. total += labels.size(0)
  123. correct += (predicted == labels).sum()
  124. print("第%d轮训练集上的准确率为:%3d %%" % ((j + 1) * loop, 100 * correct / total), end=' ')
  125. Training_accuracy.append(100 * correct / total)
  126. # 在测试集上测试====================================
  127. correct = 0 # 预测正确图片数
  128. total = 0 # 总图片数
  129. for images, labels in test_set:
  130. images = images.to(device)
  131. labels = labels.to(device)
  132. outputs = model(images)
  133. # 返回得分最高的索引(一组 64 个)
  134. _, predicted = torch.max(outputs.data, 1)
  135. total += labels.size(0)
  136. correct += (predicted == labels).sum()
  137. total = 100 * correct / total
  138. print("\t测试集上的准确率为:%3d %%" % total)
  139. Test_accuracy.append(total)
  140. # 模型保存==========================================
  141. print("模型已训练完成,是否保存已训练模型(Y\\N):")
  142. shuru = input()
  143. if shuru == 'Y' or shuru == 'y':
  144. torch.save(model.state_dict(), seat)
  145. print("保存模型至%s======================================" % seat)
  146. else:
  147. print("未保存已训练模型")
  148. # 绘制训练过程===========================================================
  149. # 从GPU中拿出来才能用来画图
  150. Training_accuracy = torch.tensor(Training_accuracy, device='cpu')
  151. Test_accuracy = torch.tensor(Test_accuracy, device='cpu')
  152. plt.figure(1) # =======================================
  153. # 误差随时间变化
  154. plt.plot(list(range(len(process))), process, label='loss')
  155. plt.legend(loc='lower right') # 显示上面的label
  156. plt.xlabel('time') # x_label
  157. plt.ylabel('loss') # y_label
  158. plt.title('loss about time') # 标题
  159. plt.figure(2) # =======================================
  160. # 正确率
  161. plt.plot(list(range(len(Training_accuracy))), Training_accuracy, label='Train_set')
  162. plt.plot(list(range(len(Test_accuracy))), Test_accuracy, label='Test_set')
  163. plt.legend(loc='lower right') # 显示上面的label
  164. plt.xlabel('time') # x_label
  165. plt.ylabel('loss') # y_label
  166. plt.title('Training_accuracy and Test_accuracy') # 标题
  167. plt.figure(3) # =======================================
  168. # 输出在测试集上一组(64个)的数据和预测结果===================
  169. dataiter = iter(test_set) # 生成测试集的可迭代对象
  170. images, labels = dataiter.next() # 得到一组数据
  171. npimg = (tv.utils.make_grid(images / 2 + 0.5)).numpy()
  172. plt.imshow(np.transpose(npimg, (1, 2, 0)))
  173. print("实际标签:", labels)
  174. show = ToPILImage() # 把tensor转为image
  175. images = images.to(device)
  176. labels = labels.to(device)
  177. outputs = model(images) # 计算图片在每个类别上的分数
  178. # 返回得分最高的索引
  179. _, predicted = torch.max(outputs.data, 1) # 第一个数是具体值,不需要
  180. # 一组 4 张图,所以找每行的最大值
  181. print("预测结果:", predicted)
  182. plt.show() # 显示========================================================

结果示例

  1. 训练及图像有: 60000 张。
  2. 测试集图像有: 10000 张。
  3. 已将将数据集64 个打包为一组,加快训练速度
  4. 正在加载卷积神经网络=========================================
  5. cuda
  6. 可使用GPU加速
  7. 未检测到旧模型文件
  8. 训练次数为: 20
  9. 每过 1 轮执行自动测试以及模型保存
  10. 开始训练===================================================
  11. 基础学习率为: 0.003
  12. 1/ 1 轮循环, 938/ 938 组,误差为:2.2994
  13. 开始第 1次测试===================================================
  14. 1轮训练集上的准确率为: 19 % 测试集上的准确率为: 20 %
  15. 1/ 1 轮循环, 938/ 938 组,误差为:2.2794
  16. 开始第 2次测试===================================================
  17. 2轮训练集上的准确率为: 47 % 测试集上的准确率为: 47 %
  18. 1/ 1 轮循环, 938/ 938 组,误差为:2.0767
  19. 开始第 3次测试===================================================
  20. 3轮训练集上的准确率为: 65 % 测试集上的准确率为: 66 %
  21. 1/ 1 轮循环, 938/ 938 组,误差为:0.7186
  22. 开始第 4次测试===================================================
  23. 4轮训练集上的准确率为: 87 % 测试集上的准确率为: 88 %
  24. 1/ 1 轮循环, 938/ 938 组,误差为:0.3513
  25. 开始第 5次测试===================================================
  26. 5轮训练集上的准确率为: 91 % 测试集上的准确率为: 91 %
  27. 1/ 1 轮循环, 938/ 938 组,误差为:0.2641
  28. 开始第 6次测试===================================================
  29. 6轮训练集上的准确率为: 92 % 测试集上的准确率为: 93 %
  30. 1/ 1 轮循环, 938/ 938 组,误差为:0.2144
  31. 开始第 7次测试===================================================
  32. 7轮训练集上的准确率为: 93 % 测试集上的准确率为: 94 %
  33. 1/ 1 轮循环, 938/ 938 组,误差为:0.1807
  34. 开始第 8次测试===================================================
  35. 8轮训练集上的准确率为: 94 % 测试集上的准确率为: 95 %
  36. 1/ 1 轮循环, 938/ 938 组,误差为:0.1568
  37. 开始第 9次测试===================================================
  38. 9轮训练集上的准确率为: 95 % 测试集上的准确率为: 95 %
  39. 1/ 1 轮循环, 938/ 938 组,误差为:0.1393
  40. 开始第10次测试===================================================
  41. 10轮训练集上的准确率为: 96 % 测试集上的准确率为: 96 %
  42. 1/ 1 轮循环, 938/ 938 组,误差为:0.1262
  43. 开始第11次测试===================================================
  44. 11轮训练集上的准确率为: 96 % 测试集上的准确率为: 96 %
  45. 1/ 1 轮循环, 938/ 938 组,误差为:0.1163
  46. 开始第12次测试===================================================
  47. 12轮训练集上的准确率为: 96 % 测试集上的准确率为: 96 %
  48. 1/ 1 轮循环, 938/ 938 组,误差为:0.1080
  49. 开始第13次测试===================================================
  50. 13轮训练集上的准确率为: 97 % 测试集上的准确率为: 97 %
  51. 1/ 1 轮循环, 938/ 938 组,误差为:0.1011
  52. 开始第14次测试===================================================
  53. 14轮训练集上的准确率为: 96 % 测试集上的准确率为: 96 %
  54. 1/ 1 轮循环, 938/ 938 组,误差为:0.0954
  55. 开始第15次测试===================================================
  56. 15轮训练集上的准确率为: 97 % 测试集上的准确率为: 97 %
  57. 1/ 1 轮循环, 938/ 938 组,误差为:0.0903
  58. 开始第16次测试===================================================
  59. 16轮训练集上的准确率为: 97 % 测试集上的准确率为: 97 %
  60. 1/ 1 轮循环, 938/ 938 组,误差为:0.0862
  61. 开始第17次测试===================================================
  62. 17轮训练集上的准确率为: 97 % 测试集上的准确率为: 97 %
  63. 1/ 1 轮循环, 938/ 938 组,误差为:0.0821
  64. 开始第18次测试===================================================
  65. 18轮训练集上的准确率为: 97 % 测试集上的准确率为: 97 %
  66. 1/ 1 轮循环, 938/ 938 组,误差为:0.0789
  67. 开始第19次测试===================================================
  68. 19轮训练集上的准确率为: 97 % 测试集上的准确率为: 97 %
  69. 1/ 1 轮循环, 938/ 938 组,误差为:0.0757
  70. 开始第20次测试===================================================
  71. 20轮训练集上的准确率为: 97 % 测试集上的准确率为: 97 %
  72. 模型已训练完成,是否保存已训练模型(Y\N):
  73. N
  74. 未保存已训练模型
  75. 实际标签: tensor([7, 2, 1, 0, 4, 1, 4, 9, 5, 9, 0, 6, 9, 0, 1, 5, 9, 7, 3, 4, 9, 6, 6, 5,
  76. 4, 0, 7, 4, 0, 1, 3, 1, 3, 4, 7, 2, 7, 1, 2, 1, 1, 7, 4, 2, 3, 5, 1, 2,
  77. 4, 4, 6, 3, 5, 5, 6, 0, 4, 1, 9, 5, 7, 8, 9, 3])
  78. 预测结果: tensor([7, 2, 1, 0, 4, 1, 4, 9, 5, 9, 0, 6, 9, 0, 1, 5, 9, 7, 3, 4, 9, 6, 6, 5,
  79. 4, 0, 7, 4, 0, 1, 3, 1, 3, 4, 7, 2, 7, 1, 2, 1, 1, 7, 4, 2, 3, 5, 1, 2,
  80. 4, 4, 6, 3, 5, 5, 6, 0, 4, 1, 9, 5, 7, 8, 9, 3], device='cuda:0')

 

 

 

 基本上15轮就能97%了

训练时间不长,这里就不放保存的模型文件了。

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/509487
推荐阅读
相关标签
  

闽ICP备14008679号