当前位置:   article > 正文

在pytorch中使用ResNet50实现猫狗分类_pytorch 用预训练的resnet50做猫分类

pytorch 用预训练的resnet50做猫分类

        前面的自己设计的模型出现了过拟合现象,训练集准确度高达95%,但是测试集准确度惨不忍睹63%左右。

       使用交叉熵作为loss,模型采用resnet50,使用预训练模型,我在调试的过程中,使用预训练模型可以快速得到收敛好的模型,使用预训练模型将pretrained设置为True即可。更改最后一层的全连接,将类别设置为2,然后将模型放到DEVICE。优化器选用Adam。

代码有详细的注释就不说过程了。没有出现过拟合现象,受限于我的机器就没有设置更低的学习率,跑的结果还行。

       超参数:

        BATCH_SIZE = 16  # 每批处理的数据

        DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

        EPOCHS = 15  # 训练数据集的轮次

        modellr = 1e-3  # 学习率

  1. 最后一个epoch(第15个epoch)时候的训练集的损失率

2. 最后一个epoch时候的训练准确率 

3. 总共15个epoch,每次epoch之后都测试一次,得到15次的loss 

4. 每次训练完epoch之后在测试集的准确度 

  1. #!/usr/bin/env python
  2. # -#-coding:utf-8 -*-
  3. # author: vv
  4. # datetime:2021/10/18 11:05:52
  5. # software:PyCharm
  6. # 1.加载库
  7. import os
  8. import numpy as np
  9. import torch
  10. import torch.nn as nn
  11. import torch.nn.functional as F
  12. import torch.optim as optim
  13. import torchvision
  14. from torch.autograd.variable import Variable
  15. from torch.utils.data import DataLoader
  16. from torchvision import datasets, transforms
  17. import matplotlib.pyplot as plt
  18. # 2.定义超参数
  19. BATCH_SIZE = 16 # 每批处理的数据
  20. DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 放在cuda或者cpu上训练
  21. EPOCHS = 15 # 训练数据集的轮次
  22. modellr = 1e-3
  23. # 3.构建pipeline,对图像做处理
  24. pipeline = transforms.Compose([
  25. # 分辨率重置为256
  26. transforms.Resize(256),
  27. # 对加载的图像作归一化处理, 并裁剪为[224x224x3]大小的图像(因为这图片像素不一致直接统一)
  28. transforms.CenterCrop(224),
  29. # 将图片转成tensor
  30. transforms.ToTensor(),
  31. # 正则化,模型出现过拟合现象时,降低模型复杂度
  32. transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
  33. ])
  34. # 图片路径(训练图片和测试图片的)
  35. base_dir_train = 'data/train'
  36. base_dir_test = 'data/val'
  37. # 打印一下训练图片猫狗各多少张图片
  38. print('train dogs total images : %d' % (len(os.listdir(base_dir_train + '\\dog'))))
  39. print('train cats total images : %d' % (len(os.listdir(base_dir_train + '\\cat'))))
  40. print('test cats total images : %d' % (len(os.listdir(base_dir_test + '\\cat'))))
  41. print('test dogs total images : %d' % (len(os.listdir(base_dir_test + '\\dog'))))
  42. # 4. 加载数据集
  43. """
  44. 训练集,猫是0,狗是1,ImageFolder方法自己分类的,关于ImageFolder详见:
  45. https://blog.csdn.net/weixin_42147780/article/details/102683053?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link
  46. """
  47. train_dataset = datasets.ImageFolder(root=base_dir_train, transform=pipeline)
  48. print("train_dataset=" + repr(train_dataset[1][0].size()))
  49. print("train_dataset.class_to_idx=" + repr(train_dataset.class_to_idx))
  50. # 创建训练集的可迭代对象,一个batch_size地读取数据,shuffle设为True表示随机打乱顺序读取
  51. train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)
  52. # 测试集
  53. test_dataset = datasets.ImageFolder(root=base_dir_test, transform=pipeline)
  54. print(test_dataset)
  55. print("test_dataset=" + repr(test_dataset[1][0].size()))
  56. print("test_dataset.class_to_idx=" + repr(test_dataset.class_to_idx))
  57. # 创建测试集的可迭代对象,一个batch_size地读取数据
  58. test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=True)
  59. # 获得一批测试集的数据
  60. images, labels = next(iter(test_loader))
  61. print(images.shape)
  62. print(labels.shape)
  63. # 5.定义函数,显示一批图片
  64. def imShow(inp, title=None):
  65. # tensor转成numpy,tranpose转成(通道数,长,宽)
  66. inp = inp.numpy().transpose((1, 2, 0))
  67. mean = np.array([0.485, 0.456, 0.406]) # 均值
  68. std = np.array([0.229, 0.224, 0.225]) # 标准差
  69. inp = std * inp + mean
  70. inp = np.clip(inp, 0, 1) # 像素值限制在0-1之间
  71. plt.imshow(inp)
  72. if title is not None:
  73. plt.title(title)
  74. plt.pause(0.001)
  75. # 网格显示
  76. out = torchvision.utils.make_grid(images)
  77. imShow(out)
  78. # 损失函数,交叉熵损失函数
  79. criterion = nn.CrossEntropyLoss()
  80. # 使用预训练模型
  81. resnet_model = torchvision.models.resnet50(pretrained=True)
  82. num_ftrs = resnet_model.fc.in_features
  83. resnet_model.fc = nn.Linear(num_ftrs, 2)
  84. resnet_model.to(DEVICE)
  85. # 选择简单暴力的Adam优化器,学习率调低
  86. optimizer = optim.Adam(resnet_model.parameters(), lr=modellr)
  87. # 更新学习率的方法
  88. def adjust_learning_rate(optimizer, epoch):
  89. """Sets the learning rate to the initial LR decayed by 10 every 30 epochs"""
  90. modellrnew = modellr * (0.1 ** (epoch // 50))
  91. print("lr:", modellrnew)
  92. for param_group in optimizer.param_groups:
  93. param_group['lr'] = modellrnew
  94. train_loss_list = []
  95. train_accuracy_list = []
  96. test_loss_list = []
  97. test_accuracy_list = []
  98. train_iteration_list = []
  99. test_iteration_list = []
  100. # 定义训练方法
  101. def train(model, device, train_loader, optimizer, epoch):
  102. iteration = 0
  103. train_correct = 0.0
  104. model.train()
  105. sum_loss = 0.0
  106. total_num = len(train_loader.dataset)
  107. print(total_num, len(train_loader))
  108. for batch_idx, (data, target) in enumerate(train_loader):
  109. data, target = Variable(data).to(device), Variable(target).to(device)
  110. output = model(data)
  111. loss = criterion(output, target)
  112. optimizer.zero_grad()
  113. loss.backward()
  114. optimizer.step()
  115. print_loss = loss.data.item()
  116. sum_loss += print_loss
  117. train_predict = torch.max(output.data, 1)[1]
  118. if torch.cuda.is_available():
  119. train_correct += (train_predict.cuda() == target.cuda()).sum()
  120. else:
  121. train_correct += (train_predict == target).sum()
  122. accuracy = (train_correct / total_num) * 100
  123. print("Epoch: %d , Batch: %3d , Loss : %.8f,train_correct:%d , train_total:%d , accuracy:%.6f" % (
  124. epoch + 1, batch_idx + 1, loss.item(), train_correct, total_num, accuracy))
  125. # 存在集合画图
  126. if (epoch + 1) == EPOCHS: # 只画出最后一个epoch时候的准确度变化曲线
  127. iteration += 1
  128. train_loss_list.append(loss.item())
  129. train_iteration_list.append(iteration)
  130. train_accuracy_list.append(accuracy)
  131. # 定义验证方法
  132. def val(model, device, test_loader, epoch):
  133. print("=====================预测开始=================================")
  134. iteration = 0
  135. model.eval()
  136. test_loss = 0.0
  137. correct = 0.0
  138. total_num = len(test_loader.dataset)
  139. print(total_num, len(test_loader))
  140. with torch.no_grad():
  141. for data, target in test_loader:
  142. data, target = Variable(data).to(device), Variable(target).to(device)
  143. output = model(data)
  144. loss = criterion(output, target)
  145. _, pred = torch.max(output.data, 1)
  146. if torch.cuda.is_available():
  147. correct += torch.sum(pred.cuda() == target.cuda())
  148. else:
  149. correct += torch.sum(pred == target)
  150. print_loss = loss.data.item()
  151. test_loss += print_loss
  152. acc = correct / total_num * 100
  153. avg_loss = test_loss / len(test_loader)
  154. """
  155. 因为调用这个方法的时候就是每次结束训练一次之后调用
  156. """
  157. # iteration += 1
  158. # 存入集合准备画图
  159. test_loss_list.append(avg_loss)
  160. test_accuracy_list.append(acc)
  161. test_iteration_list.append(epoch)
  162. print('\nVal set: Average loss: {:.4f}, Accuracy: {}/{} ({:.6f}%)\n'.format(
  163. avg_loss, correct, len(test_loader.dataset), acc))
  164. # 训练
  165. for epoch in range(EPOCHS):
  166. train(resnet_model, DEVICE, train_loader, optimizer, epoch)
  167. val(resnet_model, DEVICE, test_loader, epoch)
  168. # torch.save(resnet_model, 'model.pth') # 保存模型
  169. # 可视化测试机的loss和accuracy
  170. plt.figure(1)
  171. plt.plot(test_iteration_list, test_loss_list)
  172. plt.title("ResNet50 test loss")
  173. plt.ylabel("loss")
  174. plt.xlabel("Number of test iteration")
  175. plt.show()
  176. plt.figure(2)
  177. plt.plot(test_iteration_list, test_accuracy_list)
  178. plt.title("ResNet50 test accuracy")
  179. plt.xlabel("Number of test iteration")
  180. plt.ylabel("accuracy")
  181. plt.show()
  182. # 可视化训练集loss和accuracy
  183. plt.figure(3)
  184. plt.plot(train_iteration_list, train_loss_list)
  185. plt.title("ResNet50 train loss")
  186. plt.xlabel("Number of train iteration")
  187. plt.ylabel("accuracy")
  188. plt.show()
  189. plt.figure(4)
  190. plt.plot(train_iteration_list, train_accuracy_list)
  191. plt.title("ResNet50 train accuracy")
  192. plt.xlabel("Number of train iteration")
  193. plt.ylabel("accuracy")
  194. plt.show()

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

闽ICP备14008679号