当前位置:   article > 正文

深度学习模型:Pytorch搭建ResNet、DenseNet网络,完成一维数据分类任务_class resnet(torch.nn.module): def __init__(self,i

class resnet(torch.nn.module): def __init__(self,in_channels=1, classes=2):

2023.7.17

DenseNet和ResNet都是深度学习中常用的网络结构,它们各有优缺点。

DenseNet的优点是可以充分利用网络中的信息,因为每个层都可以接收来自前面所有层的信息。这种密集连接的结构可以提高网络的准确性,减少过拟合的风险。此外,DenseNet的参数量比ResNet少,训练速度更快。

ResNet的优点是可以解决深度网络中的梯度消失问题,使得网络可以更深更复杂。ResNet的残差结构可以让信息直接从前面的层传递到后面的层,避免了信息的丢失,提高了网络的准确性。此外,ResNet的结构简单,易于理解和实现。

DenseNet和ResNet的缺点也有所不同。DenseNet的缺点是需要更多的内存和计算资源,因为每个层都需要接收来自前面所有层的信息。此外,DenseNet的结构较为复杂,不易于理解和实现。

ResNet的缺点是在某些情况下可能会出现过拟合的问题,因为残差结构可以让信息直接从前面的层传递到后面的层,可能会导致网络过于复杂,难以泛化。

一、数据集的处理:

训练集、验证集、测试集的划分:

数据会被整理为.txt:(例如形成的trian.txt)

                最后会分割为trian_data.txt和train_labels.txt两个文件 

  1. import os
  2. import numpy as np
  3. import random
  4. import math
  5. def normalization(data): # 归一化:均值0,方差1
  6. data = (data - data.mean()) / data.std()
  7. return data
  8. def random_rowl(data): # 把行的顺序随机排列
  9. idx = np.arange(data.shape[0])
  10. np.random.shuffle(idx)
  11. data = data[idx[0:]]
  12. return data
  13. def getfilelist(path): # 读取文件夹下所有txt文件
  14. filelist = []
  15. for filename in os.listdir(path):
  16. if os.path.splitext(filename)[1] == '.txt':
  17. filelist.append(filename)
  18. random.shuffle(filelist) # 随机打乱文件列表里的顺序
  19. return filelist
  20. path = '第一类数据的文件夹子路径','第二类数据的文件夹子路径','第三类数据的文件夹子路径'
  21. sort_num = 3 # 一共多少类?
  22. for i in range(sort_num): # 个数修改为路径的数目,与文件夹个数相同
  23. fileName = "{}/".format(path[i])
  24. files = getfilelist(fileName)
  25. # files=getfilelist(path[i]+'/')
  26. a = len(files)
  27. print(path[i], a)
  28. data = np.loadtxt(fileName + files[0])[:, 1]
  29. data = normalization(data)
  30. for j in range(1, a):
  31. data1 = np.loadtxt(fileName + '/' + files[j])[:, 1]
  32. data1 = normalization(data1)
  33. data = np.c_[data, data1]
  34. data = data.T
  35. # 加标签
  36. label = np.zeros((len(data), sort_num)) # 标签也改为分类的数目,与文件夹个数相同
  37. for m in range(len(label)):
  38. label[m, i] = 1
  39. data = np.c_[data, label]
  40. data = random_rowl(data)
  41. t = math.floor(len(data) * 0.7)
  42. v = math.floor(len(data) * 0.2)
  43. train = data[:t, :]
  44. val = data[t:(t + v), :]
  45. test = data[(t + v):, :]
  46. np.savetxt(path[i] + '_train.txt', train, fmt='%.6f')
  47. np.savetxt(path[i] + '_val.txt', val, fmt='%.6f')
  48. np.savetxt(path[i] + '_test.txt', test, fmt='%.6f')
  49. train = np.loadtxt(path[0] + '_train.txt')
  50. val = np.loadtxt(path[0] + '_val.txt')
  51. test = np.loadtxt(path[0] + '_test.txt')
  52. for i in range(1, sort_num): # 需要修改为与分类个数相同,最后一个数与文件夹
  53. train1 = np.loadtxt(path[i] + '_train.txt')
  54. val1 = np.loadtxt(path[i] + '_val.txt')
  55. test1 = np.loadtxt(path[i] + '_test.txt')
  56. train = random_rowl(np.r_[train, train1])
  57. val = random_rowl(np.r_[val, val1])
  58. test = random_rowl(np.r_[test, test1])
  59. np.savetxt('train.txt', train, fmt='%.6f') # 划分训练集
  60. np.savetxt('val.txt', val, fmt='%.6f') # 划分验证集
  61. np.savetxt('test.txt', test, fmt='%.6f') # 划分测试集
  62. # 从train.txt、val.txt、test.txt中分别获取数据和标签
  63. class_num = sort_num # 分类的类数
  64. train_labels = np.loadtxt('./train.txt')[:, -class_num:]
  65. test_labels = np.loadtxt('./test.txt')[:, -class_num:]
  66. val_labels = np.loadtxt('./val.txt')[:, -class_num:]
  67. train_data = np.loadtxt('./train.txt')[:, :-class_num]
  68. test_data = np.loadtxt('./test.txt')[:, :-class_num]
  69. val_data = np.loadtxt('./val.txt')[:, :-class_num]
  70. np.savetxt('train_data.txt', train_data, fmt='%.6f')
  71. np.savetxt('val_data.txt', val_data, fmt='%.6f')
  72. np.savetxt('test_data.txt', test_data, fmt='%.6f')
  73. np.savetxt('train_labels.txt', train_labels, fmt='%d')
  74. np.savetxt('val_labels.txt', val_labels, fmt='%d')
  75. np.savetxt('test_labels.txt', test_labels, fmt='%d')

二、数据的训练:

ResNet:

  1. import numpy as np
  2. import torch.optim as optim
  3. import torch.nn as nn
  4. import torch
  5. from torch.utils.data import DataLoader, Dataset
  6. class Bottlrneck(torch.nn.Module):
  7. def __init__(self, In_channel, Med_channel, Out_channel, downsample=False):
  8. super(Bottlrneck, self).__init__()
  9. self.stride = 1
  10. if downsample == True:
  11. self.stride = 2
  12. self.layer = torch.nn.Sequential(
  13. torch.nn.Conv1d(In_channel, Med_channel, 1, self.stride),
  14. torch.nn.BatchNorm1d(Med_channel),
  15. torch.nn.ReLU(),
  16. torch.nn.Conv1d(Med_channel, Med_channel, 3, padding=1),
  17. torch.nn.BatchNorm1d(Med_channel),
  18. torch.nn.ReLU(),
  19. torch.nn.Conv1d(Med_channel, Out_channel, 1),
  20. torch.nn.BatchNorm1d(Out_channel),
  21. torch.nn.ReLU(),
  22. )
  23. if In_channel != Out_channel:
  24. self.res_layer = torch.nn.Conv1d(In_channel, Out_channel, 1, self.stride)
  25. else:
  26. self.res_layer = None
  27. def forward(self, x):
  28. if self.res_layer is not None:
  29. residual = self.res_layer(x)
  30. else:
  31. residual = x
  32. return self.layer(x) + residual
  33. class ResNet(torch.nn.Module):
  34. def __init__(self, in_channels=2, classes=6):
  35. super(ResNet, self).__init__()
  36. self.features = torch.nn.Sequential(
  37. torch.nn.Conv1d(in_channels, 64, kernel_size=7, stride=2, padding=3),
  38. torch.nn.MaxPool1d(3, 2, 1),
  39. Bottlrneck(64, 64, 256, False),
  40. Bottlrneck(256, 64, 256, False),
  41. Bottlrneck(256, 64, 256, False),
  42. #
  43. Bottlrneck(256, 128, 512, True),
  44. Bottlrneck(512, 128, 512, False),
  45. Bottlrneck(512, 128, 512, False),
  46. Bottlrneck(512, 128, 512, False),
  47. #
  48. Bottlrneck(512, 256, 1024, True),
  49. Bottlrneck(1024, 256, 1024, False),
  50. Bottlrneck(1024, 256, 1024, False),
  51. Bottlrneck(1024, 256, 1024, False),
  52. Bottlrneck(1024, 256, 1024, False),
  53. Bottlrneck(1024, 256, 1024, False),
  54. #
  55. Bottlrneck(1024, 512, 2048, True),
  56. Bottlrneck(2048, 512, 2048, False),
  57. Bottlrneck(2048, 512, 2048, False),
  58. torch.nn.AdaptiveAvgPool1d(1)
  59. )
  60. self.classifer = torch.nn.Sequential(
  61. torch.nn.Linear(2048, classes)
  62. )
  63. def forward(self, x):
  64. x = torch.Tensor.view(x, (-1, 2, 511))
  65. x = self.features(x)
  66. x = x.view(-1, 2048)
  67. x = self.classifer(x)
  68. return x
  69. class MyDataset(Dataset):
  70. def __init__(self, raman_dir, label_file):
  71. self.raman_dir = np.loadtxt(raman_dir)
  72. self.label_file = np.loadtxt(label_file)
  73. self.raman_data = []
  74. self.label_list = []
  75. for index in self.raman_dir:
  76. self.raman_data.append(index)
  77. for index in self.label_file:
  78. self.label_list.append(index)
  79. def __getitem__(self, idx):
  80. raman = torch.Tensor(self.raman_data[idx])
  81. label = torch.Tensor(self.label_list[idx])
  82. label = np.argmax(label)
  83. return raman, label
  84. def __len__(self):
  85. # 获取数据集的长度
  86. return len(self.label_list)
  87. if __name__ == '__main__':
  88. # 准备数据集
  89. train_data = './train_data.txt'
  90. val_data = './val_data.txt'
  91. # 标签
  92. train_label = './train_labels.txt'
  93. val_label = './val_labels.txt'
  94. # 创建数据加载器
  95. batch_size = 128
  96. # 训练集输入
  97. train_dataset = MyDataset(train_data, train_label)
  98. train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
  99. # 测试集输入
  100. test_dataset = MyDataset(test_data, test_label)
  101. test_dataloader = DataLoader(test_dataset, batch_size=batch_size, shuffle=True)
  102. # 验证集输入
  103. val_dataset = MyDataset(val_data, val_label)
  104. val_dataloader = DataLoader(val_dataset, batch_size=batch_size, shuffle=True)
  105. train_data_size = len(train_dataset)
  106. val_data_size = len(val_dataset)
  107. # 创建网络模型
  108. class_num = 6
  109. test_data_length = 600
  110. ResNetOutput = ResNet(in_channels=2, classes=class_num).cuda()
  111. # 定义损失函数
  112. loss_fn = nn.CrossEntropyLoss().cuda()
  113. # 定义优化器
  114. learning_rate = 0.00001
  115. optimizer = optim.Adam(ResNetOutput.parameters(), lr=learning_rate)
  116. # 记录验证的次数
  117. total_train_step = 0
  118. total_val_step = 0
  119. # 训练
  120. epoch = 100
  121. acc_list = np.zeros(epoch)
  122. print("{0:-^27}".format('Train_Model'))
  123. for i in range(epoch):
  124. print("----------epoch={}----------".format(i + 1))
  125. ResNetOutput.train()
  126. for data in train_dataloader: # data 是batch大小
  127. raman_train_data, t_labels = data
  128. raman_train_data = raman_train_data.cuda()
  129. t_labels = t_labels.cuda()
  130. output = ResNetOutput(raman_train_data)
  131. loss = loss_fn(output, t_labels)
  132. # 优化器优化模型
  133. optimizer.zero_grad() # 梯度清零
  134. loss.backward() # 反向传播
  135. optimizer.step() # 优化更新参数
  136. total_train_step = total_train_step + 1
  137. print("train_times:{},Loss:{}".format(total_train_step, loss.item()))
  138. # 测试步骤开始
  139. ResNetOutput.eval()
  140. total_val_loss = 0
  141. total_accuracy = 0
  142. with torch.no_grad(): # 测试的时候不需要对梯度进行调整,所以梯度设置不调整
  143. for data in val_dataloader:
  144. raman_val_data, v_labels = data
  145. raman_val_data = raman_val_data.cuda()
  146. v_labels = v_labels.cuda()
  147. outputs = ResNetOutput(raman_val_data)
  148. loss = loss_fn(outputs, v_labels)
  149. total_val_loss = total_val_loss + loss.item() # 计算损失值的和
  150. accuracy = 0
  151. for j in v_labels:
  152. if outputs.argmax(1)[j] == v_labels[j]:
  153. accuracy = accuracy + 1
  154. # accuracy = (outputs.argmax(1) == v_labels).sum() # 计算一个数据的精确度
  155. total_accuracy = total_accuracy + accuracy
  156. val_acc = float(total_accuracy / 1440) * 100
  157. acc_list[i] = val_acc
  158. print('the_classification_is_correct :', total_accuracy) # 正确分类的个数
  159. print("val_Loss:{}".format(total_val_loss))
  160. print("val_acc:{}".format(float(total_accuracy / 1440) * 100), '%')
  161. total_val_step += 1
  162. torch.save(ResNetOutput, "ResNet_{}.pth".format(i))
  163. # torch.save(ResNetOutput.state_dict(), "ResNet_{}.pth".format(i))
  164. print("{0:-^24}".format('Model_Save'), '\n')
  165. print('val_max=', max(acc_list), '%')

注意!在代码的75行:

x = torch.Tensor.view(x, (-1, 2, 511))  # 511的位置要根据自己的数据集形状调整

DenseNet:

  1. import numpy as np
  2. import torch.optim as optim
  3. import torch.nn as nn
  4. import torch
  5. from torch.utils.data import DataLoader, Dataset
  6. class DenseLayer(torch.nn.Module):
  7. def __init__(self, in_channels, middle_channels=128, out_channels=32):
  8. super(DenseLayer, self).__init__()
  9. self.layer = torch.nn.Sequential(
  10. torch.nn.BatchNorm1d(in_channels),
  11. torch.nn.ReLU(inplace=True),
  12. torch.nn.Conv1d(in_channels, middle_channels, 1),
  13. torch.nn.BatchNorm1d(middle_channels),
  14. torch.nn.ReLU(inplace=True),
  15. torch.nn.Conv1d(middle_channels, out_channels, 3, padding=1)
  16. )
  17. def forward(self, x):
  18. return torch.cat([x, self.layer(x)], dim=1)
  19. class DenseBlock(torch.nn.Sequential):
  20. def __init__(self, layer_num, growth_rate, in_channels, middele_channels=128):
  21. super(DenseBlock, self).__init__()
  22. for i in range(layer_num):
  23. layer = DenseLayer(in_channels + i * growth_rate, middele_channels, growth_rate)
  24. self.add_module('denselayer%d' % (i), layer)
  25. class Transition(torch.nn.Sequential):
  26. def __init__(self, channels):
  27. super(Transition, self).__init__()
  28. self.add_module('norm', torch.nn.BatchNorm1d(channels))
  29. self.add_module('relu', torch.nn.ReLU(inplace=True))
  30. self.add_module('conv', torch.nn.Conv1d(channels, channels // 2, 3, padding=1))
  31. self.add_module('Avgpool', torch.nn.AvgPool1d(2))
  32. class DenseNet(torch.nn.Module):
  33. def __init__(self, layer_num=(6, 12, 24, 16), growth_rate=32, init_features=64, in_channels=1, middele_channels=128,
  34. classes=6):
  35. super(DenseNet, self).__init__()
  36. self.feature_channel_num = init_features
  37. self.conv = torch.nn.Conv1d(in_channels, self.feature_channel_num, 7, 2, 3)
  38. self.norm = torch.nn.BatchNorm1d(self.feature_channel_num)
  39. self.relu = torch.nn.ReLU()
  40. self.maxpool = torch.nn.MaxPool1d(3, 2, 1)
  41. # self.attention = SpatialAttention(64) # 空间注意力机制
  42. self.DenseBlock1 = DenseBlock(layer_num[0], growth_rate, self.feature_channel_num, middele_channels)
  43. self.feature_channel_num = self.feature_channel_num + layer_num[0] * growth_rate
  44. self.Transition1 = Transition(self.feature_channel_num)
  45. self.DenseBlock2 = DenseBlock(layer_num[1], growth_rate, self.feature_channel_num // 2, middele_channels)
  46. self.feature_channel_num = self.feature_channel_num // 2 + layer_num[1] * growth_rate
  47. self.Transition2 = Transition(self.feature_channel_num)
  48. self.DenseBlock3 = DenseBlock(layer_num[2], growth_rate, self.feature_channel_num // 2, middele_channels)
  49. self.feature_channel_num = self.feature_channel_num // 2 + layer_num[2] * growth_rate
  50. self.Transition3 = Transition(self.feature_channel_num)
  51. self.DenseBlock4 = DenseBlock(layer_num[3], growth_rate, self.feature_channel_num // 2, middele_channels)
  52. self.feature_channel_num = self.feature_channel_num // 2 + layer_num[3] * growth_rate
  53. self.avgpool = torch.nn.AdaptiveAvgPool1d(1)
  54. self.classifer = torch.nn.Sequential(
  55. torch.nn.Linear(self.feature_channel_num, self.feature_channel_num // 2),
  56. torch.nn.ReLU(),
  57. torch.nn.Dropout(0.5),
  58. torch.nn.Linear(self.feature_channel_num // 2, classes),
  59. )
  60. def forward(self, x):
  61. x = torch.Tensor.view(x, (-1, 1, 1022)) # 第一个参数是batch_size
  62. x = x.resize_as_(x.to(torch.float32))
  63. x = self.conv(x)
  64. x = self.norm(x) # 正则化
  65. x = self.relu(x)
  66. x = self.maxpool(x)
  67. x = self.DenseBlock1(x)
  68. x = self.Transition1(x)
  69. x = self.DenseBlock2(x)
  70. x = self.Transition2(x)
  71. x = self.DenseBlock3(x)
  72. x = self.Transition3(x)
  73. x = self.DenseBlock4(x)
  74. x = self.avgpool(x)
  75. x = x.view(-1, self.feature_channel_num)
  76. x = self.classifer(x)
  77. return x
  78. class MyDataset(Dataset): # 利用Pytorch的内置函数加载数据
  79. def __init__(self, raman_dir, label_file):
  80. self.raman_dir = np.loadtxt(raman_dir)
  81. self.label_file = np.loadtxt(label_file)
  82. self.raman_data = []
  83. self.label_list = []
  84. for index in self.raman_dir:
  85. self.raman_data.append(index)
  86. for index in self.label_file:
  87. self.label_list.append(index)
  88. def __getitem__(self, idx):
  89. raman = torch.Tensor(self.raman_data[idx])
  90. label = torch.Tensor(self.label_list[idx])
  91. label = np.argmax(label)
  92. return raman, label
  93. def __len__(self):
  94. # 获取数据集的长度
  95. return len(self.label_list)
  96. if __name__ == '__main__':
  97. # 准备数据集
  98. train_data = './train_data.txt'
  99. val_data = './val_data.txt'
  100. # 标签
  101. train_label = './train_labels.txt'
  102. val_label = './val_labels.txt'
  103. # 数据长度
  104. test_data_length = 600
  105. val_data_length = 1440
  106. # 分类的类别
  107. class_num = 6 # 注意调整58行的函数中的class(分类类别)
  108. # 学习率
  109. learning_rate = 0.00001
  110. # 批处理大小
  111. batch_size = 128
  112. # 数据加载器
  113. train_dataset = MyDataset(train_data, train_label)
  114. train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
  115. test_dataset = MyDataset(test_data, test_label)
  116. test_dataloader = DataLoader(test_dataset, batch_size=batch_size, shuffle=True)
  117. val_dataset = MyDataset(val_data, val_label)
  118. val_dataloader = DataLoader(val_dataset, batch_size=batch_size, shuffle=True)
  119. train_data_size = len(train_dataset)
  120. val_data_size = len(val_dataset)
  121. # 创建网络模型
  122. DenseNetOutput = DenseNet().cuda() # .Cuda()数据是指放到GPU上
  123. # 定义损失函数
  124. loss_fn = nn.CrossEntropyLoss().cuda() # 交叉熵函数
  125. # 定义优化器
  126. optimizer = optim.Adam(DenseNetOutput.parameters(), lr=learning_rate)
  127. # 记录验证的次数
  128. total_train_step = 0
  129. total_val_step = 0
  130. writer = SummaryWriter("logs_train") # 记录训练的权重
  131. # 训练
  132. epoch = 30 #
  133. acc_list = np.zeros(epoch)
  134. print("{0:-^27}".format('Train_Model'))
  135. for i in range(epoch):
  136. print("----------epoch={}----------".format(i + 1))
  137. DenseNetOutput.train()
  138. for data in train_dataloader: # data 是batch大小
  139. raman_train_data, t_labels = data
  140. raman_train_data = raman_train_data.cuda()
  141. t_labels = t_labels.cuda()
  142. output = DenseNetOutput(raman_train_data)
  143. loss = loss_fn(output, t_labels)
  144. # 优化器优化模型
  145. optimizer.zero_grad() # 梯度清零
  146. loss.backward() # 反向传播
  147. optimizer.step() # 优化更新参数
  148. total_train_step = total_train_step + 1
  149. print("train_times:{},Loss:{}".format(total_train_step, loss.item()))
  150. # 测试步骤开始
  151. DenseNetOutput.eval()
  152. total_val_loss = 0
  153. total_accuracy = 0
  154. with torch.no_grad(): # 测试的时候不需要对梯度进行调整,所以梯度设置不调整
  155. for data in val_dataloader:
  156. raman_val_data, v_labels = data
  157. raman_val_data = raman_val_data.cuda()
  158. v_labels = v_labels.cuda()
  159. outputs = DenseNetOutput(raman_val_data)
  160. loss = loss_fn(outputs, v_labels)
  161. total_val_loss = total_val_loss + loss.item() # 计算损失值的和
  162. accuracy = 0
  163. for j in v_labels: # 计算精确度的和
  164. if outputs.argmax(1)[j] == v_labels[j]:
  165. accuracy = accuracy + 1
  166. # accuracy = (outputs.argmax(1) == v_labels).sum() # 计算一个数据的精确度
  167. total_accuracy = total_accuracy + accuracy
  168. val_acc = float(total_accuracy / val_data_size) * 100
  169. acc_list[i] = val_acc # 记录验证集的正确率
  170. print('the_classification_is_correct :', total_accuracy, val_data_length)
  171. print("val_Loss:{}".format(total_val_loss))
  172. print("val_acc:{}".format(val_acc), '%')
  173. total_val_step += 1
  174. torch.save(DenseNetOutput, "DenseNet_{}.pth".format(i + 1))
  175. print("{0:-^24}".format('Model_Saved'), '\n')
  176. print('val_max=', max(acc_list), '%') # 验证集的最高正确率

注意!在代码的93行:

x = torch.Tensor.view(x, (-1, 1, 1022))  # 1022的位置要根据自己的数据集大小取调整 

测试代码:

  1. import torch
  2. import numpy as np
  3. from ResNet import Bottlrneck, ResNet
  4. # from DenseNet_SpatialAttention import DenseNet, DenseLayer, DenseBlock
  5. device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') # 判断是否有GPU
  6. test_data = np.loadtxt('./test_data.txt') # 测试集的路径
  7. model = ResNet().to(device)
  8. model.load_state_dict(torch.load('ResNet_100.pth')) # 加载模型
  9. # model = DenseNet().to(device)
  10. # model.load_state_dict(torch.load('DenseNet_100.pth')) # 加载模型
  11. test_length = test_data.shape[0]
  12. for i in range(test_length):
  13. td = torch.from_numpy(test_data[i]).float().to(device)
  14. Predict_output = model(td).to(device)
  15. _, predicted = Predict_output.max(1)
  16. pred_type = predicted.item()
  17. print('pred_type:', pred_type)

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

闽ICP备14008679号