Pytorch学习日记04-模型应用与修改

VGG16的加载与变化

import torchvision.datasets
from torch import nn
"""
    主要对模型的加载,并用于自己的需求中修改网络层数。
        pretrained是否下载对于成熟数据集的参数作为初始化参数使用.
"""

# import os
# os.environ['TORCH_HOME']='D:/technology/pycharmDown'
train_data = torchvision.datasets.CIFAR10("../DataSet/dataset", train=True, download=True,
                                          transform=torchvision.transforms.ToTensor())

vgg16_false = torchvision.models.vgg16(pretrained=False)
vgg16_True = torchvision.models.vgg16(pretrained=True)
# 使用vgg16去做10分类为题.本身vgg16是做1000分类的,如何修改呢.可以直接在原网络后面添加一层线性层进行一个1000转10的操作.
vgg16_True.classifier.add_module('add_linear', nn.Linear(1000, 10))
print(vgg16_True)
# 或者将vgg中最后一层的线性变换输出变成10也可
vgg16_false.classifier[6] = nn.Linear(4096,10)
print(vgg16_false)

模型保存与加载

model_save.py 保存模型

import torch
import torchvision
from torch import nn
"""
    本文件用于去演示保存我们训练好的模型结构和模型参数
    结合加载文件  model_load.py观看
    两种方法进行存储!两种方式进行加载
"""
# 下载模型
vgg16 = torchvision.models.vgg16(pretrained=False)
# 方法一保存:模型结构+模型参数  会有陷阱!
torch.save(vgg16, "vgg16_method1.pth")
# 方法二保存:仅保存模型参数  官方推荐
torch.save(vgg16.state_dict(), "vgg16_method2.pth")


# 自定义模型,使用第一种方式打包可能出现问题:
class MyModule(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3)

    def forward(self, x):
        output = self.conv1(x)
        return output


mymodule = MyModule()
torch.save(mymodule, "custom_module.pth")

model_load.py 加载模型

import torch
import torchvision.models
from model_save import MyModule

"""
    加载已经训练好的模型数据,进行使用。配合model_save.py进行观看
    两种方式进行加载。
"""
# 保存方式1对应的加载方式  model就是一个网络结构
model = torch.load('vgg16_method1.pth')
print(model)

# 保存方式2对应的加载方式
# 新建网络结构:
vgg16 = torchvision.models.vgg16(pretrained=False)
# 从字典数据中加载出网络的参数
vgg16.load_state_dict(torch.load('vgg16_method2.pth'))
# model = torch.load('vgg16_method2.pth')   # 仅能得到各网络层的参数字典
print(vgg16)

# 陷阱1出现:针对自定义的模型
model = torch.load('custom_module.pth')
print(model)
# Can't get attribute 'MyModule' on <module '__main__' from 'E:\\technology\\pythongross\\Neural_Network\\model_load.py'>
# 如果当前文件没有你自己创建的网络结构,就会无法找到.需要将创建的结构类复制到当前文件中或导入模型名称即可。

完整的模型训练步骤–GPU

利用10分类问题来演示整个过程。数据集为CIFAR10
整个构建过程看代码详解:

import torch.optim
import torchvision.datasets
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

from Classify_model import CIFAR10

# 准备数据集
train_data = torchvision.datasets.CIFAR10("../DataSet/dataset", train=True, transform=torchvision.transforms.ToTensor(),
                                          download=False)
test_data = torchvision.datasets.CIFAR10("../DataSet/dataset", train=False, transform=torchvision.transforms.ToTensor(),
                                         download=False)
# 观看数据集长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print(f"训练数据集的长度{train_data_size}")  # 50000
print(f"训练数据集的长度{test_data_size}")  # 10000

# 利用dataloader加载数据集
train_dataloader = DataLoader(train_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)

# 搭建神经网络 ---就是前面搭建的10分类的神经网络  这部分需要使用模块化思想所以将其单独成一个文件
myModule = CIFAR10()
# 创建损失函数
loss_fn = nn.CrossEntropyLoss()
# 定义优化器
learning_rate = 0.01  # 1e-2
optimizer = torch.optim.SGD(myModule.parameters(), lr=learning_rate)
# 设置训练网络的一些参数
# 记录训练次数
total_train_step = 0
# 记录测试次数
total_test_step = 0
# 设置训练轮次
epoch = 10

# 添加tensorboard
writer = SummaryWriter("CIFAR10")

for i in range(epoch):
    # 严格意思上需要我们去 书写 myModule.train()
    print(f"----第{i + 1}轮训练开始----")
    total_train_loss = 0.0  # 用于观测每轮计算后的损失值
    # 开始传入loader数据开始训练
    for data in train_dataloader:
        imgs, targets = data
        # 传入网络
        output = myModule(imgs)
        # 计算损失函数并反向传播
        loss = loss_fn(output, targets)
        total_train_loss += loss.item()
        # 清除梯度数
        optimizer.zero_grad()
        loss.backward()
        # 优化器步入
        optimizer.step()

    total_train_step += 1
    writer.add_scalar("train_loss", total_train_loss, global_step=total_train_step)
    print(f"当前轮训练总损失值为:{total_train_loss}")

    # 测试步骤开始     没有梯度改变
    # 严格意思上需要我们去书写 myModule.eval()  网络有特殊层时必须调用
    total_test_loss = 0  # 总损失值
    total_accuracy = 0  # 预测正确的个数
    with torch.no_grad():  # 必须这样写让网络梯度不变化
        for data in test_dataloader:
            imgs, targets = data
            outputs = myModule(imgs)
            # 添加正确个数的计算
            accuracy = (outputs.argmax(1) == targets).sum()
            total_accuracy += accuracy
            loss = loss_fn(outputs, targets)
            total_test_loss += loss.item()

    print(f"当前轮测试总损失值为:{total_test_loss}")
    print(f"当前轮测试正确率为:{total_accuracy / test_data_size}")
    total_test_step += 1
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    writer.add_scalar("test_accuracy", total_accuracy / test_data_size, total_test_step)

    print(f"----第{i + 1}轮训练结束----")

    #    每轮结束后保存当前轮训练的参数:
    torch.save(myModule, f"./Module/CIFAR10_{i + 1}.pth")
    print("本轮模型已保存")
writer.close()

tensorboard绘画出训练结果。
上述为分类问题观测损失函数。一般更会利用正确率来作为评价标准。
在这里插入图片描述

函数[].argmax(int)

  • 当int 为0时 将会竖着对比(第一例中选出最大的值的行标)。
  • 为1时,将会横着对比(第一行中选出最大值的列标)。
    测试代码为下图:
    正确率
    在代码中添加计算每轮迭代过程的正确率并绘制图像。
    在这里插入图片描述
    状态栏结果

利用GPU计算

 有两种方式能够添加!

F1 针对网络模型、数据、损失函数 使用.cuda()即可

  • myModule=myModuel.cuda() loss_fn=loss_fn.cuda() imgs=imgs.cuda() targets=targets.cuda()
  • 良好的行为习惯为:先判断if torch.cuda.is_avilable():在执行

F2更适合可移植使用

  • 对于模型、数据、损失函数调用.to(device)
  • 声明device=torch.device("CPU")device=torch.device("cuda") device=torch.device("cuda:0")
    在这里插入图片描述

完整的模型验证步骤

  • 测试 demo 利用已经训练好的模型,利用自己的输入进行预测。
import torch
import torchvision.transforms
from PIL import Image
from Classify_model import CIFAR10
"""
    针对已经存在的模型进行导入自己的数据集进行验证测试的步骤。
        必须获得网络定义的初始类才能够加载成功网络。比如上面导入的CIFAR10即为自定义的网络
        引入自己的数据集,一定将数据集格式尺寸修改成网络传入初始的格式要求才可运行。
        了解模型训练的方式,如果为GPU训练还需要将数据转成CUDA模式。两种方式!
        注意模型导入方式。方式一、方式二的加载方式不同。
        加载后需要将网络设置成测试模式进行测试。
"""
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
image_path = "../pytorch-tutorial-master/imgs/dog.png"
image = Image.open(image_path)
print(image)
image = image.convert('RGB')

transform = torchvision.transforms.Compose(
    [torchvision.transforms.Resize((32, 32)), torchvision.transforms.ToTensor()])
image = transform(image)
# print(image.shape)
image = torch.reshape(image, (1, 3, 32, 32))
image = image.to(device)
# print(image.shape)
model = torch.load('./Module/CIFAR10_10.pth')
model.eval()
with torch.no_grad():
    output = model(image)
    print(output.argmax(1))
# RuntimeError: Input type (torch.FloatTensor) and weight type (torch.cuda.FloatTensor)
# should be the same or input should be a MKLDNN tensor and weight is a dense tensor 这个错误是因为模型是GPU训练的。所以你的图片也得使用GPU   
# 如果想用cpu来观测结果,则在加载过程中model = torch.load('./Module/CIFAR10_10.pth' map_location = torch.device('CPU'))
实验结果为 tensor([5], device='cuda:0')

在这里插入图片描述

公开模型

pass

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值