train.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. from model import LeNet5 # 引入我们写好的神经网络(也是我们要训练的网络)
  2. from torch.nn import CrossEntropyLoss # 引入损失函数(用来做分类损失最佳)
  3. from torch.optim import Adam # 损失函数优化器(其他损失函数的最小值:使用梯度下降法)
  4. from torchvision.datasets import MNIST # 数据集
  5. from torchvision.transforms import Compose, ToTensor # 图像转换为张量
  6. from torch.utils.data import DataLoader # 批次数据集(数据集不是一次训练,而是分成多个批次)
  7. import torch # 调用torch的基本函数
  8. import os # 路径与文件处理
  9. class Trainer:
  10. def __init__(self):
  11. # 判定电脑安装GPU的环境:cuda,cnn,pytorch-
  12. self.CUDA = False # torch.cuda.is_available() # 返回逻辑值:True:支持GPU,False不支持GPU
  13. # 准备训练需要的数据、损失函数,优化器,学习率
  14. self.lr = 0.0001
  15. self.m_file = "lenet5.pt" # 模型的保存文件
  16. self.net = LeNet5() # 需要训练的网络
  17. if self.CUDA:
  18. self.net.cuda() # 把net网络模型存储到GPU上面
  19. # 加载上一次训练的模型
  20. if os.path.exists(self.m_file):
  21. # 存在就加载
  22. print("加载模型中...")
  23. state = torch.load(self.m_file) # 读取文件
  24. self.net.load_state_dict(state)
  25. else:
  26. print("模型存在,重头训练")
  27. self.loss_f = CrossEntropyLoss() # 损失函数
  28. self.optimizer = Adam(self.net.parameters(), lr=self.lr) # 优化器
  29. # 数据集 - 训练集
  30. self.trans = Compose([ToTensor()])
  31. self.ds_train = MNIST(root="datasets", download=True, train=True, transform=self.trans)
  32. self.bt_train = DataLoader(self.ds_train, batch_size=1000, shuffle=True)
  33. # 数据集 - 验证集
  34. self.ds_valid = MNIST(root="datasets", download=True, train=False, transform=self.trans)
  35. self.bt_valid = DataLoader(self.ds_valid, batch_size=1000, shuffle=False) # shuffle=False是否随机打乱
  36. def train_one(self):
  37. # 训练一轮epoch,60批次batch,每个批次1000张录像
  38. # 循环训练每个批次
  39. batch = 1
  40. for x, y in self.bt_train:
  41. # print(F"\t|-第{batch:02d}批次训练。")
  42. if self.CUDA:
  43. x = x.cuda()
  44. y = y.cuda()
  45. y_ = self.net(x) # 进行预测
  46. # 计算误差
  47. loss = self.loss_f(y_, y) # 使用真实的标签与预测标签计算sunshi
  48. # 优化卷积核与全链接矩阵
  49. self.optimizer.zero_grad()
  50. loss.backward() # 使用导数计算梯度
  51. self.optimizer.step() # 更新梯度,优化网络模型
  52. batch+=1
  53. @torch.no_grad() # 该函数中的运算都不会进行求导跟踪
  54. def valid(self):
  55. # 使用测试数据集验证 (准确率,损失值)
  56. all_num = 0.0 # 验证的样本数
  57. acc_num = 0.0 # 识别正确数量
  58. all_loss = 0.0 # 累加每个样本的损失
  59. for t_x, t_y in self.bt_valid:
  60. if self.CUDA:
  61. t_x = t_x.cuda()
  62. t_y = t_y.cuda()
  63. # 统计样本数
  64. all_num += len(t_x)
  65. # 预测
  66. t_y_ = self.net(t_x)
  67. # 判定准确
  68. y_cls = torch.argmax(t_y_, dim=1)
  69. # 统计正确率
  70. acc_num += (y_cls == t_y).float().sum()
  71. # 统计损失
  72. all_loss += self.loss_f(t_y_, t_y)
  73. print(F"\t|- 训练损失:{all_loss/all_num:8.6f}")
  74. print(F"\t|- 准确率:{acc_num * 100.0/all_num:5.2f}%")
  75. def train(self, epoch):
  76. # 训练指定的论数
  77. for e in range(epoch):
  78. print(F"第{e:04d}轮训练。")
  79. self.train_one()
  80. self.valid()
  81. # 保存训练的模型
  82. torch.save(self.net.state_dict(), self.m_file)
  83. if __name__ == "__main__":
  84. trainer = Trainer()
  85. trainer.train(50) # 训练10轮
  86. # print(torch.cuda.is_available())
  87. """
  88. 244K = 6 * 5 * 5 * 8 矩阵
  89. 16 * 5 * 5 * 8
  90. 120 * 5 * 5 * 8
  91. 120 * 84* 8
  92. 84 * 10*8
  93. """