pytorch 笔记

1.python文件、python控制台Terminal、jupyter代码执行比较

在这里插入图片描述

2.Dataset和Dataloader

dataset存储数据集,dataloader从数据集中批量加载数据,如

把 dataset 放入 DataLoader
    loader = Data.DataLoader(
        dataset=torch_dataset,  # torch TensorDataset format
        batch_size=BATCH_SIZE,  # mini batch size 处理的数据个数
        shuffle=False,  # 要不要打乱数据 (打乱比较好)
        num_workers=0,  # 多线程来读数据
    )

3.tensorboard

一种显示图或表格的服务器

在这里插入图片描述
代码示例在这里插入图片描述
效果展示
在这里插入图片描述

4. transform结构及用法

通常用作转换图片格式/大小的模块,如

#ToTensor方法 是transforms中的一个类, 用于将PIL或ndarray类型转化为tensor类型
# 获取PIL图片 将其转化为tensor格式
img = Image.open('xx.jpg')
# 实例化对象
trans_to_Tensor = transforms.ToTensor()
# 使用方法进行转换
img_tensor = trans_to_Tensor(img)
# Normalize:图片归一化,修改tensor图片的一些参数,对色调影响很大
# Resize改变图片尺寸
# RandomCrop:随机裁剪,按照规定尺寸随机裁剪图片的任意位置, 传入和输出都是PIL图片
# Compose:可讲totensor方法和resize方法等一并调用

在这里插入图片描述
transform使用totensor的问题在这里插入图片描述

4.1常见的transforms案例

在这里插入图片描述
ToTensor: 将PIL图片转化为带神经网络参数的Tensor图片
在这里插入图片描述
将图片归一化Normalize在这里插入图片描述
归一化在tensorboard的效果在这里插入图片描述

4.2 常见的Transforms

resize-图片重置长和宽
transforms.resize传入的是PIL格式img在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
随机裁剪 RnadomCrop-参数PIL格式图片
在这里插入图片描述
汇总

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

# transforms:Totensor--Normalize--Resize--RandomCrop
img = Image.open("images/img.png")
print(img)

# 得到ToTensor对象--ToTensor使用
trans_totensor = transforms.ToTensor()
# 将图像变为tensor格式的img
img_tensor = trans_totensor(img)

# 写入tensorboard
writer = SummaryWriter("logs")
writer.add_image("Totensor", img_tensor)

# Normalize 图片归一化。 归一化计算公式: output[channel] = (input[channel] - mean[channel]) / std[channel]
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([5, 2, 1], [1, 2, 2])
           #传入tensor格式的img
img_norm = trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("normalImg", img_norm,2)

# resize - img PIL格式
print(img.size)
trans_size = transforms.Resize((512, 512))
# img PIL -> resize -> img_resize PIL
img_resize = trans_size(img)

# img_resize PIL -> totensor - >img_resize tensor
img_resize = trans_totensor(img_resize)
print(img_resize)

writer.add_image("Resize",img_resize,0)

# resize2 - Compose
# 得到ToTensor对象--ToTensor使用
img = Image.open("images/img.png")
trans_totensor = transforms.ToTensor()
trans_size_2 = transforms.Resize(512)
# PIL -> PIL -> tensor              后一个参数的输入 要和前一个参数的输出一致
trans_compose = transforms.Compose([trans_size_2, trans_totensor])
img_resize_2 = trans_compose(img)

writer.add_image("Resize", img_resize_2,1)

# RandomCrop 随机裁剪
img = Image.open("images/img.png")
trans_totensor = transforms.ToTensor()
trans_random = transforms.RandomCrop(512)
trans_compose_2 = transforms.Compose([trans_random, trans_totensor])
for i in range(10):
    img_crop = trans_compose_2(img)
    writer.add_image("RandomCrop", img_crop, i)

writer.close()

5.torchvision

torchvision是Pytorch的一个图形库,主要用来构建计算机视觉模型,torchvision由以下四个部分构成:
1 torchvision.datasets:包括一些加载数据的函数和常用的数据集接口
2 torchvision.models:包含常用的模型结构(含预训练模型),例如AlexNet、ResNet等等
3 torchvision.transforms:包含一些常见的图片变换,例如裁剪、旋转等等
4 torchvision.utils:其他用法

torchvision使用dataset拉取pytorch官网数据集到本地
在这里插入图片描述
将官网下载的图片用 transforms 转化为tensor类型
在这里插入图片描述
在这里插入图片描述

扫描二维码关注公众号,回复: 16640787 查看本文章

6.dataloader

dataset得到数据。dataloader加载器,把数据加载到神经网络,从dataset中取数据。
在这里插入图片描述
在这里插入图片描述
dataloader代码示例

import torchvision
# 测试集数据
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

test_data = torchvision.datasets.CIFAR10(root="./datasets", train=False, transform=torchvision.transforms.ToTensor())
# batch_size : 一次处理64个图片。 drop_last:false表示一次去除64,若数据集最后还有2张图片则只取两张,若为true,后两张不取
# shuffle:false表示取出来的两次图片集顺序一模一样。若为true则两次取出来的图片顺序不一样
test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=False)

# 测试集中第一张样品图片
img, target = test_data[0]
# torch.Size([3, 32, 32]):3代表rgb。32*32的图片
print("img.shape",img.shape)
# 3 代表索引为3的标签
print("target", 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

print("张数:", step)
writer.close()

7.神经网络的搭建

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

forward讲解:使用Pytorch的时候,模型训练时,不需要调用forward这个函数,只需要在实例化一个对象中传入对应的参数就可以自动调用 forward 函数。但需要在定义类中引入"nn.Module",此时如vcoy.forward(x) 就等价于 vcoy(x)

在这里插入图片描述

8.卷积案例

在这里插入图片描述
代码示例
在这里插入图片描述
在这里插入图片描述


import torch.nn.functional as F
import torch
# tensor是张量
# input :  torch.Size([5, 5])
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.Size([3, 3])
kernel = torch.tensor([[1, 2, 1],
                       [0, 1, 0],
                       [2, 1, 0]])

# torch.Size([1, 1, 5, 5])
# reshape改变tensor对象的维度 二维变思维--》conv2d要求tensor输入为四维
input = torch.reshape(input, (1, 1, 5, 5))
# torch.Size([1, 1, 3, 3])
kernel = torch.reshape(kernel, (1, 1, 3, 3))

print(input.shape)
print(kernel.shape)

output = F.conv2d(input,kernel,stride=1)
print(output)

# padding 对输入的数据四周填充一层0
output1 = F.conv2d(input,kernel,stride=1,padding=1)
print(output1)

9.卷积层

在定义的神经网络模型中加入卷积层,使用pytorch官网的Conv2d卷积函数。
在这里插入图片描述


import torchvision
import torch
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("../p18_data", train=False, transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset, batch_size=64)

class Vcoy(nn.Module):

    def __init__(self):
        super(Vcoy, self).__init__()
        # 定义一个卷积层。in_channels:输入 图像个数。out_channels:输出的卷积结果个数。kernel_size:卷积核为3*3
        self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)

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

vcoy = Vcoy()
writer = SummaryWriter("../logs")
step = 0
for data in dataloader:
    imgs, targets = data

    print(imgs.shape)
    out_img = vcoy.forward(imgs)
    print(out_img.shape)
    # torch_Size([64,3,32,32])
    writer.add_images("input",imgs,step)
    # torch_Size([64,6,30,30])
    writer.add_images("output",imgs,step)
    step = step + 1

writer.close()

10.最大池化

上采样:插值。下采样:抽样

池化核(3*3):kernel_size=3,则步长也为3,池化层尺寸默认等于步长

最大池化作用:最大限度的保留图片特征,同时减少数据量。加速训练速度。

在这里插入图片描述
reshape的作用:由于在卷积过程需要输入四维格式的图片,需要通过reshape进行转换。
在这里插入图片描述
神经网络中仅定义了池化,将输入矩阵经过神经网络得到最大池化的结果。
在这里插入图片描述

对CIFRA10数据集中的图像进行池化
在这里插入图片描述

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

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

writer = SummaryWriter("../logs_maxpool")

class Vcoy(nn.Module):

    def __init__(self):
        super(Vcoy, self).__init__()
        # kernel_size=3: 池化核窗口大小,默认步长=池化核窗口尺寸
        self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True)

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

vcoy = Vcoy()
step = 0
for data in dataloader:
    imgs, targets = data
    writer.add_images("input",imgs,step)
    output = vcoy.forward(imgs)
    writer.add_images("output",output,step)
    step = step + 1

writer.close()

池化效果
在这里插入图片描述

补充reshape

在这里插入图片描述

11.非线性激活

非线性激活Sigmoid(input)的使用,输入参数input为CIFAR10数据集图片。可在forward函数使用output = self.relu1(input)查看Relu函数效果
在这里插入图片描述


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

input = torch.tensor([[1,-0.5],
                      [-1, 3]])

print(input.shape)
# reshape : -1代表不设置参数,根据后边3个自动生成。1代表数据只有一层。2,2表示两行两列.将input变为四维的,提供下边使用
input = torch.reshape(input, (-1, 1, 2, 2))
print(input.shape)

dataset = torchvision.datasets.CIFAR10("../p20_data", train=False, download=True,
                                       transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset, batch_size=64)
class Vcoy(nn.Module):

    def __init__(self):
        super(Vcoy, self).__init__()
        # 非线性变换--目的给网络中引入一些非线性特征,因为非线性越多,才能训练出符合各种特征/曲线的模型
        self.relu1 = ReLU()
        self.sigmoid1 = Sigmoid()

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

vcoy = Vcoy()

writer = SummaryWriter("../logs_relu")
step = 0
for data in dataloader:
    imgs, targets = data
    writer.add_images("input1", imgs, global_step=step)
    output = vcoy(imgs)
    writer.add_images("output1", output, global_step=step)
    step = step + 1

writer.close()

在tensorboard上查看效果
在这里插入图片描述
在这里插入图片描述

12.线性层

线性层:训练后,要评价模型的好坏,通过将最后的一层替换成线性层。线性层一般在神经网络模型的后几层,一般为全连接,转化成结果分类数。一般经过卷积(conv2d)-非线性激活(relu)-最大池化(maxpool)-平铺(flatten)-线性变化(linear)。
以CIFAR10数据集的训练过程图为例:经过线性变化输出10个值对应该数据集的10个分类的概率
在这里插入图片描述
线性层案例,pytorch线性函数为Linear(in_feature,out_feature)
在这里插入图片描述

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

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

dataloader = DataLoader(dataset, batch_size=64,drop_last=True)

class Vcoy(nn.Module):

    def __init__(self):
        super(Vcoy, self).__init__()
        self.linear1 = Linear(196608, 10)

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

vcoy = Vcoy()
# linear使用场景:在神经网络的前部分输入是二维矩阵,不需要摊平。而在神经网络的最后几层,需要将卷积层摊平平放到全连接里进行计算
for data in dataloader:
    imgs, targets = data
    # torch.Size([64, 3, 32, 32])
    print(imgs.shape)
    # 最后一个-1代表图像宽度自己拉伸,将图片原来的张量拉伸成长条。
    output = torch.reshape(imgs, (1, 1, 1, -1))
    # torch.Size([1, 1, 1, 196608])
    print(output.shape)
    output = vcoy.forward(output)
    # torch.Size([1, 1, 1, 10])
    print(output.shape)

上图这里torch.reshape(imgs, (1, 1, 1, -1))等价于使用 flatten函数
在这里插入图片描述
根据图片经典卷积过程套入公式反推出padding的填充值
在这里插入图片描述


##### 12.1简单神经网络的搭建

在这里插入图片描述
输出神经网络参数测试结果
在这里插入图片描述

简单神经网络搭建


import torch
from torch import nn
from torch.nn import Module, Conv2d, MaxPool2d, Flatten, Linear, Sequential


class Vcoy(nn.Module):

    def __init__(self):
        super(Vcoy, self).__init__()
        # @前的是channels个数
        # 3代表in_channel,若图片是彩色则代表rgb就为3,若是灰色图像就是1
        # 32代表经过卷积要输出的通道channels个数,一般卷积后的通道数就是下一层的in_channel个数
        # 5代表卷积核尺寸5*5            --第一次卷积
        self.conv1 = Conv2d(3, 32, 5, stride=1, padding=2)
        # 图中池化核尺寸为2
        self.maxpool1 = MaxPool2d(2)
        #   第二次卷积  和 池化
        self.conv2 = Conv2d(32, 32, 5, stride=1, padding=2)
        self.maxpool2 = MaxPool2d(2)
        #   第三次卷积
        self.conv3 = Conv2d(32, 64, 5, stride=1, padding=2)
        self.maxpool3 = MaxPool2d(2)
        # 数据展平--作用同 output = torch.reshape(imgs, (1, 1, 1, -1))
        self.flatten = Flatten()
        # 第一个线性层 64*4*4 = 1024。第一个参数1024代表输入特征个数,第二个参数64代表输出特征个数
        self.linear1 = Linear(1024, 64)
        # 第二个线性层 输出10个结果
        self.linear2 = Linear(64, 10)


    def forward(self, x):
        x = self.conv1(x)
        x = self.maxpool1(x)
        x = self.conv2(x)
        x = self.maxpool2(x)
        x = self.conv3(x)
        x = self.maxpool3(x)
        x = self.flatten(x)
        x = self.linear1(x)
        x = self.linear2(x)
        return x

    def __str__(self):
        # 打印它的全部属性
        print('\n'.join(['{0}: {1}'.format(item[0], item[1]) for item in self.__dict__.items()]))

if __name__ == '__main__':
    vcoy = Vcoy()
    # 3和32和32 代表上边神经网络中输入的 3@32x32,即一张图片,3就是代表rgb为3个通道。 64表示batch_size=64即64张图片数据
    input = torch.ones((64, 3, 32, 32))
    output = vcoy.forward(input)
    print(output.shape)

Sequential的引入(封装)–效果同上
在这里插入图片描述
Sequential的引入


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


class Vcoy(nn.Module):

    def __init__(self):
        super(Vcoy, self).__init__()
        self.model1 = Sequential(
            Conv2d(3, 32, 5, stride=1, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, stride=1, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, stride=1, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

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

if __name__ == '__main__':
    vcoy = Vcoy()
    # 3和32和32 代表上边神经网络中输入的 3@32x32,即一张图片,3就是代表rgb为3个通道。 64表示batch_size=64即64张图片数据
    input = torch.ones((64, 3, 32, 32))
    output = vcoy(input)
    print(output.shape)

    writer = SummaryWriter("../logs_seq")
    writer.add_graph(vcoy, input)
    writer.close()

使用tensorboard查看搭建的神经网络结构
在这里插入图片描述
效果图
在这里插入图片描述
在这里插入图片描述

13.损失函数与反向传播

note:官方文档中参数N一般代表batch_size图片个数。

loss为实际输出和目标输出之间的差值,这个插值越小越好。3个pytorch官网求损失值的函数:在这里插入图片描述

损失函数

在这里插入图片描述

均方误差

在这里插入图片描述

import torch
from torch.nn import L1Loss
from torch import nn
inputs = torch.tensor([1, 2, 3], dtype=torch.float32)
targets = torch.tensor([1, 2, 5], dtype=torch.float32)

inputs = torch.reshape(inputs, (1, 1, 1, 3))
targets = torch.reshape(targets, (1, 1, 1, 3))

loss = L1Loss()
result = loss(inputs, targets)
# 默认计算过程 result = ((1-1) + (2-2) + (5-3))/3
print("result ", result)

loss_mes = nn.MSELoss()
result_mse = loss_mes(inputs, targets)
print("result_mse", result_mse)


if __name__ == '__main__':

    x = torch.tensor([0.1, 0.2, 0.3])
    y = torch.tensor([1])
    # print(x)
    x = torch.reshape(x, (1, 3))
    # print(x)
	# 交叉熵损失函数
    loss_cross = nn.CrossEntropyLoss()
    result_cross = loss_cross(x, y)
    print(result_cross)
交叉熵损失函数识别Person- dog- car,通过CrossEntropyLoss计算的损失值过程,参数参考官网

在这里插入图片描述


交叉熵损失函数输入为2维,reshape将数据转化为二维
在这里插入图片描述
使用交叉熵计算识别 [Person- dog- car] 过程的损失函数。x为假设的网络模型输出的各个类别的概率,y为实际的类别的索引,1即是dog。通过该损失函数计算它们之间的损失值。
在这里插入图片描述
在这里插入图片描述


将12.1 列化后的简单神经网络序应用到CIFAR10数据集上,该数据集一共10个类别
在这里插入图片描述
在这里插入图片描述
计算损失值
在这里插入图片描述
梯度下降法:通过反向传播计算某点的梯度,根据当前点进行参数变化,使得梯度下降,损失值变小
在这里插入图片描述
使用backward计算出每个节点的grad-梯度参数
在这里插入图片描述
在这里插入图片描述
查看module-》grad(即梯度),然后通过优化器根据梯度对神经网络中的参数进行更新。
对应代码


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

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

dataloader = DataLoader(dataset, batch_size=1)

class Vcoy(nn.Module):

    def __init__(self):
        super(Vcoy, self).__init__()
        self.model1 = Sequential(
            Conv2d(3, 32, 5, stride=1, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, stride=1, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, stride=1, padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10)
        )

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

if __name__ == '__main__':
    vcoy = Vcoy()
    loss = nn.CrossEntropyLoss()
    for data in dataloader:
        imgs, targets = data
        outputs = vcoy(imgs)
        result_loss = loss(outputs, targets)
        # print(result_loss)
        result_loss.backward()
        print("finish")



官方其他损失函数
在这里插入图片描述

14.优化器

官方文档
在这里插入图片描述
优化器降低损失值的过程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述存在损失值先降低后增长的问题:在顺序寻找loss最小值,误差小,识别率高。让误差变小,但在函数中很难找到最小值,能找到极小值,需要改变幅度,再次找到最小值。可以尝试降低学习率 lr再查看损失值变化。
在这里插入图片描述

15.现有模型的使用和修改:VGG16模型

在这里插入图片描述
在这里插入图片描述
修改vgg16模型内的参数
在这里插入图片描述
修改后
在这里插入图片描述
添加一步全连接层
在这里插入图片描述

16.网络模型的保存与加载

模型保存的两种方式及加载
保存
在这里插入图片描述
加载方式1:是正常的网络模型
在这里插入图片描述
加载方式2:打印的是一个个的字典形式,不再是网络模型,需要恢复成网络模型
在这里插入图片描述
加载方式2:加载网络模型
在这里插入图片描述
自定义模型保存
在这里插入图片描述
自定义模型加载
在这里插入图片描述

17.完整模型训练套路(数据集CIFAR10)

在这里插入图片描述

17.1搭建神经网络模型并测试

模型
在这里插入图片描述
测试模型输出
在这里插入图片描述
model.py

import torch
from torch import nn

# 搭建神经网络模型
class Vcoy(nn.Module):

    def __init__(self):
        super(Vcoy, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2),
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            # 64*4*4=1024
            nn.Linear(in_features=64*4*4, out_features=64),
            nn.Linear(64, 10)
        )

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

if __name__ == '__main__':
    # 测试网络正确性
    vcoy = Vcoy()
    # 参数说明:64--batch-size 3--in_channels通道数 32*32的图片尺寸
    input = torch.ones((64, 3, 32, 32))
    output = vcoy(input)
    # 输出 torch.Size([64, 10]):64表示64张图片,10表示每个图片在10个类别中的概率(CIFAR10数据集为10个类别)
    print(output.shape)

17.2 模型进行训练、测试、保存每次训练的模型

训练
在这里插入图片描述
在这里插入图片描述

训练结果并保存每一轮训练后的模型。第76行需要变动为 total_test_loss = total_test_loss + loss.item()。 loss格式是 tensor(x)格式,loss.item()是数据x
在这里插入图片描述
train.py

import torch
import torchvision
from torch.utils.tensorboard import SummaryWriter
from model import *
from torch.utils.data import DataLoader
# 准备数据集
train_data = torchvision.datasets.CIFAR10("../train_data", train=True, transform=torchvision.transforms.ToTensor(),
                                          download=True)
test_data = torchvision.datasets.CIFAR10("../train_data", train=False, transform=torchvision.transforms.ToTensor(),
                                          download=True)

# 数据集长度
train_data_size = len(train_data)
test_data_size = len(test_data)
# 若train_data_size=10 则训练数据集的长度为10。 测试集长度10000 训练集50000
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)

# 创建网络模型
vcoy = Vcoy()

# 损失函数:分类问题可使用 交叉熵 损失函数
loss_fn = nn.CrossEntropyLoss()

# 优化器: 采用随机梯度下降
# learning_rate = 1e-2 :1e-2 = 1x(10)^(-2) = 1/100 = 0.01
learning_rate = 0.01
optimizer = torch.optim.SGD(vcoy.parameters(), lr=learning_rate)

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

# 添加tensorboard
writer = SummaryWriter("../logs")

for i in range(epoch):
    print("------第{}轮训练开始------".format(i+1))
    # 训练步骤开始
    for data in train_dataloader:
        imgs, targets = data
        # 训练数据放到网络当中
        output = vcoy(imgs)
        # 根据训练结果得到和真实值的误差--损失值。output:通过神经网络模型后的值,targets是真实值。如猫的图片的targets=猫
        loss = loss_fn(output, targets)

        # 优化器优化模型
        # 梯度清0
        optimizer.zero_grad()
        # 清0的时候,用求出的损失的反向传播得到每个参数节点的梯度
        loss.backward()
        # 进行优化
        optimizer.step()
        # 训练次数+1
        total_train_step = total_train_step + 1
        if total_train_step % 100 == 0:
            print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))
            # 记录每一步训练的损失值 显示到tensorboard上
            writer.add_scalar("train_loss", loss.item(), total_train_step)
    # 如何知道模型有没有训练好,达到想要的需求效果。:每训练完一次课使用测试数据进行测试,测试过程不需要调优
    # 没有梯度时候测试-保证没有在进行调优。测试步骤开始:
    total_test_loss = 0
    with torch.no_grad():
        for data in test_dataloader:
            imgs, targets = data
            outputs = vcoy(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss = total_test_loss + loss.item()

    print("整体测试集上的Loss:{}".format(total_test_loss))
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    # 测试步骤+1
    total_test_step + total_train_step + 1

    # 保存每一轮的训练结果模型
    torch.save(vcoy, "vcoy_{}.pth".format(i))
    print("模型已保存")

writer.close()

训练结果

Files already downloaded and verified
Files already downloaded and verified
训练数据集的长度:50000
测试数据集的长度:10000
------第1轮训练开始------
训练次数:100,Loss:2.2880163192749023
训练次数:200,Loss:2.2714011669158936
训练次数:300,Loss:2.2264020442962646
训练次数:400,Loss:2.1325900554656982
训练次数:500,Loss:2.0504238605499268
训练次数:600,Loss:1.9959642887115479
训练次数:700,Loss:2.049309492111206
整体测试集上的Loss:322.9267883300781
模型已保存
------第2轮训练开始------
训练次数:800,Loss:1.9377368688583374
训练次数:900,Loss:1.8804967403411865

结果优化问题
在这里插入图片描述
argmax案例:利用argmax将上图中outputs转化到preds
在这里插入图片描述
预测值和实际值比较
在这里插入图片描述
利用上述转化过程可对17.1和17.2的模型训练进一步优化,计算出整体的正确率
在这里插入图片描述

改进的train.py,model代码不变

import torch
import torchvision
from torch.utils.tensorboard import SummaryWriter
from model import *
from torch.utils.data import DataLoader
# 准备数据集
train_data = torchvision.datasets.CIFAR10("../train_data", train=True, transform=torchvision.transforms.ToTensor(),
                                          download=True)
test_data = torchvision.datasets.CIFAR10("../train_data", train=False, transform=torchvision.transforms.ToTensor(),
                                          download=True)

# 数据集长度
train_data_size = len(train_data)
test_data_size = len(test_data)
# 若train_data_size=10 则训练数据集的长度为10。 测试集长度10000 训练集50000
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)

# 创建网络模型
vcoy = Vcoy()

# 损失函数:分类问题可使用 交叉熵 损失函数
loss_fn = nn.CrossEntropyLoss()

# 优化器: 采用随机梯度下降
# learning_rate = 1e-2 :1e-2 = 1x(10)^(-2) = 1/100 = 0.01
learning_rate = 0.01
optimizer = torch.optim.SGD(vcoy.parameters(), lr=learning_rate)

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

# 添加tensorboard
writer = SummaryWriter("../logs")

for i in range(epoch):
    print("------第{}轮训练开始------".format(i+1))
    # 训练步骤开始
    for data in train_dataloader:
        imgs, targets = data
        # 训练数据放到网络当中
        output = vcoy(imgs)
        # 根据训练结果得到和真实值的误差--损失值。output:通过神经网络模型后的值,targets是真实值。如猫的图片的targets=猫
        loss = loss_fn(output, targets)

        # 优化器优化模型
        # 梯度清0
        optimizer.zero_grad()
        # 清0的时候,用求出的损失的反向传播得到每个参数节点的梯度
        loss.backward()
        # 进行优化
        optimizer.step()
        # 训练次数+1
        total_train_step = total_train_step + 1
        if total_train_step % 100 == 0:
            print("训练次数:{},Loss:{}".format(total_train_step, loss.item()))
            # 记录每一步训练的损失值 显示到tensorboard上
            writer.add_scalar("train_loss", loss.item(), total_train_step)
    # 如何知道模型有没有训练好,达到想要的需求效果。:每训练完一次课使用测试数据进行测试,测试过程不需要调优
    # 没有梯度时候测试-保证没有在进行调优。测试步骤开始:
    total_test_loss = 0
    # 整体正确率
    total_accuracy = 0
    with torch.no_grad():
        for data in test_dataloader:
            # imgs加载的图片数组 targets加载的图片对应的真实标签值
            imgs, targets = data
            outputs = vcoy(imgs)
            loss = loss_fn(outputs, targets)
            total_test_loss = total_test_loss + loss.item()
            # 累计正确率:先计算出预测结果,再比较真实值,再求和转换
            accuracy = (outputs.argmax(1) == targets).sum()
            total_accuracy = total_accuracy + accuracy.item()

    print("整体测试集上的Loss:{}".format(total_test_loss))
    print("整体测试集上的正确率:{}".format(total_accuracy/test_data_size))
    # 将每轮的测试【损失值】和【正确率】画成图存入tensorboard
    writer.add_scalar("test_loss", total_test_loss, total_test_step)
    writer.add_scalar("test_accuracy", total_accuracy/test_data_size, total_test_step)
    # 测试步骤+1
    total_test_step + total_train_step + 1
    # 保存每一轮的训练结果模型
    torch.save(vcoy, "vcoy_{}.pth".format(i))
    print("模型已保存")
writer.close()

在这里插入图片描述

启动tensorboard查看
在这里插入图片描述
在这里插入图片描述
准确率
在这里插入图片描述
进一步完善网络模型,只添加红圈内,其余不变
在这里插入图片描述

17.3 利用GPU训练

训练方式1:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
gpu训练方式2
在这里插入图片描述
代码 实现
在这里插入图片描述
在这里插入图片描述

17.4 读取一张狗的图片输入模型

在这里插入图片描述
代码部分
在这里插入图片描述
在这里插入图片描述
第一次训练模型准确率可能不高,可切换到vcoy_8.pth模型进行测试
在这里插入图片描述
reshape目的在这里插入图片描述
加载的数据集标签对应的索引,输出的是5对应dog的索引
在这里插入图片描述
识别狗的神经网络代码

import torch
from PIL import Image
import torchvision
from torch import nn

img_path = "../images/dog.png"

image = Image.open(img_path)
# 输出的是:<PIL.WebPImagePlugin.WebPImageFile image mode=RGB size=800x500 at 0x1B6A9F475E0>
print(image)

# png图片格式是四个通道,除了RGB还有一个透明通道,使用convert(rgb)保留颜色通道。
# 若图片本来是三个颜色通道,经过convert不变。但加上这一步可适应各种png jpg格式图片
image = image.convert('RGB')

# Compose:把几个transform连接在一起
transform = torchvision.transforms.Compose(
	# 转化成CIFAR10数据集中图片大小32*32,适应该网络模型输入的参数
    [torchvision.transforms.Resize((32, 32)),
     torchvision.transforms.ToTensor()]
)

image = transform(image)
# 输出:torch.Size([3, 32, 32])
print(image.shape)

# 搭建神经网络模型
class Vcoy(nn.Module):

    def __init__(self):
        super(Vcoy, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2),
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(kernel_size=2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            # 64*4*4=1024
            nn.Linear(in_features=64*4*4, out_features=64),
            nn.Linear(64, 10)
        )

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

# 加载训练过一次的模型
models = torch.load("vcoy_0.pth")
print(models)
# 1指的是batch_size 3只rgb三通道 32是图片大小
image = torch.reshape(image, (1, 3, 32, 32))
# 当前模型是GPU训练 所以进行输入要将image加入gpu中
image = image.cuda()
# 网络模型要求张量的阶数为4,即(batch_size,channel,height,weight),一般图片输入为3阶张量,即(channel:3,Hight:32,Weight:32)
models.eval()
# 节约性能
with torch.no_grad():
    output = models(image)
print(output)
print(output.argmax(1))

gpu训练的模型放到cpu运行
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43917045/article/details/129925746