当前位置:   article > 正文

小土堆代码暂存 -- 完整的GPU训练_zchnn

zchnn

就只是贴了一个代码,部分解释写在代码注释里面了,之后会补上文字解释:

1. 第一种方式:

  1. import torch
  2. import torchvision
  3. import time #用于计时的
  4. from torch import nn
  5. from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
  6. from torch.utils.data import DataLoader
  7. """
  8. 方法一:
  9. 想要使用GPU训练:那么在 "网络模型的实体" 、 "从Dataoader中加载的数据" 、 "损失函数实体" 都是可以 .cuda()来表明时可以使用GPU的
  10. 并且,网络模型的实体 、 损失函数实体 是可以 不去赋值的
  11. 即: 可以写为 z1 = z1.cuda() 也可以直接略写为 z1.cuda()
  12. PS 对于这种方式,其实为了增强容错,可以加一句:
  13. if torch.cuda.is_available() :
  14. z1 = z1.cuda()
  15. loss_fn = loss_fn.cuda()
  16. imgs = imgs.cuda()
  17. targets = targets.cuda()
  18. """
  19. #定义一个名为Zch的神经网络模型的类 ,之所以是神经网络模型的类是因为Zch继承了nn.Module
  20. class Zch(nn.Module):
  21. def __init__(self):
  22. super(Zch, self).__init__()
  23. self.module1 = Sequential(
  24. Conv2d(3, 32, 5, padding=2) ,
  25. MaxPool2d(2) ,
  26. Conv2d(32, 32, 5, padding=2) ,
  27. MaxPool2d(2) ,
  28. Conv2d(32, 64, 5, padding=2) ,
  29. MaxPool2d(2) ,
  30. Flatten() , # torch对于在nn.Module中也有专门的flatten函数,torch.nn.Flatten()
  31. Linear(1024, 64) ,
  32. Linear(64, 10)
  33. )
  34. #对于神经网络模型,虽说训练时要一来一回 : (来:)需要前向传播计算loss,grad ; (回:)需要反向传播时修正模型中的参数
  35. #但显然,通过前想传播就可以构造出计算图了(计算的流程图了) , 所以 ,反向传播写在神经网络类的定以外就可以了(而且反响传播人家pytorch已经集装好了,两条函数调用就可以了)
  36. def forward(self,x):
  37. output = self.module1(x)
  38. return output
  39. #引入(下载)torch官方已经整理好的数据集CIFAR10
  40. train_dataset = torchvision.datasets.CIFAR10("dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True) # 第二个参数train=True意思是 这是训练数据集;
  41. test_dataset = torchvision.datasets.CIFAR10("dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True) # 第二个参数train=True意思是 这是测试数据集;
  42. #展示train_dataset 、 test_dataset 的长度
  43. print( len( train_dataset ) )
  44. print( len( test_dataset ) )
  45. #通过DataLoader类实例化训练集数据和测试集数据的Dataloader数据加载器
  46. train_dataloader = DataLoader(train_dataset,batch_size=64)
  47. test_dataloader = DataLoader(test_dataset,batch_size=64)
  48. z1 = Zch() # 实例化模型,我们得把训练的数据塞到一个实例出来的模型中去
  49. z1 = z1.cuda() # 将模型变为cuda模式: z1.cuda()
  50. loss_fn = nn.CrossEntropyLoss() # 定义(实例化) 损失函数,由于CIFAR10是一个10分类问题,所以将损失函数实例化为一个交叉熵计算工具,用于计算预测值和真实值之间的差距loss , 并可以通过调用.backward()来根据loss计算出模型中的各个参数的梯度grad
  51. loss_fn = loss_fn.cuda() #损失函数也是可以转换为cuda形式的 : loss_fn.cuda()
  52. learning_rate = 1e-2 # 1e-2 就是0.01的意思,这样更好看、直观。并且,learning_rate是一个学习是比较重要的参数,所以,但提出来,方便查找和修改
  53. optim = torch.optim.SGD(z1.parameters() , lr=learning_rate) #定义(实例化)一个优化器,把模型的实例z1的参数与optim绑定,好让优化器知道 该通过loss_fn.backward()计算出的grad 来去修正谁
  54. #一般会训练多个epoch (1个epoch就是一个全数据集走一遍)
  55. epoch = 10 # 训练的轮数
  56. train_step = 0
  57. test_step = 0
  58. #计算训练时间
  59. start_time = time.time()
  60. for idx in range(epoch):
  61. #训练开始:
  62. z1.train() #对于神经网络中有Dropout层、BatchNorm层等时,在模型训练、测试的时在训练前要明确地加 .train() .eval()标注。 如果网络中没有这两类层结构,那么,.train() .eval()加不加其实没关系不影响模型训练
  63. for data in train_dataloader :
  64. imgs,labels = data #由于CIFAR10是一个10分类问题,所以对于每个图片他都是输出一个数值代表一个类别。由于我们设置batch_size=64 , 所以,labels就算一个长度为64的1维度tensor向量
  65. imgs = imgs.cuda() #对于数据来说就必须得赋值了,无法略写为 imgs.cuda() 或 labels.cuda()
  66. labels = labels.cuda() #labels同理
  67. outputs = z1(imgs)
  68. loss = loss_fn(outputs , labels) # 计算得到loss
  69. #接下来准备用优化器根据loss调用backward()函数 求出的 grad 来对模型参数进行更新 。
  70. #【注意】由于我们是在一套循环里面反复调用优化器对模型参数进行更新,为了避免上一轮的干扰,每次在loss计算相应的grad前,先将优化器的内容清空
  71. optim.zero_grad()
  72. loss.backward() #根据计算得到的loss计算出对应的grad
  73. optim.step() #调用优化器,根据 loss.backward()求得的grad 对模型参数进行更新
  74. train_step += 1
  75. tt_time = time.time()
  76. if train_step % 100 == 0 :
  77. print("第",train_step,"次训练迭代时,loss为:",loss.item()) #loss.item()和loss的区别在于:区别不大,略
  78. print("到第", train_step, "次训练迭代时,耗时:", tt_time-start_time)
  79. #测试开始 :
  80. #如何确认训练的模型是否有效呢? -- 通过测试数据集:测试集数据 传入 刚刚在训练的模型 ,查看其准确率,毕竟loss没有准确率来的直观
  81. z1.eval() # 对于神经网络中有Dropout层、BatchNorm层等时,在模型训练、测试的时在训练前要明确地加 .train() .eval()标注。 如果网络中没有这两类层结构,那么,.train() .eval()加不加其实没关系不影响模型训练
  82. with torch.no_grad() : #在测试的时候就不需要对模型进行调优了,所以我们需要写明no_grad()
  83. test_total_loss = 0
  84. test_total_accuracy = 0 #在一轮epoch中可以正确预测多少个图片分类
  85. for data in test_dataloader :
  86. imgs , targets = data
  87. imgs = imgs.cuda()
  88. targets = targets.cuda()
  89. outputs = z1(imgs)
  90. #计算loss
  91. loss = loss_fn(outputs , targets)
  92. test_total_loss += loss
  93. #计算accuracy
  94. #labels是一个1维的64元素的tensor,我们的outputs是一个2维的64*10的tensor,64是batchsize大小,而10是因为我们的输出是经网络训练后,该张图片是10分类中的各个分类的概率
  95. outputs = outputs.argmax(1) #找到一维array中的最大值,并返回该最大值所在的array的下标 ; 参数为0意味着一列列对比,参数为1意味着一行行对比
  96. accuracy = (outputs == targets).sum()
  97. test_total_accuracy += accuracy
  98. print("第",idx,"轮测试集上的总loss是:",test_total_loss.item()) #不加.item()输出是:tensor(311.6063) 而非 311.6063 就很乱
  99. print("第", idx, "轮测试集上的总accuracy是:", test_total_accuracy.item())
  100. # #补充解释一下求解accuracy时的公式: accuracy = (outputs == targets).sum()
  101. # a1 = torch.tensor([1,3,5,7])
  102. # b1 = torch.tensor([1,36,15,7])
  103. #
  104. # res = (a1 == b1) #因为两个tensor相 == 就是会返回一个元素是True或者False的tensor阿
  105. # print(res)
  106. # print(res.sum()) #该元素是True或者False的tensor的调用sum()函数返回该tensor中所有的True值的加和

2. 第二种方法 :

  1. import torch
  2. import torchvision
  3. import time #用于计时的
  4. from torch import nn
  5. from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
  6. from torch.utils.data import DataLoader
  7. """
  8. 方法二:
  9. 使用.to(device)来定义训练的设备
  10. 方法二 和 方法一 相同,想要使用GPU训练:也是只能在 "网络模型的实体" 、 "从Dataoader中加载的数据" 、 "损失函数实体" 上做文章,将其通过.to()传送至对应的device上
  11. 并且,网络模型的实体 、 损失函数实体 是可以 不去赋值的
  12. 即: 可以写为 z1 = z1.to(device) 也可以直接略写为 z1.to(device)
  13. PS 对于这种方式,其实为了增强容错,更合适的做法是:
  14. if torch.cuda.is_available() :
  15. device = torch.device("cuda:0") # 和 device = torch.device("cuda") 在只有一个GPU时是完全没有差别的
  16. else :
  17. device = torch.device("cpu")
  18. 或者利用语法糖,简单地写为:
  19. device = torch.drvice( "cuda" if torch.cuda.is_availabel() else "cpu" )
  20. """
  21. #定义一个名为Zch的神经网络模型的类 ,之所以是神经网络模型的类是因为Zch继承了nn.Module
  22. class Zch(nn.Module):
  23. def __init__(self):
  24. super(Zch, self).__init__()
  25. self.module1 = Sequential(
  26. Conv2d(3, 32, 5, padding=2) ,
  27. MaxPool2d(2) ,
  28. Conv2d(32, 32, 5, padding=2) ,
  29. MaxPool2d(2) ,
  30. Conv2d(32, 64, 5, padding=2) ,
  31. MaxPool2d(2) ,
  32. Flatten() , # torch对于在nn.Module中也有专门的flatten函数,torch.nn.Flatten()
  33. Linear(1024, 64) ,
  34. Linear(64, 10)
  35. )
  36. #对于神经网络模型,虽说训练时要一来一回 : (来:)需要前向传播计算loss,grad ; (回:)需要反向传播时修正模型中的参数
  37. #但显然,通过前想传播就可以构造出计算图了(计算的流程图了) , 所以 ,反向传播写在神经网络类的定以外就可以了(而且反响传播人家pytorch已经集装好了,两条函数调用就可以了)
  38. def forward(self,x):
  39. output = self.module1(x)
  40. return output
  41. #引入(下载)torch官方已经整理好的数据集CIFAR10
  42. train_dataset = torchvision.datasets.CIFAR10("dataset",train=True,transform=torchvision.transforms.ToTensor(),download=True) # 第二个参数train=True意思是 这是训练数据集;
  43. test_dataset = torchvision.datasets.CIFAR10("dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True) # 第二个参数train=True意思是 这是测试数据集;
  44. #展示train_dataset 、 test_dataset 的长度
  45. print( len( train_dataset ) )
  46. print( len( test_dataset ) )
  47. #通过DataLoader类实例化训练集数据和测试集数据的Dataloader数据加载器
  48. train_dataloader = DataLoader(train_dataset,batch_size=64)
  49. test_dataloader = DataLoader(test_dataset,batch_size=64)
  50. #定义训练的设备:
  51. device_cpu = torch.device("cpu")
  52. device_gpu = torch.device("cuda:0")
  53. z1 = Zch() # 实例化模型,我们得把训练的数据塞到一个实例出来的模型中去
  54. z1 = z1.to(device_gpu) # 将模型发送到device上执行
  55. loss_fn = nn.CrossEntropyLoss() # 定义(实例化) 损失函数,由于CIFAR10是一个10分类问题,所以将损失函数实例化为一个交叉熵计算工具,用于计算预测值和真实值之间的差距loss , 并可以通过调用.backward()来根据loss计算出模型中的各个参数的梯度grad
  56. loss_fn = loss_fn.to(device_gpu) # 将损失函数发送到device上执行
  57. learning_rate = 1e-2 # 1e-2 就是0.01的意思,这样更好看、直观。并且,learning_rate是一个学习是比较重要的参数,所以,但提出来,方便查找和修改
  58. optim = torch.optim.SGD(z1.parameters() , lr=learning_rate) #定义(实例化)一个优化器,把模型的实例z1的参数与optim绑定,好让优化器知道 该通过loss_fn.backward()计算出的grad 来去修正谁
  59. #一般会训练多个epoch (1个epoch就是一个全数据集走一遍)
  60. epoch = 10 # 训练的轮数
  61. train_step = 0
  62. test_step = 0
  63. #计算训练时间
  64. start_time = time.time()
  65. for idx in range(epoch):
  66. #训练开始:
  67. z1.train() #对于神经网络中有Dropout层、BatchNorm层等时,在模型训练、测试的时在训练前要明确地加 .train() .eval()标注。 如果网络中没有这两类层结构,那么,.train() .eval()加不加其实没关系不影响模型训练
  68. for data in train_dataloader :
  69. imgs,labels = data #由于CIFAR10是一个10分类问题,所以对于每个图片他都是输出一个数值代表一个类别。由于我们设置batch_size=64 , 所以,labels就算一个长度为64的1维度tensor向量
  70. imgs = imgs.to(device_gpu) #对于数据来说就必须得赋值了,无法略写为 imgs.cuda() 或 labels.cuda()
  71. labels = labels.to(device_gpu) #labels同理
  72. outputs = z1(imgs)
  73. loss = loss_fn(outputs , labels) # 计算得到loss
  74. #接下来准备用优化器根据loss调用backward()函数 求出的 grad 来对模型参数进行更新 。
  75. #【注意】由于我们是在一套循环里面反复调用优化器对模型参数进行更新,为了避免上一轮的干扰,每次在loss计算相应的grad前,先将优化器的内容清空
  76. optim.zero_grad()
  77. loss.backward() #根据计算得到的loss计算出对应的grad
  78. optim.step() #调用优化器,根据 loss.backward()求得的grad 对模型参数进行更新
  79. train_step += 1
  80. tt_time = time.time()
  81. if train_step % 100 == 0 :
  82. print("第",train_step,"次训练迭代时,loss为:",loss.item()) #loss.item()和loss的区别在于:区别不大,略
  83. print("到第", train_step, "次训练迭代时,耗时:", tt_time-start_time)
  84. #测试开始 :
  85. #如何确认训练的模型是否有效呢? -- 通过测试数据集:测试集数据 传入 刚刚在训练的模型 ,查看其准确率,毕竟loss没有准确率来的直观
  86. z1.eval() # 对于神经网络中有Dropout层、BatchNorm层等时,在模型训练、测试的时在训练前要明确地加 .train() .eval()标注。 如果网络中没有这两类层结构,那么,.train() .eval()加不加其实没关系不影响模型训练
  87. with torch.no_grad() : #在测试的时候就不需要对模型进行调优了,所以我们需要写明no_grad()
  88. test_total_loss = 0
  89. test_total_accuracy = 0 #在一轮epoch中可以正确预测多少个图片分类
  90. for data in test_dataloader :
  91. imgs , targets = data
  92. imgs = imgs.to(device_gpu)
  93. targets = targets.to(device_gpu)
  94. outputs = z1(imgs)
  95. #计算loss
  96. loss = loss_fn(outputs , targets)
  97. test_total_loss += loss
  98. #计算accuracy
  99. #labels是一个1维的64元素的tensor,我们的outputs是一个2维的64*10的tensor,64是batchsize大小,而10是因为我们的输出是经网络训练后,该张图片是10分类中的各个分类的概率
  100. outputs = outputs.argmax(1) #找到一维array中的最大值,并返回该最大值所在的array的下标 ; 参数为0意味着一列列对比,参数为1意味着一行行对比
  101. accuracy = (outputs == targets).sum()
  102. test_total_accuracy += accuracy
  103. print("第",idx,"轮测试集上的总loss是:",test_total_loss.item()) #不加.item()输出是:tensor(311.6063) 而非 311.6063 就很乱
  104. print("第", idx, "轮测试集上的总accuracy是:", test_total_accuracy.item())

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号