当前位置:   article > 正文

在pytorch上使用LSTM实现猫狗分类_lstm分类用什么损失函数

lstm分类用什么损失函数

    与RNN一样,输入也是三个维度,由于之前RNN先使用了CNN进行过滤,这次LSTM模型不使用CNN过滤,直接把所有向量放入训练。如下图,没有和RNN一样使用三层卷积层。

定义超参数

BATCH_SIZE = 32  # 每批处理的数据

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

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

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

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

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

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

       LSTM模型准确度方面表现正常,但是loss太过抖动,需要调参数。比如学习率,loss函数,batch_size,激活函数,优化算法等。

  1. #!/usr/bin/env python
  2. # -#-coding:utf-8 -*-
  3. # author: vv
  4. # datetime:2021/10/17 21:35:59
  5. # software:PyCharm
  6. """
  7. 模型1:Pytorch LSTM 实现流程
  8. 1.图片数据处理,加载数据集
  9. 2.使得数据集可迭代(每次读取一个Batch)
  10. 3.创建模型类
  11. 4.初始化模型类
  12. 5.初始化损失类
  13. 6.训练模型
  14. """
  15. # 1.加载库
  16. import os
  17. import numpy as np
  18. import torch
  19. import torch.nn as nn
  20. import torch.nn.functional as F
  21. import torch.optim as optim
  22. import torchvision
  23. from torch.utils.data import DataLoader
  24. from torchvision import datasets, transforms
  25. import matplotlib.pyplot as plt
  26. # 2.定义超参数
  27. BATCH_SIZE = 32 # 每批处理的数据
  28. DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # 放在cuda或者cpu上训练
  29. EPOCHS = 15 # 训练数据集的轮次
  30. # 3.构建pipeline,对图像做处理
  31. pipeline = transforms.Compose([
  32. # 彩色图像转灰度图像num_output_channels默认1
  33. # transforms.Grayscale(num_output_channels=1),
  34. # 分辨率重置为256
  35. transforms.Resize(256),
  36. # 对加载的图像作归一化处理, 并裁剪为[224x224x3]大小的图像(因为这图片像素不一致直接统一)
  37. transforms.CenterCrop(224),
  38. # 将图片转成tensor
  39. transforms.ToTensor(),
  40. # 正则化,模型出现过拟合现象时,降低模型复杂度
  41. transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
  42. ])
  43. # 图片路径(训练图片和测试图片的)
  44. base_dir_train = 'data/train'
  45. base_dir_test = 'data/val'
  46. # 打印一下训练图片猫狗各多少张图片
  47. print('train dogs total images : %d' % (len(os.listdir(base_dir_train + '\\dog'))))
  48. print('train cats total images : %d' % (len(os.listdir(base_dir_train + '\\cat'))))
  49. print('test cats total images : %d' % (len(os.listdir(base_dir_test + '\\cat'))))
  50. print('test dogs total images : %d' % (len(os.listdir(base_dir_test + '\\dog'))))
  51. # 4. 加载数据集
  52. """
  53. 训练集,猫是0,狗是1,ImageFolder方法自己分类的,关于ImageFolder详见:
  54. 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
  55. """
  56. train_dataset = datasets.ImageFolder(root=base_dir_train, transform=pipeline)
  57. print("train_dataset=" + repr(train_dataset[1][0].size()))
  58. print("train_dataset.class_to_idx=" + repr(train_dataset.class_to_idx))
  59. # 创建训练集的可迭代对象,一个batch_size地读取数据,shuffle设为True表示随机打乱顺序读取
  60. train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)
  61. # 测试集
  62. test_dataset = datasets.ImageFolder(root=base_dir_test, transform=pipeline)
  63. # print(test_dataset)
  64. print("test_dataset=" + repr(test_dataset[1][0].size()))
  65. print("test_dataset.class_to_idx=" + repr(test_dataset.class_to_idx))
  66. # 创建测试集的可迭代对象,一个batch_size地读取数据
  67. test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=True)
  68. # 获得一批测试集的数据
  69. images, labels = next(iter(test_loader))
  70. print("images shape", images.shape)
  71. print("labels shape", labels.shape)
  72. # 5.定义函数,显示一批图片
  73. def imShow(inp, title=None):
  74. # tensor转成numpy,transpose转成(通道数,长,宽)
  75. inp = inp.numpy().transpose((1, 2, 0))
  76. mean = np.array([0.485, 0.456, 0.406]) # 均值
  77. std = np.array([0.229, 0.224, 0.225]) # 标准差
  78. inp = std * inp + mean
  79. inp = np.clip(inp, 0, 1) # 像素值限制在0-1之间
  80. plt.imshow(inp)
  81. if title is not None:
  82. plt.title(title)
  83. plt.pause(0.001)
  84. # 网格显示
  85. out = torchvision.utils.make_grid(images)
  86. imShow(out)
  87. # 6.定义LSTM网络
  88. class LSTM_Model(nn.Module):
  89. def __init__(self, input_dim, hidden_dim, layer_dim, output_dim):
  90. super(LSTM_Model, self).__init__() # 初始化父类构造方法
  91. self.hidden_dim = hidden_dim
  92. self.layer_dim = layer_dim
  93. # 构建LSTM模型
  94. self.lstm = nn.LSTM(input_dim, hidden_dim, layer_dim, batch_first=True)
  95. # 全连接层
  96. self.fc = nn.Linear(hidden_dim, output_dim)
  97. def forward(self, x):
  98. # 初始化隐藏层状态全为0
  99. # (layer_dim,batch_size,hidden_dim)
  100. h0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).requires_grad_().to(DEVICE)
  101. # 初始化cell state
  102. c0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).requires_grad_().to(DEVICE)
  103. x = x.view(x.size(0), 1, -1)
  104. # 分离隐藏状态 避免梯度爆炸
  105. '''
  106. RNN只有一个状态,而LSTM有两个状态,所以两个状态都要分离
  107. '''
  108. out, (hn, cn) = self.lstm(x, (h0.detach(), c0.detach()))
  109. # 只需要最后一层隐层的状态
  110. out = self.fc(out[:, -1, :])
  111. return out
  112. # 7.初始化模型
  113. input_dim = 150528 # 输入维度(输入的节点数量)
  114. hidden_dim = 50 # 隐藏层的维度(每个隐藏层的节点数)
  115. layer_dim = 2 # 2层LSTM(隐藏层的数量 2层)
  116. out_dim = 2 # 输出维度
  117. rnn_model = LSTM_Model(input_dim, hidden_dim, layer_dim, out_dim)
  118. # 8.输出模型参数信息
  119. length = len(list(rnn_model.parameters()))
  120. print(length)
  121. # 9.输出模型参数信息
  122. length = len(list(rnn_model.parameters()))
  123. print(length)
  124. # 优化器
  125. # optimizer = optim.SGD(rnn_model.parameters(), lr=1e-3, momentum=0.9)
  126. optimizer = optim.Adam(rnn_model.parameters(), lr=1e-3, betas=(0.9, 0.99))
  127. # 损失函数,交叉熵损失函数
  128. criterion = nn.CrossEntropyLoss()
  129. # 把损失,准确度,迭代都记录出list,然后讲loss和准确度画出图像
  130. sequence_dim = 53
  131. train_loss_list = []
  132. train_accuracy_list = []
  133. train_iteration_list = []
  134. test_loss_list = []
  135. test_accuracy_list = []
  136. test_iteration_list = []
  137. iteration = 0
  138. # for i, (imgs, labels) in enumerate(test_loader):
  139. # # print("imgs=" + repr(imgs))
  140. # print("labels=" + repr(labels))
  141. # print("i=" + repr(i))
  142. # 训练
  143. # """
  144. for epoch in range(EPOCHS):
  145. # 用来显示训练的loss correct等
  146. train_correct = 0.0
  147. train_total = 0.0
  148. for i, (imgs, labels) in enumerate(train_loader):
  149. # 声明训练,loss等只能在train mode下进行运算
  150. rnn_model.train()
  151. # 把训练的数据集合都扔到对应的设备去
  152. # imgs = imgs.view(-1,1,sequence_dim, input_dim).requires_grad_().to(DEVICE)
  153. # print("imgs shape", imgs.shape)
  154. # print("imgs = ", imgs.data)
  155. imgs = imgs.to(DEVICE)
  156. labels = labels.to(DEVICE)
  157. # 防止梯度爆炸,梯度清零
  158. optimizer.zero_grad()
  159. # 前向传播
  160. rnn_model = rnn_model.cuda() # 这里要从cuda()中取得,不然前面都放在cuda后面放在cpu,会报错,报“不在同一个设备的错误" Input and parameter tensors are not at the same device, found input tensor at cuda:0 and parameter tensor at cpu
  161. output = rnn_model(imgs)
  162. # print("RNN output shape", out.shape)
  163. # print("label shape", labels.shape)
  164. # 计算损失
  165. loss = criterion(output, labels)
  166. # 反向传播
  167. loss.backward()
  168. # 更新参数
  169. optimizer.step()
  170. # 计算训练时候的准确度
  171. train_predict = torch.max(output.data, 1)[1]
  172. if torch.cuda.is_available():
  173. train_correct += (train_predict.cuda() == labels.cuda()).sum()
  174. else:
  175. train_correct += (train_predict == labels).sum()
  176. train_total += labels.size(0)
  177. accuracy = train_correct / train_total * 100.0
  178. # 只画出最后一次epoch的
  179. if (epoch + 1) == EPOCHS:
  180. # 迭代计数器++
  181. iteration += 1
  182. train_accuracy_list.append(accuracy)
  183. train_iteration_list.append(iteration)
  184. train_loss_list.append(loss)
  185. # 打印信息
  186. print("Epoch :%d , Batch : %5d , Loss : %.8f,train_correct:%d,train_total:%d,accuracy:%.6f" % (
  187. epoch + 1, i + 1, loss.item(), train_correct, train_total, accuracy))
  188. print("==========================预测开始===========================")
  189. rnn_model.eval()
  190. # 验证accuracy
  191. correct = 0.0
  192. total = 0.0
  193. # 迭代测试集 获取数据 预测
  194. for j, (datas, targets) in enumerate(test_loader):
  195. datas = datas.to(DEVICE)
  196. targets = targets.to(DEVICE)
  197. # datas = datas.view(-1, sequence_dim, input_dim).requires_grad_().to(DEVICE)
  198. # datas = datas.reshape(datas.size(0), 1, -1)
  199. # 模型预测
  200. outputs = rnn_model(datas)
  201. # 防止梯度爆炸,梯度清零
  202. optimizer.zero_grad()
  203. # 获取测试概率最大值的下标
  204. predicted = torch.max(outputs.data, 1)[1]
  205. # 统计计算测试集合
  206. total += targets.size(0)
  207. if torch.cuda.is_available():
  208. # print(predicted.cuda() == targets.cuda())
  209. correct += (predicted.cuda() == targets.cuda()).sum()
  210. # print("predicted.cuda()=" + repr(predicted.cuda()))
  211. # print("labels.cuda()=" + repr(targets.cuda()))
  212. else:
  213. correct += (predicted == targets).sum()
  214. accuracy = correct / total * 100.0
  215. test_accuracy_list.append(accuracy)
  216. test_loss_list.append(loss.item())
  217. test_iteration_list.append(iteration)
  218. print("TEST--->loop : {}, Loss : {}, correct:{}, total:{}, Accuracy : {}".format(iteration, loss.item(),
  219. correct,
  220. total, accuracy))
  221. # 可视化训练集loss
  222. plt.figure(1)
  223. plt.plot(train_iteration_list, train_loss_list)
  224. plt.xlabel("number of iteration")
  225. plt.ylabel("loss")
  226. plt.title("RNN train loss")
  227. plt.show()
  228. # 可视化训练集accuracy
  229. plt.figure(2)
  230. plt.plot(train_iteration_list, train_accuracy_list)
  231. plt.xlabel('number of iteration')
  232. plt.ylabel('accuracy')
  233. plt.title('LSTM train accuracy')
  234. plt.show()
  235. # 可视化测试集loss
  236. plt.figure(3)
  237. plt.plot(test_iteration_list, test_loss_list)
  238. plt.xlabel('number of iteration')
  239. plt.ylabel('loss')
  240. plt.title('LSTM test loss')
  241. plt.show()
  242. # 可视化测试集accuracy
  243. plt.figure(4)
  244. plt.plot(test_iteration_list, test_accuracy_list)
  245. plt.xlabel('number of iteration')
  246. plt.ylabel('accuracy')
  247. plt.title('LSTM test accuracy')
  248. plt.show()

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

闽ICP备14008679号