• 深度学习(pytorch)——神经网络完整模型训练套路及其注意事项


    一、写好网络后如何测试网络的正确性?程序如下:

    1. if __name__ == '__main__':
    2. # 通过以下代码测试模型的正确性
    3. tudui = Tudui()
    4. input = torch.ones((64,3,32,32))
    5. output = tudui(input)
    6. print(output.shape)

    torch.ones((64,3,32,32))表示batch_size=64,channel=3,高H=32,宽W=32,cifar10的图片就是3通道,宽高就是32的 

    二、为了减少打印输出太多的冗余信息,通常每几百次训练打印一次损失,下面程序是每训练100次,打印一次损失值,具体程序如下:

    1. if total_train_step % 100 ==0:
    2. print("训练次数 : {},Loss : {}".format(total_train_step,loss.item()))
    3. writer.add_scalar("train_loss",loss.item(),total_train_step)

    为什么loss要加一个item(),使其变成loss.item(),因为原本的loss是tensor类型,加了item后就变成了数值型,防止构建计算图,具体案例如下:

     

    运行结果如下:

    三、加入tensorboard,具体程序如下:

    在terminal中输入tensorboard --logdir=logs --port=6007得到下图

     

    四、模型的保存程序如下:

    五、在分类问题当中,通常需要有正确率作为分类评判的标准。

    argmax(1)时,是横向查找比较数据的大小索引,取出最大值所在的位置

    也就是说,如果是为1,则返回每一最大值的索引

    argmax(0)时,是纵向查找比较数据的大小索引,取出最大值所在的位置 

    也就是说,如果是为0,则返回每一最大值的索引

     

     

    源程序计算准确率的代码如下:

    六、model.train()的用法

    model.train()的作用是启用 Batch Normalization 和 Dropout。

    如果模型中有BN层(Batch Normalization)和Dropout,需要在训练时添加model.train()。model.train()是保证BN层能够用到每一批数据的均值和方差。对于Dropout,model.train()是随机取一部分网络连接来训练更新参数。

    七、model.eval()的用法

    model.eval()的作用是不启用 Batch Normalization 和 Dropout。

    如果模型中有BN层(Batch Normalization)和Dropout,在测试时添加model.eval()。model.eval()是保证BN层能够用全部训练数据的均值和方差,即测试过程中要保证BN层的均值和方差不变。对于Dropout,model.eval()是利用到了所有网络连接,即不进行随机舍弃神经元。

    训练完train样本后,生成的模型model要用来测试样本。在model(test)之前,需要加上model.eval(),否则的话,有输入数据,即使不训练,它也会改变权值。这是model中含有BN层和Dropout所带来的的性质。

    在做one classification的时候,训练集和测试集的样本分布是不一样的,尤其需要注意这一点。

    八、model.eval()和torch.no_grad()的区别

    在PyTorch中进行validation/test时,会使用model.eval()切换到测试模式,在该模式下:

    1. 主要用于通知dropout层和BN层在train和validation/test模式间切换:

    • 在train模式下,dropout网络层会按照设定的参数p设置保留激活单元的概率(保留概率=p); BN层会继续计算数据的mean和var等参数并更新。

    • 在eval模式下,dropout层会让所有的激活单元都通过,而BN层会停止计算和更新mean和var,直接使用在训练阶段已经学出的mean和var值。

    2. 该模式不会影响各层的gradient计算行为,即gradient计算和存储与training模式一样,只是不进行反向传播(back probagation)。

    而with torch.no_grad()则主要是用于停止autograd模块的工作,以起到加速和节省显存的作用。它的作用是将该with语句包裹起来的部分停止梯度的更新,从而节省了GPU算力和显存,但是并不会影响dropout和BN层的行为。

    如果不在意显存大小和计算时间的话,仅仅使用model.eval()已足够得到正确的validation/test的结果;而with torch.no_grad()则是更进一步加速和节省gpu空间(因为不用计算和存储梯度),从而可以更快计算,也可以跑更大的batch来测试。

    九、案例、实现下图的神经网络结构

     完整程序如下:

    model.py文件

    1. import torch
    2. from torch import nn
    3. class Tudui(nn.Module):
    4. def __init__(self):
    5. super(Tudui, self).__init__()
    6. self.model1 = nn.Sequential(
    7. nn.Conv2d(3, 32, 5, padding=2, stride=1),
    8. nn.MaxPool2d(2),
    9. nn.Conv2d(32, 32, 5, padding=2, stride=1),
    10. nn.MaxPool2d(2),
    11. nn.Conv2d(32, 64, 5, padding=2, stride=1),
    12. nn.MaxPool2d(2),
    13. nn.Flatten(),
    14. nn.Linear(1024, 64),
    15. nn.Linear(64, 10)
    16. )
    17. def forward(self, x):
    18. x = self.model1(x)
    19. return x
    20. if __name__ == '__main__':
    21. # 通过以下代码测试模型的正确性
    22. tudui = Tudui()
    23. input = torch.ones((64,3,32,32))
    24. output = tudui(input)
    25. print(output.shape)

    train.py文件

    1. import torchvision
    2. from torch import nn
    3. from torch.nn import Conv2d, MaxPool2d, Flatten
    4. from torch.utils.tensorboard import SummaryWriter
    5. from model import *
    6. from torch.utils.data import DataLoader
    7. train_data = torchvision.datasets.CIFAR10(root='./data_CIFAR10',train=True,
    8. transform=torchvision.transforms.ToTensor(),download=True)
    9. test_data = torchvision.datasets.CIFAR10(root='./data_CIFAR10',train=False,
    10. transform=torchvision.transforms.ToTensor(),download=True)
    11. train_data_size = len(train_data)
    12. test_data_size = len(test_data)
    13. print("训练数据集的长度为:{} " .format(train_data_size))
    14. print("测试数据集的长度为:{} " .format(test_data_size))
    15. train_dataloader = DataLoader(train_data,batch_size=64)
    16. test_dataloader = DataLoader(test_data,batch_size=64)
    17. #搭建神经网络
    18. tudui = Tudui()
    19. #损失函数
    20. loss_fn = nn.CrossEntropyLoss()
    21. #优化器
    22. optimizer = torch.optim.SGD(tudui.parameters(),lr=0.01)
    23. #设置训练网络的一些参数
    24. total_train_step = 0
    25. total_test_step = 0
    26. epoch = 10
    27. writer = SummaryWriter('./logs_train')
    28. for i in range(epoch):
    29. print("------------第 {} 轮训练开始--------------".format(i+1))
    30. tudui.eval()
    31. for data in train_dataloader:
    32. imgs,targets = data
    33. outputs = tudui(imgs)
    34. loss = loss_fn(outputs,targets)
    35. optimizer.zero_grad()
    36. loss.backward()
    37. optimizer.step()
    38. total_train_step +=1
    39. if total_train_step % 100 ==0:
    40. print("训练次数 : {},Loss : {}".format(total_train_step,loss.item()))
    41. writer.add_scalar("train_loss",loss.item(),total_train_step)
    42. tudui.eval()
    43. total_test_loss = 0
    44. total_accuracy = 0
    45. with torch.no_grad():
    46. for data in test_dataloader:
    47. imgs,targets = data
    48. outputs = tudui(imgs)
    49. loss = loss_fn(outputs,targets)
    50. total_test_loss += loss.item()
    51. accuracy = (outputs.argmax(1) == targets).sum()
    52. total_accuracy = total_accuracy +accuracy
    53. print("整体测试数据集的Loss:{}".format(total_test_loss))
    54. print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))
    55. writer.add_scalar('test_loss',total_test_loss,total_test_step)
    56. writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
    57. total_test_step += 1
    58. torch.save(tudui, 'tudui_{}.pth'.format(i))
    59. print("模型已保存")
    60. writer.close()

    运行结果如下:

     

  • 相关阅读:
    计算机毕业设计 基于thinphp 的校园论坛交流网站(源码+系统+mysql数据库+Lw文档)
    JavaScript this 关键字
    CSS - 盒子模型
    贪心算法的高逼格应用——Huffman编码
    职场新手必备的5款办公软件,特别是第五个百试百用
    KubeGems 启用 Nacos 配置中心
    LangChain大型语言模型(LLM)应用开发(三):Chains
    如何制作一个百货小程序
    功率放大器主要性能指标是什么(功率放大器工作状态的分类)
    别再把Tableau、PowerBI吹上天了,在中国根本用不起来,看看为啥
  • 原文地址:https://blog.csdn.net/qq_42233059/article/details/126674736