• pytorh模型训练、测试


    目录

    1 导入数据集

    2 使用tensorboard展示经过各个层的图片数据

    3 完整的模型训练测试流程

    使用Gpu训练的两种方式

    使用tensorboard显示模型

    模型训练测试

    L1Loss函数

    保存未训练模型或者已经训练完的模型

    4 加载训练好的模型进行测试


    1 导入数据集

    1. import torch
    2. from torch.utils.data import DataLoader
    3. import torchvision
    4. from torchvision import transforms
    5. import torch.nn as nn
    6. # 准备数据集
    7. from torch.utils.tensorboard import SummaryWriter
    8. train_data = torchvision.datasets.CIFAR10('./data', train=True, transform=transforms.ToTensor(), download=True)
    9. print("train数据", train_data)
    10. print(f"train_data数据的长度是{len(train_data)}")
    11. train_data = DataLoader(dataset=train_data, batch_size=64, shuffle=True)
    12. print("------------------------------------------")
    13. test_data = torchvision.datasets.CIFAR10('./data', train=False, transform=transforms.ToTensor(), download=True)
    14. print("test数据", test_data)
    15. print(f"test_data数据的长度是{len(test_data)}")
    16. print("第一条数据",test_data[0])
    17. test_data = DataLoader(dataset=test_data, batch_size=64, shuffle=True)

    train数据 Dataset CIFAR10
        Number of datapoints: 50000
        Root location: ./data
        Split: Train
        StandardTransform
    Transform: ToTensor()
    train_data数据的长度是50000
    ------------------------------------------
    Files already downloaded and verified
    test数据 Dataset CIFAR10
        Number of datapoints: 10000
        Root location: ./data
        Split: Test
        StandardTransform
    Transform: ToTensor()
    test_data数据的长度是10000
    第一条数据 (tensor([[[0.6196, 0.6235, 0.6471,  ..., 0.5373, 0.4941, 0.4549],
             [0.5961, 0.5922, 0.6235,  ..., 0.5333, 0.4902, 0.4667],
             [0.5922, 0.5922, 0.6196,  ..., 0.5451, 0.5098, 0.4706],
             ...,
             [0.2667, 0.1647, 0.1216,  ..., 0.1490, 0.0510, 0.1569],
             [0.2392, 0.1922, 0.1373,  ..., 0.1020, 0.1137, 0.0784],
             [0.2118, 0.2196, 0.1765,  ..., 0.0941, 0.1333, 0.0824]],

            [[0.4392, 0.4353, 0.4549,  ..., 0.3725, 0.3569, 0.3333],
             [0.4392, 0.4314, 0.4471,  ..., 0.3725, 0.3569, 0.3451],
             [0.4314, 0.4275, 0.4353,  ..., 0.3843, 0.3725, 0.3490],
     

    2 使用tensorboard展示经过各个层的图片数据

    1. class convModel(nn.Module):
    2. def __init__(self):
    3. super(convModel, self).__init__()
    4. self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, stride=1, padding=0, bias=True, padding_mode='zeros', kernel_size=3)
    5. def forward(self, input_data):
    6. return self.conv1(input_data)
    7. write = SummaryWriter('convModel')
    8. model = convModel()
    9. for batch_id, data in enumerate(test_data):
    10. write.add_images('原始图片数据展示', data[0], dataformats='NCHW', global_step=batch_id)
    11. input_data, label = data[0],data[1]
    12. print("batchSize",input_data.size(0))
    13. output_data = model(input_data)
    14. # 因为经过卷积之后,通道数变为6了,而add_images的源码中要求的通道个数是4个,所以要进行通道变换
    15. output_shape_data = torch.reshape(output_data,(-1,3,30,30))
    16. write.add_images('经过卷积层之后的图片数据展示', output_shape_data, global_step=batch_id)
    17. if batch_id % 300 == 0:
    18. print("原始数据的形状", input_data.shape)
    19. print("经过卷积层之后的形状", output_data.shape)
    20. print("经过形状改变之后", output_shape_data.shape)
    21. write.close()

    batchSize 64
    原始数据的形状 torch.Size([64, 3, 32, 32])
    经过卷积层之后的形状 torch.Size([64, 6, 30, 30])
    经过形状改变之后 torch.Size([128, 3, 30, 30])
    batchSize 64
    batchSize 64
    batchSize 64
    batchSize 64
    batchSize 64
    batchSize 64
    batchSize 64

    1. class maxPoolingModel(nn.Module):
    2. def __init__(self):
    3. super(maxPoolingModel, self).__init__()
    4. self.MaxPool2d = nn.MaxPool2d(kernel_size=2, stride=2, ceil_mode=False)
    5. def forward(self, input_data):
    6. return self.MaxPool2d(input_data)
    7. write = SummaryWriter('maxPoolingModel')
    8. model = maxPoolingModel()
    9. for batch_id, data in enumerate(test_data):
    10. write.add_images('原始图片数据展示', data[0], dataformats='NCHW', global_step=batch_id)
    11. input_data, label = data[0],data[1]
    12. output_data = model(input_data)
    13. write.add_images('经过池化层之后的图片数据展示', output_data, global_step=batch_id)
    14. if batch_id % 300 == 0:
    15. print("原始数据的形状", input_data.shape)
    16. print("经过池化层之后的形状", output_data.shape)
    17. write.close()

    原始数据的形状 torch.Size([64, 3, 32, 32])
    经过池化层之后的形状 torch.Size([64, 3, 16, 16])

    1. class unLineModel(nn.Module):
    2. def __init__(self):
    3. super(unLineModel, self).__init__()
    4. self.sigmoid = nn.Sigmoid()
    5. def forward(self, input_data):
    6. return self.sigmoid(input_data)
    7. write = SummaryWriter('unLineModel')
    8. model = unLineModel()
    9. for batch_id, data in enumerate(test_data):
    10. write.add_images('原始图片数据展示', data[0], dataformats='NCHW', global_step=batch_id)
    11. input_data, label = data[0],data[1]
    12. output_data = model(input_data)
    13. write.add_images('经过非线性层之后的图片数据展示', output_data, global_step=batch_id)
    14. if batch_id % 300 == 0:
    15. print("原始数据的形状", input_data.shape)
    16. print("经过非线性层之后的形状", output_data.shape)
    17. write.close()

    原始数据的形状 torch.Size([64, 3, 32, 32])
    经过非线性层之后的形状 torch.Size([64, 3, 32, 32])

    3 完整的模型训练测试流程

    1. class Model(nn.Module):
    2. def __init__(self):
    3. super(Model,self).__init__()
    4. self.model = nn.Sequential(
    5. nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2,stride=1),
    6. nn.MaxPool2d(kernel_size=2, stride=2),
    7. nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2,stride=1),
    8. nn.MaxPool2d(kernel_size=2, stride=2),
    9. nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2,stride=1),
    10. nn.MaxPool2d(kernel_size=2, stride=2),
    11. nn.Flatten(),
    12. nn.Linear(in_features=1024, out_features=64),
    13. nn.Linear(in_features=64, out_features=10)
    14. )
    15. def forward(self, batch_data):
    16. return self.model(batch_data)
    17. # 第一种方式:使用cuda,只需要给模型、损失函数、训练数据、测试数据调用cuda即可,但是这种情况下必须使用if torch.cuda.is_available():判断是否存在cuda,没有的话还是使用cpu,但是没有使用torch.cuda.is_available()判断的话会出错,导致程序无法运行
    18. # 第二种方式:cuda:0 单个显卡
    19. device = torch.device("cuda:0" if torch.cuda.is_available() else 'cpu')
    20. model = Model()
    21. model.to(device=device)
    22. print(model)
    23. batch_data = torch.ones((64,3,32,32)).to(device)
    24. output = model(batch_data)
    25. print("output.shape", output.shape)

    Model(
      (model): Sequential(
        (0): Conv2d(3, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
        (1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
        (3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (4): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
        (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
        (6): Flatten(start_dim=1, end_dim=-1)
        (7): Linear(in_features=1024, out_features=64, bias=True)
        (8): Linear(in_features=64, out_features=10, bias=True)
     

    使用Gpu训练的两种方式
    # 第一种方式:使用cuda,只需要给模型、损失函数、训练数据、测试数据调用cuda即可,但是这种情况下必须使用if torch.cuda.is_available():判断是否存在cuda,没有的话还是使用cpu,但是没有使用torch.cuda.is_available()判断的话会出错,导致程序无法运行
    # 第二种方式:cuda:0 单个显卡
    device = torch.device("cuda:0" if torch.cuda.is_available() else 'cpu'),在这种情况写,只需要将对应的模型、损失函数、训练数据、测试数据使用to调用device上即可
    
    使用tensorboard显示模型
    1. from torch.utils.tensorboard import SummaryWriter
    2. write = SummaryWriter('model')
    3. write.add_graph(model=model,input_to_model=batch_data)
    4. write.close()
    模型训练测试
    1. # -------------------------CrossEntropyLoss()维度要求的底层源码-------------------
    2. # Shape:
    3. # - Input: :math:`(N, C)` where `C = number of classes`, or
    4. # :math:`(N, C, d_1, d_2, ..., d_K)` with :math:`K \geq 1`
    5. # in the case of `K`-dimensional loss.
    6. # - Target: :math:`(N)` where each value is :math:`0 \leq \text{targets}[i] \leq C-1`, or
    7. # :math:`(N, d_1, d_2, ..., d_K)` with :math:`K \geq 1` in the case of
    8. # K-dimensional loss.
    9. # - Output: scalar.
    10. # If :attr:`reduction` is ``'none'``, then the same size as the target:
    11. # :math:`(N)`, or
    12. # :math:`(N, d_1, d_2, ..., d_K)` with :math:`K \geq 1` in the case
    13. # of K-dimensional loss.
    14. criteria = nn.CrossEntropyLoss()
    15. criteria.to(device)
    16. nn.L1Loss()
    17. optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
    18. sum_loss_list = []
    19. epoch_list = []
    20. from torch.utils.tensorboard import SummaryWriter
    21. write = SummaryWriter("figure")
    22. total_train_step = 0
    23. total_test_step = 0
    24. for epoch in range(50):
    25. ever_epoch_loss_sum = 0.0
    26. print("---------------------第 {} 轮训练开始---------------------".format(epoch+1))
    27. model.train()
    28. for batch_id, data in enumerate(train_data):
    29. input_data, input_label = data
    30. input_data = input_data.to(device)
    31. input_label = input_label.to(device)
    32. output_data = model(input_data)
    33. # if batch_id%300 == 0:
    34. # print("input_data", input_data.shape) # input_data torch.Size([64, 3, 32, 32])
    35. # print("output_data", output_data.shape) # output_data torch.Size([64, 10])
    36. # print("input_label", input_label.shape) # input_label torch.Size([64])
    37. loss = criteria(output_data, input_label)
    38. ever_epoch_loss_sum = ever_epoch_loss_sum + loss.item()
    39. loss.backward()
    40. optimizer.step()
    41. optimizer.zero_grad()
    42. if total_train_step % 200 == 0:
    43. print("当前总的训练次数:{} ,每一次的Loss:{}".format(total_train_step, loss.item()))
    44. write.add_scalar('train_loss', loss.item(), total_train_step)
    45. total_train_step = total_train_step + 1
    46. sum_loss_list.append(ever_epoch_loss_sum)
    47. epoch_list.append(epoch)
    48. print("---------------------第 {} 轮测试开始---------------------".format(epoch+1))
    49. model.eval()
    50. total_test_loss = 0
    51. total_accuracy = 0
    52. with torch.no_grad():
    53. for batch_id, data in enumerate(test_data):
    54. images, label = data
    55. images = images.to(device)
    56. label = label.to(device)
    57. output = model(images)
    58. loss = criteria(output,label)
    59. total_test_loss = total_test_loss + loss.item()
    60. accuracy = (output.argmax(1) == label).sum()
    61. total_accuracy = total_accuracy + accuracy
    62. print("整体测试集上的Loss: {}".format(total_test_loss))
    63. print("整体数据集上的正确率:{}".format(total_accuracy/len(test_data)))
    64. write.add_scalar("test_accuracy",total_accuracy/len(test_data),total_test_step)
    65. write.add_scalar('test_loss', total_test_loss, total_test_step)
    66. total_test_step = total_test_step + 1
    67. torch.save(model,'model_{}.pth'.format(epoch))
    68. print("保存第 {} 轮模型".format(epoch+1))
    69. write.close()
    L1Loss函数
    1. inputs = torch.tensor([1,2,3], dtype=torch.float32)
    2. print("原始数据inputs", inputs)
    3. print("原始数据形状inputs.shape", inputs.shape)
    4. targets = torch.tensor([1,2,5], dtype=torch.float32)
    5. print("目标数据targets", targets)
    6. print("目标数据形状targets.shape", targets.shape)
    7. inputs = torch.reshape(inputs,(1,-1))
    8. print("形状改变数据inputs", inputs)
    9. print("形状改变数据形状inputs.shape", inputs.shape)
    10. targets = torch.reshape(targets,(1,-1))
    11. print("目标数据改变targets", targets)
    12. print("目标数据形状改变targets.shape", targets.shape)
    13. loss = nn.L1Loss()
    14. # - Input: :math:`(N, *)` where :math:`*` means, any number of additional
    15. # dimensions
    16. # - Target: :math:`(N, *)`, same shape as the input
    17. result = loss(inputs, targets)
    18. print(result)

    原始数据inputs tensor([1., 2., 3.])
    原始数据形状inputs.shape torch.Size([3])
    目标数据targets tensor([1., 2., 5.])
    目标数据形状targets.shape torch.Size([3])
    形状改变数据inputs tensor([[1., 2., 3.]])
    形状改变数据形状inputs.shape torch.Size([1, 3])
    目标数据改变targets tensor([[1., 2., 5.]])
    目标数据形状改变targets.shape torch.Size([1, 3])
    tensor(0.6667)

    保存未训练模型或者已经训练完的模型
    1. # 模型的保存
    2. torch.save(model,'class_model.pth')
    3. # 模型加载,但是这种情况下如果加载的模型和原本的模型没有在同一个文件中,那么需要将原本的模型使用from加载到当前文件中,再使用torch.load
    4. model = torch.load('class_model.pth')
    5. print(model)

    4 加载训练好的模型进行测试

    1. import torch.nn as nn
    2. import torch
    3. class Model(nn.Module):
    4. def __init__(self):
    5. super(Model,self).__init__()
    6. self.model = nn.Sequential(
    7. nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2,stride=1),
    8. nn.MaxPool2d(kernel_size=2, stride=2),
    9. nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2,stride=1),
    10. nn.MaxPool2d(kernel_size=2, stride=2),
    11. nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2,stride=1),
    12. nn.MaxPool2d(kernel_size=2, stride=2),
    13. nn.Flatten(),
    14. nn.Linear(in_features=1024, out_features=64),
    15. nn.Linear(in_features=64, out_features=10)
    16. )
    17. def forward(self, batch_data):
    18. return self.model(batch_data)
    19. load_model = torch.load('G:\python_files\深度学习代码库\model_49.pth') # 加载模型,使用上面的非字典形式保存的模型,这个时候加载的时候必须把原本定义的模型加载到当前文件,然后使用该函数加载。同时需要注意,如果加载的模型原本是在cuda上跑的,这个时候要将模型使用load函数的参数map_location=torch.device('cpu')加载到cpu上,或者也可以将图片的数据放入到gpu上,与原本的模型对应起来
    20. from torchvision import transforms
    21. from PIL import Image
    22. image = Image.open('G:\python_files\深度学习代码库\cats\cat\cat.10.jpg')
    23. trans = transforms.Compose([transforms.Resize((32,32)),transforms.ToTensor()])
    24. trans_image_tensor = trans(image)
    25. # 因为上面的模型训练的时候输入是(NCHW),所以将训练完的模型加载进来使用测试的时候必须要将一张图片reshape模型需要的形状,否则就会报错
    26. tensor_shape = torch.reshape(trans_image_tensor,(1,3,32,32)).to(torch.device("cuda:0"))
    27. load_model.eval()
    28. with torch.no_grad():
    29. output = load_model(tensor_shape)
    30. print(output)

    注意事项:

    load_model = torch.load('G:\python_files\深度学习代码库\model_49.pth') # 加载模型,使用上面的非字典形式保存的模型,这个时候加载的时候必须把原本定义的模型加载到当前文件,然后使用该函数加载。同时需要注意,如果加载的模型原本是在cuda上跑的,这个时候要将模型使用load函数的参数map_location=torch.device('cpu')加载到cpu上,或者也可以将图片的数据放入到gpu上,与原本的模型对应起来
    # 因为上面的模型训练的时候输入是(NCHW),所以将训练完的模型加载进来使用测试的时候必须要将一张图片reshape模型需要的形状,否则就会报错
    tensor_shape = torch.reshape(trans_image_tensor,(1,3,32,32)).to(torch.device("cuda:0"))
  • 相关阅读:
    C++11标准模板(STL)- 算法(std::reverse)
    二维平面的变换
    【ASM】字节码操作 工具类与常用类 AdviceAdapter 介绍 打印方法进入 和 方法退出 的参数
    linux c++ 程序只能运行一个实例 文件锁
    【我的C/C++语言学习进阶之旅】C/C++编程笔记:C语言使用宏定义#define来处理通用的可抽取的代码块
    鸿鹄工程项目管理系统em Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统
    C#中+=的用法
    SpringBoot实战案例:图书管理系统
    【25届秋招备战C++】算法篇-排序算法合集
    百度、四维图新、高德争“鲜”恐后
  • 原文地址:https://blog.csdn.net/qq_51691366/article/details/134219130