admin管理员组

文章数量:1647017

本博文来自b站非常棒的一个入门教程:PyTorch深度学习快速入门教程(绝对通俗易懂!)【小土堆】

前置环境条件

Anaconda安装

官网地址:anaconda
本帖按照Python3.6版本示例,故安装anaconda3
安装教程:Anaconda安装-超详细版(2023)

显卡驱动+CUDA+CUDNN

参考教程:CUDA、CUDNN在windows下的安装及配置

环境搭建

Anaconda基础环境

创建

Anaconda可以创建一个独立的环境,在这环境里可以任意配置python、pytorch等等
创建命令:

conda create -n pytorch python=3.6

创建了一个名为pytorch的指定python版本的初始环境

激活

conda activate pytorch

命令行左侧表明当前环境名称

可以通过下面的命令查看当前环境下都有哪些基础包,这时候是没有pytorch的

pip list

pytorch安装

安装选择:pytorch
根据自己CUDA的版本进行选择,如果是老版本的可以在下面这里选择:

根据CUDA的版本选择!!!
注意:这里最好不要用conda安装,用pip,conda我下载后是用不了cuda的,比如使用下面这条:

pytorch验证

按照如下方式验证:

如果这里不是true的话就要检查自己的cuda和pytorch的版本是否有问题了,问题解决可以参考:torch.cuda.is_available()返回false——解决办法

编辑器选择

PyCharm

Pycharm下载

下载:win下载地址
这里下载社区版即可:

详细的pycharm的教程可以自己找一下

PyCharm导入环境

new project后按照如下方式:

重点注意Environment要选择我们刚刚在anaconda中创建好的名字叫pytorch的环境,这个里面我们刚刚是已经导入了pytorch的,然后create就可以了。

创建好后可以在python的console里验证一下环境是否有问题:

每一步执行都可以在右边看到当前存储的变量详情

至此pycharm的基础环境搭建已经完成

Jupyter

jupyter安装

单独安装jupyter的话可以自行找一下教程,如果是安装了Anaconda的话,就已经默认附带安装了jupyter了

jupyter导入环境

jupyter默认在base环境,由于我们当前需要使用pytorch的,所以这里有两种解决方案:
1.在base环境中安装pytorch(不推荐)
2.在已安装pytorch的环境中安装jupyter(推荐)
安装方式是在已安装pytorch的环境中(这里是举例是刚刚创建的pytorch环境)执行以下命令:

conda install nb_conda

这样就安装好Jupyter了,安装完成后通过以下命令启动Jupyter:

jupyter notebook

启动好后,新建一个文件,选择pytorch环境,如下:

可以验证下我们的pytorch的cuda是否可用:

每一步都可以独立执行并看到结果
至此,Jupyter的环境配置完成

两个重要的学习函数

dir()

dir()函数可以让我们知道工具箱以及工具箱中的分隔区有什么东西
以学习pytorch为例

dir(torch)
dir(torch.cuda)
dir(torch.cuda.is_available)

以上三条命令均可打印出对应的工具箱里都存放了哪些工具和分割区

help()

help()函数能让我们知道每个工具的使用方法
以学习torch.cuda.is_available为例

help(torch.cuda.is_available)

注意:上面的is_available虽然是一个函数工具,但是使用help的时候需要把括号()去掉!

Pytorch加载数据

Dataset类的使用

测试数据集

示例数据下载地址:蚂蚁蜜蜂/练手数据集:链接: https://pan.baidu/s/1jZoTmoFzaTLWh4lKBHVbEA 密码: 5suq

数据集引入

引入:

from torch.utils.data import Dataset

可以通过help(Dataset)以及Dataset??的方式查看Dataset的官方解释

图片读取

图片读取(以PIL为例):

from PIL import Image
# 注意windows路径中的反斜杠\需要通过反斜杠转义符来转义
img_path = "D:\\workspaces\\learn_pytorch\\learn_pytorch\\dataset\\train\\ants\\0013035.jpg"
img = Image.open(img_path)
img.show()

文件阅读

# python中用来阅读文件流的工具
import os
from PIL import Image
root_dir = "dataset/train"
label_dir = "ants"
path = os.path.join(root_dir, label_dir)
img_path = os.listdir(path)
idx = 0
img_name = img_path[idx]
img_item_path = os.path.join(root_dir, label_dir, img_name)
img = Image.open(img_item_path)
img.show()

使用实例:

import os
from torch.utils.data import Dataset
from PIL import Image

class MyData(Dataset):
    def __init__(self, root_dir, label_dir):
        self.root_dir = root_dir
        self.label_dir = label_dir
        self.path = os.path.join(self.root_dir, self.label_dir)
        self.img_path = os.listdir(self.path)

    def __getitem__(self, idx):
        img_name = self.img_path[idx]
        img_item_path = os.path.join(self.root_dir, self.label_dir, img_name)
        img = Image.open(img_item_path)
        label = self.label_dir
        return img, label

    def __len__(self):
        return len(self.img_path)

root_dir = "dataset/train"
# 这里只是因为图片都是同一个标签所以这样做,一般来说是会有同步的label文件夹,txt文件名称与img名称一致,内容为label值
ants_label_dir = "ants"
ants_dataset = MyData(root_dir, ants_label_dir)
img,label = ants_dataset[0]

TensorBoard

可视化的训练过程工具

简单使用

数据坐标图

from torch.utils.tensorboard import SummaryWriter
# 这里是指存放的文件路径
writer = SummaryWriter("logs")

# writer.add_image()
# y = x
for i in range(100):
# 添加图标的标量,依次是标题,y,x
    writer.add_scalar("y = x", i, i)
writer.close()

运行成功后可以看到本地多了一个logs文件夹,其中生成了文件

文件打开命令:

tensorboard --logdir=logs

指定端口号:

tensorboard --logdir=logs --port=6007

如果生成的图像保留了上一次的结果,可以删掉logs里的文件,并且重启tensorbaord即可

图像

示例:

from torch.utils.tensorboard import SummaryWriter
import numpy as np
from PIL import  Image

writer = SummaryWriter("logs")
image_path = "data/train/ants_image/0013035.jpg"
img_PIL = Image.open(image_path)
img_array = np.array(img_PIL)
print(type(img_array))
print(img_array.shape)

# 可以ctrl+点击方法进入查看方法详情和example
# 参数分别对应名称 图片(使用opencv的方式可以用Tensor参数) 第几步 数据三位对应含义模式
writer.add_image("train", img_array, 3, dataformats="HWC")
for i in range(100):
    writer.add_scalar("y = x", 2*i, i)

writer.close()

Transforms

tensor图像类型

tensor数据类型是包含了一些神经网络必要参数的图片格式

from PIL import Image
from torchvision import transforms

img_path = "data/train/ants_image/0013035.jpg"
img = Image.open(img_path)

tensor_trans = transforms.ToTensor()
tensor_img = tensor_trans(img)

print(tensor_img)

通过opencv处理得到的图片结果是tensor格式,opencv的安装:

pip install opencv-python

由于我们这里的python版本比较低,所以应该安装一个低版本的opencv:

pip install opencv-python==4.3.0.38

使用opencv的时候使用

cv.imread()

即可返回tensor类型的图片

简单使用方法

from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

writer = SummaryWriter("logs")
img_path = "data/train/ants_image/0013035.jpg"
img = Image.open(img_path)
print(img)

# toTensor
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image("ToTensor", img_tensor)

# Normalize
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([6,3,2],[9, 3, 5])
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalize", img_norm, 2)

# Resize
print(img.size)
trans_resize = transforms.Resize((512,512))
# img PIL-> resize -> img_resize PIL
img_resize = trans_resize(img)
# img_resize PIL -> totensor ->img)resize tensor
img_resize = trans_totensor(img_resize)
writer.add_image("Resize", img_resize, 0)
print(img_resize)

torchvision中的数据集

文档

使用

这里以体积比较小的CIFAR10为例

import torchvision
from torch.utils.tensorboard import SummaryWriter

dataset_transform = torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])

# 如果要运行下面被注掉的print代码,要把这里的transform去掉,因为这里会转换成tensor格式
# 下载对应的数据集到指定目录下,如果已有则不再下载
train_set = torchvision.datasets.CIFAR10(root="./dataset", train=True, transform=dataset_transform, download=True)
test_set = torchvision.datasets.CIFAR10(root="./dataset", train=False, transform=dataset_transform, download=True)

# print(test_set[0])
# print(test_set.classes)
#
# img, target = test_set[0]
# print(img)
# print(target)
# print(test_set.classes[target])
# img.show()
#
# print(test_set[0])

writer = SummaryWriter("logs")
for i in range(10):
    img, target = test_set[i]
    writer.add_image("test_set", img, i)

writer.close()

dataloader

dataloader定义了以什么样的方式从dataset中取值,例子:

import torchvision

# 准备的测试数据集
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

test_data = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor())

# 参数:数据集、一次取的数量、是否乱序、进程数、最后不足一个batch的时候是否丢弃
test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)

# 测试数据集中第一张图片以及target
img, target = test_data[0]
print(img.shape)
print(target)

writer = SummaryWriter("logs")
for epoch in range(2):
    step = 0
    for data in test_loader:
        imgs, targets = data
        writer.add_images("Epoch: {}".format(epoch), imgs, step)
        step = step + 1

writer.close()

神经网络的搭建

nn.Module的使用

这个是pytorch提供的一个搭建神经网络的壳子,一些如激活函数、forword、backword等神经网络因素均可在此定义,简单应用如下:

import torch
from torch import nn

class Test(nn.Module):

    # 重写方法可以用code中的generate一件生成
    def __init__(self):
        super().__init__()
        
    # 前向
    def forward(self, input):
        output = input + 1
        return output

# 这步会调用init
test = Test()
x = torch.tensor(1.0)
# 这步会调用forward
output = test(x)
print(output)

卷积操作

# 卷积操作
import torch
import torch.nn.functional as F

# 输入
input = torch.tensor([[1,2,0,3,1],
                      [0,1,2,3,1],
                      [1,2,1,0,0],
                      [5,2,3,1,1],
                      [2,1,0,1,1]])
# 卷积核
kernel = torch.tensor([[1,2,1],
                       [0,1,0],
                       [2,1,0]])

# 化为标准尺寸 batch_size 二维没有深度 5,5
input = torch.reshape(input, (1,1,5,5))
kernel = torch.reshape(kernel, (1,1,3,3))

# stride:步长,填一个值就是横向纵向一样 padding:填充
output = F.conv2d(input, kernel, stride=1, padding=1)
print(output)

卷积层

示例:

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

dataset = torchvision.datasets.CIFAR10("data", train=False, transform=torchvision.transforms.ToTensor(), download=True)

dataLoader = DataLoader(dataset, batch_size=64)
class Test(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)

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

test = Test()

writer = SummaryWriter("logs")

step = 0
for data in dataLoader:
    imgs, targets = data
    output = test.conv1(imgs)
    print(imgs.shape)
    print(output.shape)
    # torch.Size([64, 3, 32, 32])
    writer.add_images("input", imgs, step)
    # torch.Size([64, 6, 30, 30]) -> ([xxx, 3, 30, 30])
    output = torch.reshape(output, (-1, 3, 30, 30))
    writer.add_images("output", output, step)

    step = step + 1

writer.close()

池化层

这里以最大池化层为例,池化就是用一个核去比对输入,选择其中最大的值(最大池化)作为结果的一个值,这样就可以有效减少数据

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

# 这里把数据类型指定为了浮点型,这是池化能处理的类型
input = torch.tensor([[1,2,0,3,1],
                      [0,1,2,3,1],
                      [1,2,1,0,0],
                      [5,2,3,1,1],
                      [2,1,0,1,1]], dtype=torch.float32)

input = torch.reshape(input, (-1, 1, 5, 5))
print(input.shape)

class Test(nn.Module):
    def __init__(self):
        super().__init__()
        # ceil_mode是指如果输入不够核匹配的时候是否丢弃
        self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True)

    def forward(self, input):
        output = self.maxpool1(input)
        return output

test = Test()
# output = test(input)
# print(output)

# 使用图片做个例子
dataset = torchvision.datasets.CIFAR10("data", train=False, transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset, batch_size=64)

writer = SummaryWriter("logs")

step = 0
for data in dataloader:
    img, target = data
    output = test.maxpool1(img)
    writer.add_images("maxpool_input", img, step)
    writer.add_images("maxpool_output",output,step)
    step = step + 1

writer.close()

非线性激活

以sigmoid和relu函数为例:

import torchvision.datasets
from torch import nn
from torch.nn import ReLU, Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10("data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=64)


class Test(nn.Module):
    def __init__(self):
        super().__init__()
        # 这里的relu不传参中默认replace为false,即不改变input本身的值,需要一个output来接收结果
        self.relu = ReLU()
        self.sigmoid = Sigmoid()

    def forward(self, input):
        output = self.relu(input)
        return output


test = Test()
writer = SummaryWriter("logs")
step = 0

for data in dataloader:
    imgs, targets = data
    writer.add_images("relu_input", imgs, global_step=step)
    output = test(imgs)
    writer.add_images("relu_output", output, global_step=step)
    step = step + 1

writer.close()

线性激活

import torch
import torchvision.datasets
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader

dataset =  torchvision.datasets.CIFAR10("data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataLoader = DataLoader(dataset, batch_size=64)

class Test(nn.Module):
    def __init__(self):
        super().__init__()
        # input尺寸 output尺寸
        self.linear = Linear(196608, 10)

    def forward(self, input):
        output = self.linear(input)
        return output

test = Test()

for data in dataLoader:
    imgs, targets = data
    print(imgs.shape)
    # 数据展平
    output = torch.flatten(imgs)
    print(output.shape)
    output = test(output)
    print(output.shape)

完整的简单例子和Sequential的使用

这里以CIFAR model为例:

其中卷积层的各参数的计算公式:

例子:

import torch
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.tensorboard import SummaryWriter


class Test(nn.Module):
    def __init__(self):
        super().__init__()
        self.model = Sequential(
            # 神经网路图中并未给出padding和stride的大小,但是可以根据已有的数据带入公式求出
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

    def forward(self, input):
        output = self.model(input)
        return output

test = Test()
print(test)
input = torch.ones((64, 3, 32, 32))
output = test(input)
print(output.shape)

# 可以通过tensorboard查看model的详情展示
writer = SummaryWriter("logs")
writer.add_graph(test, input)
writer.close()

损失函数与反向传播

import torch
import torchvision
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader

dataset =  torchvision.datasets.CIFAR10("data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataLoader = DataLoader(dataset, batch_size=1)
class Test(nn.Module):
    def __init__(self):
        super().__init__()
        self.model = Sequential(
            # 神经网路图中并未给出padding和stride的大小,但是可以根据已有的数据带入公式求出
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

    def forward(self, input):
        output = self.model(input)
        return output

# 交叉熵误差
loss = nn.CrossEntropyLoss()
test = Test()
for data in dataLoader:
    imgs, targetes = data
    outputs = test(imgs)
    result_loss = loss(outputs, targetes)
    # 梯度下降法
    result_loss.backward()

优化器

import torch
import torchvision
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader

dataset =  torchvision.datasets.CIFAR10("data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
dataLoader = DataLoader(dataset, batch_size=1)
class Test(nn.Module):
    def __init__(self):
        super().__init__()
        self.model = Sequential(
            # 神经网路图中并未给出padding和stride的大小,但是可以根据已有的数据带入公式求出
            Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

    def forward(self, input):
        output = self.model(input)
        return output

# 交叉熵误差
loss = nn.CrossEntropyLoss()
test = Test()
# 优化器(随机梯度下降法)
optim = torch.optim.SGD(test.parameters(), lr=0.01)
for epoch in range(20):
    running_loss = 0.0
    for data in dataLoader:
        imgs, targetes = data
        outputs = test(imgs)
        result_loss = loss(outputs, targetes)
        # 每次都要把梯度先归零
        optim.zero_grad()
        # 梯度下降法
        result_loss.backward()
        # 执行优化
        optim.step()
        running_loss = running_loss + result_loss
    print(running_loss)

现有网络模型的修改

以VGG为例

import torchvision
from torch import nn

vgg16_false = torchvision.models.vgg16(pretrained=False)
vgg16_true = torchvision.models.vgg16(pretrained=True)

print(vgg16_true)

train_data = torchvision.datasets.CIFAR10("data", train=False, transform=torchvision.transforms.ToTensor(), download=True)

# 给vgg16_false的classifier部分新增一步
vgg16_true.classifier.add_module("add_linear", nn.Linear(1000, 10))
print(vgg16_true)

print(vgg16_false)
# 修改vgg16_false原本classifier中的第六步
vgg16_false.classifier[6] = nn.Linear(4096, 10)
print(vgg16_false)

网络模型的保存与读取

保存

import torch
import torchvision.models
from torch import nn

vgg16 = torchvision.models.vgg16(pretrained=False)
# 保存方式1(模型结构+模型参数)
torch.save(vgg16, "vgg16_method1.pth")

# 保存方式2(模型参数)
torch.save(vgg16.state_dict(), "vgg16_method2.pth")

# 陷阱
class Test(nn.Module):
    def __init__(self):
        super(Test, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3)

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

test = Test()
torch.save(test, "test_method1.pth")

读取

import torch
import torchvision.models
from torch import nn

from model_save import *

# 方式1加载模型
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
class Test(nn.Module):
    def __init__(self):
        super(Test, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3)

    def forward(self, x):
        x = self.conv1(x)
        return x
# 原来这里不可以创建 现在版本可以了 不影响了 不是陷阱了
test = Test()
model1 = torch.load("test_method1.pth")
print(model1)

完整的模型训练套路

以Vgg16为例:
model:

import torch
from torch import nn

class Test(nn.Module):
    def __init__(self):
        super(Test, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(64*4*4, 64),
            nn.Linear(64, 10)
        )

    def forward(self, x):
        x = self.model(x)
        return x
# 验证网络的正确性(输入输出的尺寸)
if __name__ == '__main__':
    test = Test()
    input = torch.ones((64, 3, 32, 32))
    output = test(input)
    print(output.shape)

train:

import torch.optim
import torchvision
from torch.utils.tensorboard import SummaryWriter
from model import *

# 准备数据集
from torch import nn
from torch.utils.data import DataLoader

# GPU训练的第二种方式,如果用GPU不能用就改为cpu
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

train_data = torchvision.datasets.CIFAR10(root="data", train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_data = torchvision.datasets.CIFAR10(root="data", train=False, transform=torchvision.transforms.ToTensor(), download=True)

# length长度
train_data_size = len(train_data)
test_data_size = len(test_data)
print("训练数据集的长度为:{}".format(train_data_size))
print("测试数据集的长度为:{}".format(test_data_size))

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

# 创建网络模型
test = Test()
# 利用GPU进行训练
# if torch.cuda.is_available():
#     test = test.cuda()
# GPU训练的第二种方式
test = test.to(device)

# 损失函数
loss_fn = nn.CrossEntropyLoss()
# 利用GPU进行训练
# if torch.cuda.is_available():
#     loss_fn = loss_fn.cuda()
# GPU训练的第二种方式
loss_fn.to(device)

# 优化器(0.01)
learning_rate = 1e-2
optimizer = torch.optim.SGD(test.parameters(), lr=learning_rate)

# 设置训练网络的一些参数
# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10

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

for i in range(epoch):
    print("-------------第 {} 轮训练开始------------".format(i+1))

    # 训练步骤开始
    test.train()
    for data in train_dataloader:
        imgs, targets = data
        ouputs = test(imgs)
        # 利用GPU进行训练
        # if torch.cuda.is_available():
        #     imgs = imgs.cuda()
        #     outputs = outputs.cuda()
        # GPU训练的第二种方式
        imgs = imgs.to(device)
        targets = targets.to(device)
        loss = loss_fn(ouputs, targets)

        # 优化器优化模型
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

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

    # 测试步骤开始
    test.eval()
    total_test_loss = 0
    total_accuracy = 0
    with torch.no_grad():
        for data in test_dataloader:
            imgs, targets = data
            outputs = test(imgs)
            # 利用GPU进行训练
            # if torch.cuda.is_available():
            #     imgs = imgs.cuda()
            #     outputs = outputs.cuda()
            # GPU训练的第二种方式
            imgs = imgs.to(device)
            targets = targets.to(device)
            loss = loss_fn(outputs, targets)
            total_test_loss = total_test_loss + loss.item()
            accuracy = (outputs.argmax(1) == targets).sum()
            total_accuracy = total_accuracy + accuracy

    print("整体测试集上的Loss:{}".format(total_test_loss))
    print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
    total_test_step = total_test_step + 1

    torch.save(test, "test_{}.pth".format(i))
    print("模型已保存")

writer.close()

# 训练数据集的长度为:50000
# 测试数据集的长度为:10000
# -------------第 1 轮训练开始------------
# 训练次数:100, Loss:2.2875332832336426
# 训练次数:200, Loss:2.2817461490631104
# 训练次数:300, Loss:2.2471563816070557
# 训练次数:400, Loss:2.1874866485595703
# 训练次数:500, Loss:2.132857322692871
# 训练次数:600, Loss:2.0947699546813965
# 训练次数:700, Loss:1.998453974723816
# 整体测试集上的Loss:311.0058389902115
# 整体测试集上的正确率:0.29330000281333923
# 模型已保存
# -------------第 2 轮训练开始------------
# 训练次数:800, Loss:1.8712564706802368
# 训练次数:900, Loss:1.8552746772766113
# 训练次数:1000, Loss:1.9931343793869019
# 训练次数:1100, Loss:2.0174198150634766
# 训练次数:1200, Loss:1.7257994413375854
# 训练次数:1300, Loss:1.652297854423523
# 训练次数:1400, Loss:1.7540465593338013
# 训练次数:1500, Loss:1.8159812688827515
# 整体测试集上的Loss:302.5420438051224
# 整体测试集上的正确率:0.30820000171661377
# 模型已保存
# -------------第 3 轮训练开始------------
# 训练次数:1600, Loss:1.725656270980835
# 训练次数:1700, Loss:1.6797170639038086
# 训练次数:1800, Loss:1.9214810132980347
# 训练次数:1900, Loss:1.6856346130371094
# 训练次数:2000, Loss:1.9710376262664795
# 训练次数:2100, Loss:1.5192266702651978
# 训练次数:2200, Loss:1.479805827140808
# 训练次数:2300, Loss:1.7519457340240479
# 整体测试集上的Loss:270.47529923915863
# 整体测试集上的正确率:0.3765999972820282
# 模型已保存
# -------------第 4 轮训练开始------------
# 训练次数:2400, Loss:1.7157604694366455
# 训练次数:2500, Loss:1.3676215410232544
# 训练次数:2600, Loss:1.6065953969955444
# 训练次数:2700, Loss:1.6743344068527222
# 训练次数:2800, Loss:1.512872338294983
# 训练次数:2900, Loss:1.5963021516799927
# 训练次数:3000, Loss:1.3251683712005615
# 训练次数:3100, Loss:1.5172301530838013
# 整体测试集上的Loss:268.4225286245346
# 整体测试集上的正确率:0.3808000087738037
# 模型已保存
# -------------第 5 轮训练开始------------
# 训练次数:3200, Loss:1.3438873291015625
# 训练次数:3300, Loss:1.479296088218689
# 训练次数:3400, Loss:1.4665098190307617
# 训练次数:3500, Loss:1.57560133934021
# 训练次数:3600, Loss:1.5602474212646484
# 训练次数:3700, Loss:1.3665083646774292
# 训练次数:3800, Loss:1.2847181558609009
# 训练次数:3900, Loss:1.4571285247802734
# 整体测试集上的Loss:256.30487501621246
# 整体测试集上的正确率:0.4120999872684479
# 模型已保存
# -------------第 6 轮训练开始------------
# 训练次数:4000, Loss:1.416244626045227
# 训练次数:4100, Loss:1.447770595550537
# 训练次数:4200, Loss:1.5056679248809814
# 训练次数:4300, Loss:1.2424676418304443
# 训练次数:4400, Loss:1.1738076210021973
# 训练次数:4500, Loss:1.3533822298049927
# 训练次数:4600, Loss:1.3864424228668213
# 整体测试集上的Loss:242.49723303318024
# 整体测试集上的正确率:0.4397999942302704
# 模型已保存
# -------------第 7 轮训练开始------------
# 训练次数:4700, Loss:1.3078216314315796
# 训练次数:4800, Loss:1.5058083534240723
# 训练次数:4900, Loss:1.3374627828598022
# 训练次数:5000, Loss:1.4076875448226929
# 训练次数:5100, Loss:0.9756096601486206
# 训练次数:5200, Loss:1.3260319232940674
# 训练次数:5300, Loss:1.219860315322876
# 训练次数:5400, Loss:1.3333754539489746
# 整体测试集上的Loss:228.80793249607086
# 整体测试集上的正确率:0.46939998865127563
# 模型已保存
# -------------第 8 轮训练开始------------
# 训练次数:5500, Loss:1.1971160173416138
# 训练次数:5600, Loss:1.1699522733688354
# 训练次数:5700, Loss:1.1365596055984497
# 训练次数:5800, Loss:1.2375069856643677
# 训练次数:5900, Loss:1.3294936418533325
# 训练次数:6000, Loss:1.5747617483139038
# 训练次数:6100, Loss:1.0562301874160767
# 训练次数:6200, Loss:1.13783860206604
# 整体测试集上的Loss:215.84799444675446
# 整体测试集上的正确率:0.5037999749183655
# 模型已保存
# -------------第 9 轮训练开始------------
# 训练次数:6300, Loss:1.4156008958816528
# 训练次数:6400, Loss:1.1690418720245361
# 训练次数:6500, Loss:1.5879621505737305
# 训练次数:6600, Loss:1.1197248697280884
# 训练次数:6700, Loss:1.0698397159576416
# 训练次数:6800, Loss:1.1453744173049927
# 训练次数:6900, Loss:1.1327089071273804
# 训练次数:7000, Loss:0.8645357489585876
# 整体测试集上的Loss:205.44150614738464
# 整体测试集上的正确率:0.536899983882904
# 模型已保存
# -------------第 10 轮训练开始------------
# 训练次数:7100, Loss:1.2320799827575684
# 训练次数:7200, Loss:0.9454939961433411
# 训练次数:7300, Loss:1.1817400455474854
# 训练次数:7400, Loss:0.7851381897926331
# 训练次数:7500, Loss:1.2794373035430908
# 训练次数:7600, Loss:1.3157795667648315
# 训练次数:7700, Loss:0.8761026859283447
# 训练次数:7800, Loss:1.2188628911972046
# 整体测试集上的Loss:197.47857344150543
# 整体测试集上的正确率:0.5537999868392944
# 模型已保存

样本验证

随机存储一张图片,利用已经训练好的模型进行识别验证:

import torch
from PIL import Image
import torchvision

img_path = "img.png"
image = Image.open(img_path)
image = image.convert("RGB")
print(image)

transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32,32)),
                                            torchvision.transforms.ToTensor()])

image = transform(image)
print(image.shape)

model = torch.load("test_9。pth", map_location=torch.device("cpu"))
print(model)
image = torch.reshape(image, [1, 3, 32, 32])
model.eval()
with torch.no_grad():
    output = model(image)
print(output)

print(output.argmax(1))

end,感谢土堆

本文标签: 深度入门教程快速Pytorch