Pytorch基础

目录

一.Dataset(数据集)代码

二.Tensorboard

三.Transform

四.Transforms的使用

4.1 tansforms中两个函数的使用------Totensor与normalize

 4.2  transforms其余函数的使用

        1. Resize-------将图片进行缩放,有两个参数或者单参数

        2.Compose---------组合使用方法,同步进行resize和totensor

        3. RandomCrop--------------对图片进行随机裁剪

五. 对Transforms的总结,及TensorBoard

六.torchvision中的数据集使用

七.DataLoader的定义及使用

八. 神经网络的基本骨架-nn.Module的使用

九. 神经网络中神经结构的使用

        9.0 卷积操作 -----  其中stride是步数的意思,若为2则是横向或者纵向走两步

        9.0 代码示例

        9.1 神经网络---卷积层

        9.3 神经网络-----池化层

        9.3.1---------------最大池化操作

        9.3------------对数据集进行最大池化操作-----------代码示例

        9.4------------------------------非线性激活

9.5 神经网络的其他层

十. 神经网络搭建实战---利用Sequential

十一. 损失函数与反向传播

        11. 1----------------------------损失函数要注意输入与输出的参数

        11.2----------------------------交叉损失函数

        11.3----------------反向传播:backward( )

十二.优化器 

十三.网络模型的相关设置

        13.1 现有网络模型的使用与修改

        13.2 网络模型的保存与读取(加载)

十四.完整的模型训练套路

        14.1 完整的模型训练代码示例

        14.2 利用tensoerboard来呈现模型训练的过程

        14.3 计算模型的正确率-----利用argmax( )

十五.  整体流程

十六. 利用GPU来训练网络模型 

        16.1 GPU运行的第一种形式

        16.2 GPU运行的第二种方式----常用

十七.  模型测试(demo)套路


一.Dataset(数据集)代码

        

        

在真正的使用中,数据集的分类为

        在一个大的文件中,分为image与label;image为真实的图片对象,label所存储的为每个图片对象所对应的txt文件

2.--------------------------------------------------------------------------------对应上面的image与label

import os

# 设置源目录和目标目录
source_dir = 'dataset/train/bees_image'
target_dir = 'dataset/train/bees_label'

# 如果目标目录不存在,则创建它
if not os.path.exists(target_dir):
os.makedirs(target_dir)

# 遍历源目录中的所有.jpg文件
for filename in os.listdir(source_dir):
if filename.endswith('.jpg'):
# 构建目标文件路径(替换.jpg为.txt)
target_file_path = os.path.join(target_dir, filename.replace('.jpg', '.txt'))

# 创建并写入.txt文件
with open(target_file_path, 'w') as f:
f.write('bees')

print("所有.txt文件已生成并放置在'ants_label'目录下。")
p7代码,新建一个脚本和dataset同目录,蚂蚁的相应地方改成ants就行了

二.Tensorboard

        1.定义和作用

            TensorBoard 是一个由 TensorFlow 提供的可视化工具,它允许用户在训练机器学习模型时可视化和分析模型的性能。TensorBoard 可以展示多种类型的数据,包括损失和准确率曲线、激活直方图、权重和偏差的分布、以及嵌入的可视化等

        2.代码

        

logdir是事件文件夹所在的位置   logs是创建的文件夹

打开方式为 :   tensorboard --logdir =logs  --port6008 

 y轴是标量,x轴是迭代次数,也就是执行次数

        3.在tensorboard下,传入打开图片,并利用numpy进行格式转换; 

        -----最终可以查看过程和输出图片的结果---

三.Transform

        1.transform的结构与用法

-----------tensor的意思就是张量,也就是维度------------------

        ---将一个图片通过工具进行转换,以得到结果,其中totensor是转换为tensor类型

        2.代码实例

        3.为什么要使用tensor数据类型

没有为什么,在深度学习中就是必须要用

四.Transforms的使用

        python中__call__的用法

符号__下划线所表示的是内置函数;其作用是不需要再通过.来调用函数,可以直接在类名中传入参数

4.1 tansforms中两个函数的使用------Totensor与normalize

1.转换数据类型

2.规范化

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

writer = SummaryWriter("logs")
img = Image.open("DataSet/train/ants/0013035.jpg")
print(img)

# ToTensor---------1.转换为tensor数据类型
trans_totensor = transforms.ToTensor()
img_tensor = trans_totensor(img)
writer.add_image("ToTensor", img_tensor)  #名称,图片对象

# Normalize-------2.将图片进行规范化
print(img_tensor[0][0][0])        # 选择第一个图像的第一个通道的第一个像素值 [0]->[0]->[0]
trans_norm = transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5])  # 两个长度为三的数组,分别表示三个通道的平均值和标准差
img_norm= trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("Normalize", img_norm,1)  #后面的数字是迭代次数,也就是第几步

writer.close()

归一化是为了消除奇异值,及样本数据中与其他数据相比特别大或特别小的数据,可以加快训练速度

 4.2  transforms其余函数的使用

        1. Resize-------将图片进行缩放,有两个参数或者单参数

Risize输入两个参数时,输出图片的高和宽的像素点数量会按照你设定的值进行输出。而只输入一个参数时,代表的时你最短的那个边输出的像素点数量

        代码实例

# Resize----------3.1改变图片大小,等比缩放
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)

        2.Compose---------组合使用方法,同步进行resize和totensor

        代码实例

# Compose------------3.2 另一种resize的方法
trans_resize_2 = transforms.Resize(512)  #单参数形式
# PIL -> PIL  --> tensor
trans_compose = transforms.Compose([trans_resize_2, trans_totensor])  #传入的参数是列表的形式,首先进行缩放,再进行数据转换
img_resize_2 = trans_compose(img)
writer.add_image("Resize", img_resize_2, 1)

        3. RandomCrop--------------对图片进行随机裁剪

        代码示例

# RandomCrop-------------4.随机裁剪
trans_random = transforms.RandomCrop(123)
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)   # 总共有10个图片

五. 对Transforms的总结,及TensorBoard

        1.transforms和tensorboard是两种不同的工具,分别用于图像预处理和模型训练过程的可视化;所以请分清两者的作用------> 图像等数据经过transforms中的函数后,在tensorboard中进行可视化展示

        2.tansforms学习技巧-----------如何学习其中的函数

注意所定义的数据所返回的类型

六.torchvision中的数据集使用

torchvision是torch库的一个扩展,专门用于支持计算机视觉任务‌

        1.代码示例---------步骤

-------------数据集的下载可以用迅雷,具体操作看p14------------------------

import torchvision

# 为了在tensorboard中显示,使用tansforms将图片转换为tensor类型
from torch.utils.tensorboard import SummaryWriter

dataset_transform = torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()       #将其类型转换
])


# 定义训练数据集                              存放路径         是否为训练数据集   对图片进行transform中的函数使用   是否下载
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)

img, target = test_set[0]   #返回 ->>图像的信息,种类的下标!!!!!!!!!!!!!!!!!!!!!!!!!

# print(test_set[0])
# print(test_set.classes)   # 打印测试数据集中图片的种类
# print(img)
# print(target)
# print(test_set.classes[target])

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

七.DataLoader的定义及使用

注意在dataloader中,imgs, targets与writer.add_images的写法!!!

        代码示例

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())

# 从测试数据集中加载           传入数据集          从中提取数量      打乱顺序        线程/多线程     删除最后一步所有图像
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("dataloader")

step = 0  #迭代次数
for data in test_loader:
    imgs, targets = data   #将遍历到的图片信息等赋值       
    writer.add_images("test_data_drop_last", imgs, step)
    step = step+1

writer.close()

八. 神经网络的基本骨架-nn.Module的使用

        1.在定义的神经网络模版中-----进行输入与输出的过程

        2.代码示例

import torch
from torch import  nn    #引用神经网络


#创建一个神经网络模版
class Tudui(nn.Module):
    def __int__(self):
        super().__init__()   #引用父类的特殊方法

    def forward(self, input):  #传入一个输入
        output = input + 1
        return output

#创建一个真实的神经网络
tudui = Tudui()
x = torch.tensor(1.0)
output = tudui(x)   #在神经网络中进行输入,再输出
print(output)

九. 神经网络中神经结构的使用

        9.0 卷积操作 -----  其中stride是步数的意思,若为2则是横向或者纵向走两步

其中conv是卷积的意思

        9.0 代码示例

import torch
# 引入神经网络中的所有函数方法,简写为F
import torch.nn.functional as F

#输入图像 --------------注意tensor中只能传入一个参数,所以这里外面还有个中括号
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]])


#上面所定义的输入图像和卷积核只有宽高,没有通道数等参数
#重写输入图像-----在卷积函数中需要输入图像和卷积核的通道数等信息

input = torch.reshape(input, (1, 1, 5, 5)) #后面的参数分别为(batchsize, 通道数,宽,高)
kernel = torch.reshape(kernel, (1, 1, 3, 3))

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

                #输入图像  卷积核    步数
output = F.conv2d(input, kernel, stride=1)
print(output)

#在卷积函数中还有一个参数-------padding-------为几就会将输入图像往外扩展几个大小
output3 = F.conv2d(input, kernel, stride=1, padding=1)
print(output3)

        9.1 神经网络---卷积层

conv2d卷积函数---2d图像(前五个参数必须知道!重要)

channel(通道数):当outchannel为2时,需要两个卷积核,输出结果也为两个

        代码示例

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

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

data_loader = DataLoader(data_set, batch_size=64)

class Tudui(nn.Module):
    def __int__(self):
        super(Tudui, self).__int__()
        #定义一个自身的函数--卷积----->   用2d卷积层来进行赋值
        self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)

    def forward(self, x):
        #传入x这个参数,利用自身定义的函数来进行卷积操作
        x = self.conv1(x)
        return x

#创建实例
tudui = Tudui()

writer = SummaryWriter("logs")

step = 0
for data in data_loader:
    imgs, targets = data
    output = tudui(imgs)   #!!!!!!!将参数imgs图片信息,传入所创建的神经网络中,利用forward函数进行自定义的卷积

    print(imgs.shape)
    print(output.shape)
    # torch.Size([64, 3, 32, 32])  #输出图像集合的信息,batchsize......
    writer.add_image("input", imgs, step)

    # 要将torch.Size([64, 3, 32, 32]) ->> [xxx, 3, 30 , 30]
    output = torch.reshape(output, (-1, 3, 30, 30))
    writer.add_images("output", imgs, step)
    step = step + 1

writer.close()

        9.3 神经网络-----池化层

池化层的步长默认是卷积核的大小

ceil_mode-------------------floor地板,ceil天花板(也就是上下取整)

dilation指的是卷积核元素之间的间距----在卷积中,就是空洞卷积

padding指的是输入图像,对输入图像的周围添加方块数,其内的值一般为0

        9.3.1---------------最大池化操作

通过池化核选取输入图像中所对应的最大值

池化的作用:

将原始图片进行池化,以便运行加快方便

import torch
from torch import nn
from torch.nn import MaxPool2d

input = torch.tensor([[1, 2, 0,3 ,1],
                      [0, 1, 2, 3, 1],
                      [1, 2, 1, 0, 0],
                      [5, 2, 3, 1, 1],    #datatype 数据类型
                      [2, 1, 0, 1, 1]], dtype=torch.float32)

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

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()              #默认为false,即取地板,下限
        self.maxpool = MaxPool2d(kernel_size=3, ceil_mode=False)

    def forward(self, input):
        output = self.maxpool(input)  #将输入图像传入,进行最大池化层操作
        return output

tudui = Tudui()
output = tudui(input)  #对神经网络传入输入图像

        9.3------------对数据集进行最大池化操作-----------代码示例

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

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

data_loader = DataLoader(data_set, batch_size=64)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()              #默认为false,即取地板,下限
        self.maxpool = MaxPool2d(kernel_size=3, ceil_mode=False)

    def forward(self, input):
        output = self.maxpool(input)  #将输入图像传入,进行最大池化层操作
        return output

tudui = Tudui()

writer = SummaryWriter("logs")
step = 0

for data in data_loader:
    imgs, targets = data
    writer.add_images("input", imgs, step)
    output = tudui(imgs)
    writer.add_images("output", output, step)
    step += 1

writer.close()

        9.4------------------------------非线性激活

非线性激活-------两个函数(ReLu与Sigmoid)作用是就是为了非线性的存在

ReLu函数中的参数---inplace,其本意是替换的意思

        代码示例

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

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

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

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

data_loader = DataLoader(data_set, batch_size=64)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.rule = ReLU()

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

tudui = Tudui()

writer = SummaryWriter("new_logs")
step = 0
for data in data_loader:
    imgs, targets = data
    writer.add_images("input", imgs, step)
    output = tudui(imgs)    #因为使用数据集,所以这里传入输入图像
    writer.add_images("output", output, step)
    step += 1

writer.close()

9.5 神经网络的其他层

其他的所有层请看torch官网中的官方文档

正则化层                 Normalization   Layers

                               ReCurrent       Layers

Transformer层         Transformer     Layers

线性层                     Linear Layers  Layers

                               Dropout           Layers  

                               Sparse

线性层-----------------示例代码(将图像变成一行的形式)

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

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

data_loader = DataLoader(data_set, batch_size=64)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.linear = Linear(196608, 10)

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

tudui = Tudui()

for data in data_loader:
    imgs, targets =  data
    print(imgs.shape)
    output = torch.reshape(imgs, (1, 1, 1, -1))
    #将输入展成一维的形式,也就是一行
    output = torch.flatten(output)

    output = tudui(output)
    print(output.shape)

十. 神经网络搭建实战---利用Sequential

        代码示例

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


class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        #通过Sequntial来自定义一个model来进行对数据的训练
        self.model1 = Sequential(
            Conv2d(3, 32, 5, padding=2),  #此处的padding(增加图片周围格子数)是通过公式计算得来的
            MaxPool2d(2),     #池化核的大小为2
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(), #一个平铺操作
            Linear(1024, 64),  # 线性层,一个图片中的1024变为64
            Linear(64, 10)
        )
    def forward(self, x):
        x = self.model1(x)
        return x

tudui = Tudui()
input = torch.ones((64, 3, 32, 32))  # ones就是很多个1,对数据进行1的填充
output = tudui(input)
print(output.shape)

十一. 损失函数与反向传播

        11. 1----------------------------损失函数要注意输入与输出的参数

                                   绝对值损失函数 : L1Loss

                                   平方差损失函数: MSELoss

import torch

# 输入的数据
from torch.nn import L1Loss

inputs = torch.tensor([1, 2, 3], datype=torch.float32 )
# 目标数据
targets = torch.t([1, 2, 5], datype=torch.float32)


#!!!!!!!!因为  L1Loss 函数需要的参数有batchsize,所以需要进行reshape
inputs = torch.reshape(inputs, (1, 1, 1, 3))
targets = torch.reshape(targets, (1, 1, 1, 3))

# 计算损失大小
loss = L1Loss(reduction= 'sum') # 如果不写该参数,则计算方式默认为平均值形式
result = loss(inputs, targets) #传入输入数据与目标数据

print(result)

        11.2----------------------------交叉损失函数

#CrossEntropy Loss   交叉损失函数

# 这里三个参数分别代表预测的 人,狗,猫 三种结果的概率
x = torch.tensor([0.1, 0.2, 0.3]) # 得分结果,也就是真实值
y = torch.tensor([1])      # 1为三个类的下标,此为狗

x = torch.reshape(x, (1, 3))  # 交叉损失函数的参数需要batchsize 与 类别----类别为3

loss_cross = nn.CrossEntropyLoss()
result = loss_cross(x, y)

        在神经网络中使用交叉损失函数,计算损失值大小

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

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

data_loader = DataLoader(data_set, batch_size=64)

class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        #通过Sequntial来自定义一个model来进行对数据的训练
        self.model1 = Sequential(
            Conv2d(3, 32, 5, padding=2),  #此处的padding(增加图片周围格子数)是通过公式计算得来的
            MaxPool2d(2),     #池化核的大小为2
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(), #一个平铺操作
            Linear(1024, 64),  # 线性层,一个图片中的1024变为64
            Linear(64, 10)
        )
    def forward(self, x):
        x = self.model1(x)
        return x


# 定义损失函数
loss = nn.CrossEntropyLoss()
tudui = Tudui()
for data in data_loader:
    imgs, targets = data
    output = tudui(imgs)
    # 计算损失函数
    result_loss = loss(output, targets)
    print(result_loss)

        11.3----------------反向传播:backward( )

反向传播:计算每个节点的梯度参数,以选择合适的优化器,对参数进行优化

# 定义损失函数
loss = nn.CrossEntropyLoss()
tudui = Tudui()
for data in data_loader:
    imgs, targets = data
    output = tudui(imgs)
    # 计算损失函数
    result_loss = loss(output, targets)
    print(result_loss)
    # 进行反向传播,计算每个节点的梯度参数,以选择合适的优化器,对参数进行优化
    result_loss.backward()

十二.优化器 

优化器就是对神经网络中每个结点的梯度参数进行优化,for就是一轮,多轮需要嵌套循环

#构建一个优化器-------此处为随机梯度下降
optim = torch.optim.SGD(tudui.parameters(), lr=0.01) # 传入的参数为结点的参数, 学习速率

for epoch in range(20):
    running_loss = 0.0
    for data in data_loader:
        imgs, targets = data
        outputs = tudui(imgs)
        # 计算损失函数
        result_loss = loss(outputs, targets)
        # 将优化器中结点的梯度参数清零
        optim.zero_grad()
        # 进行反向传播,计算每个节点的梯度参数,以选择合适的优化器,对参数进行优化
        result_loss.backward()
        #优化器运行
        optim.step()
        #计算每轮损失值的大小
        running_loss = running_loss + result_loss
    print(running_loss)

十三.网络模型的相关设置

        13.1 现有网络模型的使用与修改

        代码示例

import torch
import torchvision
from torch import nn

# 加载神经网络模型
vgg166_false = torchvision.models.vgg16(pretrained=False)  # 是否已训练过,选择为否
vgg166_true = torchvision.models.vgg16(pretrained=True) # 已训练过

# 加载CIFAR10中的训练数据集
train_data = torchvision.datasets.CIFAR10("./DataSet", train=True, transform=torchvision.transforms.ToTensor(), download=True)

# 在神经网络中添加一个层---线性层
#            此为一个sequential的名称                       名称            线性层设置
vgg166_true.classifier.add_module('add_linear', nn.Linear(1000, 10))
print(vgg166_true)

# 修改原先的神经网络中的层---线性层
vgg166_false.classifier[6] = nn.Linear(4096, 10)
print(vgg166_false)

 将新添加的线性层放入到classifier中(即sequential中)

        13.2 网络模型的保存与读取(加载)

通常使用方式2来进行保存和加载------------------不保存网络模型结构,只保存数据(字典形式)

import torch
import torchvision

# 加载一个网络模型
vgg16 = torchvision.models.vgg16()

# 保存方式1-------优点:不仅保存网络模型的结构,还保存网络模型的参数

torch.save(vgg16, "vgg16_method1.pth")   # 参数:网络模型, 文件名


# 保存方式2---------官方推荐,只保存模型的数据(字典形式)
torch.save(vgg16.state_dict(), "vgg16_method2.pth")

----------------------------------------------------------------------------------
import torch
import torchvision

# 方式2------加载数据模型(字典形式)

vgg16 = torchvision.models.vgg16() # 字典形式的保存需要先引用网络模型的结构
vgg16.load_state_dict(torch.load("vgg16_method2.pth"))


------------------------如果是在本地目录下已存在的---------------
# --------------------在有自己的神经网络模型的前提下,进行加载--------------
# 需要先引入自己的网络模型,从头文件中引入
model = Tudui()
model.load_state_dict(torch.load("tudui_0.pth", map_location=torch.device('cuda')))

十四.完整的模型训练套路

        14.1 完整的模型训练代码示例

项目分为------模型model、数据集进行训练train

tuidui.train( )-------------开始模型训练

tudui.eval( )---------------开始模型测试

import torch
import torchvision
#---------引入所搭建的神经网络------
from p27_model import *  # *表示所有的东西


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

train_data = torchvision.datasets.CIFAR10("./DataSet", train=True, transform=torchvision.transforms.ToTensor(), download=True)
# 准备测试数据集
test_data = torchvision.datasets.CIFAR10("./DataSet", train=False, transform=torchvision.transforms.ToTensor(), download=True)


# length 长度----计算数据集的大小
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data_size=10, 则训练数据集的大小为:10
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)

# ---------------------数据集都准备完毕,需要搭建的神经网络--------------------

# 1.创建网络模型
tudui = Tudui()

# 2.损失函数
loss_fn = nn.CrossEntropyLoss()  # 交叉损失函数

# 3.优化器
learning_rate = 1e-2 # 1 x(10)^(-2) = 1/100 = 0.01
optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate)

# 4.设置训练网络的一些参数

# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10

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

    #训练步骤开始
    tudui.train()
    for data in train_dataloader:
        imgs, targets = data
        outputs = tudui(imgs)
        #计算损失值
        loss = loss_fn(outputs, targets)

        # 优化器优化模型
        optimizer.zero_grad()  # 将每个结点的梯度参数调为0
        loss.backward() # 反向传播
        optimizer.step() # 优化器调优

        total_train_step = total_train_step+1  # 记录训练的次数
        print("训练次数: {}, Loss:{}".format(total_train_step, loss.item()))

        14.2 利用tensoerboard来呈现模型训练的过程

import torch
import torchvision
#---------引入所搭建的神经网络------
from torch.utils.tensorboard import SummaryWriter

from p27_model import *  # *表示所有的东西


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

train_data = torchvision.datasets.CIFAR10("./DataSet", train=True, transform=torchvision.transforms.ToTensor(), download=True)
# 准备测试数据集
test_data = torchvision.datasets.CIFAR10("./DataSet", train=False, transform=torchvision.transforms.ToTensor(), download=True)


# length 长度----计算数据集的大小
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data_size=10, 则训练数据集的大小为:10
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)

# ---------------------数据集都准备完毕,需要搭建的神经网络--------------------

# 1.创建网络模型
tudui = Tudui()

# 2.损失函数
loss_fn = nn.CrossEntropyLoss()  # 交叉损失函数

# 3.优化器
learning_rate = 1e-2 # 1 x(10)^(-2) = 1/100 = 0.01
optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate)

# 4.设置训练网络的一些参数

# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10

# 添加tensorboard进行训练过程的展示
writer = SummaryWriter("logs_train")


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

    #--------------------------------训练步骤开始-------------------------------------
    tudi.train()
    for data in train_dataloader:
        imgs, targets = data
        outputs = tudui(imgs)
        #计算损失值
        loss = loss_fn(outputs, targets)

        # 优化器优化模型
        optimizer.zero_grad()  # 将每个结点的梯度参数调为0
        loss.backward() # 反向传播
        optimizer.step() # 优化器调优

        total_train_step = total_train_step+1  # 记录训练的次数
        if total_train_step % 100 == 0:   # 当训练次数为100的整数倍时
            print("训练次数: {}, Loss:{}".format(total_train_step, loss.item()))
            # 记录训练的数据,标量的形式
            writer.add_scalar("train_loss", loss.item(), total_train_step)

    # --------------------------测试步骤开始--------------------
    tudui.eval()
    total_test_loss = 0
    with torch.no_grad():  # 在进行测试时,不需要梯度参数
        for data in test_dataloader:
            imgs, targets = data
            outputs = tudui(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)
    total_test_step = total_test_step + 1

    # 保存每轮的网络模型,其数据用字典来保存
    torch.save(tudui, "tudui_{}.pth".format(i))

writer.close()

        14.3 计算模型的正确率-----利用argmax( )

其中argmax(1) 参数为1或者0,1为横向,0为纵向

 # 测试步骤开始
    total_test_loss = 0
    total_accuracy = 0  # 定义总体正确率
    with torch.no_grad():  # 在进行测试时,不需要梯度参数
        for data in test_dataloader:
            imgs, targets = data
            outputs = tudui(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

    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

十五.  整体流程

总结模型训练的整体流程:准备数据、加载数据、准备模型、设置损失函数、设置优化器、开始训练、最后验证(测试)、结果聚合展示

十六. 利用GPU来训练网络模型 

        16.1 GPU运行的第一种形式

需要修改原本代码的三个地方:网络模型、数据、损失函数;分别加.cuda( )

修改以上三处的正确形式:

if torch.cuda.is_available():

        tudui = tudui.cuda( )

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

from torch.utils.tensorboard import SummaryWriter

#---------引入所搭建的神经网络------
# from p27_model import *  # *表示所有的东西


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

train_data = torchvision.datasets.CIFAR10("./DataSet", train=True, transform=torchvision.transforms.ToTensor(), download=True)
# 准备测试数据集
test_data = torchvision.datasets.CIFAR10("./DataSet", train=False, transform=torchvision.transforms.ToTensor(), download=True)


# length 长度----计算数据集的大小
train_data_size = len(train_data)
test_data_size = len(test_data)
# 如果train_data_size=10, 则训练数据集的大小为:10
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)

# ---------------------数据集都准备完毕,需要搭建的神经网络--------------------

# 1.创建网络模型
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1 = Sequential(
            Conv2d(3, 32, 5, padding=2),  # 此处的padding(增加图片周围格子数)是通过公式计算得来的
            MaxPool2d(2),  # 池化核的大小为2
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten(),  # 一个平铺操作
            Linear(1024, 64),  # 线性层,一个图片中的1024变为64
            Linear(64, 10)
        )

    # 前向传播, 输入后变换为输出
    def forward(self, x):
        x = self.model1(x)
        return x
tudui = Tudui()
if torch.cuda.is_available():
    tudui = tudui.cuda()

# 2.损失函数
loss_fn = nn.CrossEntropyLoss()  # 交叉损失函数
if torch.cuda.is_available():
    loss_fn = loss_fn.cuda()

# 3.优化器
learning_rate = 1e-2 # 1 x(10)^(-2) = 1/100 = 0.01
optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate)

# 4.设置训练网络的一些参数

# 记录训练的次数
total_train_step = 0
# 记录测试的次数
total_test_step = 0
# 训练的轮数
epoch = 10

# 添加tensorboard进行训练过程的展示
writer = SummaryWriter("logs_train")


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

    #--------------------------------训练步骤开始-------------------------------------
    tudui.train()
    for data in train_dataloader:
        imgs, targets = data
        if torch.cuda.is_available():
            imgs = imgs.cuda()
            targets = targets.cuda()
        outputs = tudui(imgs)
        #计算损失值
        loss = loss_fn(outputs, targets)

        # 优化器优化模型
        optimizer.zero_grad()  # 将每个结点的梯度参数调为0
        loss.backward() # 反向传播
        optimizer.step() # 优化器调优

        total_train_step = total_train_step+1  # 记录训练的次数
        if total_train_step % 100 == 0:   # 当训练次数为100的整数倍时
            print("训练次数: {}, Loss:{}".format(total_train_step, loss.item()))
            # 记录训练的数据,标量的形式
            writer.add_scalar("train_loss", loss.item(), total_train_step)

    # ---------------------------------测试步骤开始---------------------------------
    tudui.eval()
    total_test_loss = 0
    total_accuracy = 0  # 定义总体正确率
    with torch.no_grad():  # 在进行测试时,不需要梯度参数
        for data in test_dataloader:
            imgs, targets = data
            if torch.cuda.is_available():
                imgs = imgs.cuda()
                targets = targets.cuda()
            outputs = tudui(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

    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(tudui.state_dict(), "tudui_{}.pth".format(i))
    print("模型已保存")

writer.close()

        16.2 GPU运行的第二种方式----常用

# 在最开始进行定义,如果有gpu则直接gpu,否则cpu
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 在gpu下运行
tudui = tudui.to(device)

十七.  模型测试(demo)套路

利用已经训练好的模型,然后给它提供输入的道具结果;真实应用场景下

image = image.convert('RGB')------加上这一步后,可以适应png,jpg各种格式的图片

from PIL import Image
from p27_model import *

import torch
import torchvision
from torch import nn

image_path = "./imgs/airplane.png"
# 通过Image打开图片对象
image = Image.open(image_path)

# 为了适应各种图片格式
image = image.convert('RGB')

print(image)

#   Compose是组合变换
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
                                            torchvision.transforms.ToTensor()])

# 将原始图片进行变换
image = transform(image)


# 加载网络模型-第二种形式
model = Tudui()
model.load_state_dict(torch.load("tudui_0.pth", map_location=torch.device('cuda')))

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))

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值