首页 > 其他分享 >孙怡带你深度学习(2)--PyTorch框架认识

孙怡带你深度学习(2)--PyTorch框架认识

时间:2024-09-17 22:23:28浏览次数:12  
标签:loss 孙怡 模型 torch 张量 -- PyTorch 数据 self

文章目录

PyTorch框架认识

PyTorch是一个由Facebook人工智能研究院(FAIR)在2016年发布的开源深度学习框架,专为GPU加速的深度神经网络(DNN)编程而设计。它以其简洁、灵活和符合Python风格的特点,在科研和工业生产中得到了广泛应用。

1. Tensor张量

在PyTorch中,张量(Tensor)是核心数据结构,它是一个多维数组,用于存储和变换数据。张量类似于Numpy中的数组,但具有更丰富的功能和灵活性,特别是在支持GPU加速方面。

定义与特性

  • 多维数组:张量可以看作是一个n维数组,其中n可以是任意正整数。它可以是标量(零维数组)、向量(一维数组)、矩阵(二维数组)或具有更高维度的数组。
  • 数据类型统一:张量中的元素具有相同的数据类型,这有助于在GPU上进行高效的并行计算。
  • 支持GPU加速:PyTorch中的张量可以存储在CPU或GPU上,通过将张量转移到GPU上,可以利用GPU的强大计算能力来加速深度学习模型的训练和推理过程。

创建方式

  • 直接使用torch.tensor():根据提供的Python列表或Numpy数组创建张量。
  • 下载数据集时:transform=ToTensor()直接将数据转化为Tensor张量类型。

2. 下载数据集

在PyTorch中,有许多封装了很多与图像相关的模型、数据集,那么如何获取数据集呢?

导入datasets模块

from torchvision import datasets #封装了很多与图像相关的模型,数据集

以datasets模块中的MNIST数据集为例,包含70000张手写数字图像:60000张用于训练,10000张用于测试。图像是灰度的,28*28像素,并且居中的,以减少预处理和加快运行。

下载测试

我们来下载MNIST数据集

from torchvision.transforms import ToTensor # 数据转换,张量,将其他类型数据转换为tensor张量
"""-----下载训练集数据集-----"""
training_data = datasets.MNIST(
    root="data",
    train=True,# 取训练集
    download=True,
    transform=ToTensor(),# 张量,图片是不能直接传入神经网络模型的
) # 对于pytorch库能够识别的数据,一般是tensor张量

"""-----下载测试集数据集-----"""
test_data = datasets.MNIST(
    root="data",
    train=False,
    download=True,
    transform=ToTensor(),
)# numpy数组只能在CPU上运行,Tensor可以在GPU上运行,这在深度学习中可以显著提高计算速度

在这里插入图片描述

下载完成之后可在project栏查看。

展现下载内容

我们来查看部分图片(第59000张到第59009张):

"""-----展现手写字图片-----"""
# tensor -->numpy  矩阵类型数据
from matplotlib import pyplot as plt
figure = plt.figure() # 创建一个新的图形
for i in range(9):
    img,label = training_data[i+59000] #提取第59000张图片

    figure.add_subplot(3,3,i+1) #图像窗口中创建多个小窗口,小窗口用于显示图片
    plt.title(label)
    plt.axis("off")# 关闭当前轴的坐标轴
    plt.imshow(img.squeeze(),cmap="gray")
    a = img.squeeze()# squeeze()从张量img中去掉维度为1的。如果该维度不为1则张量不会改变
plt.show()

图片信息获取时,得到的张量数据类型是这样的:

在这里插入图片描述

我们通过squeeze()函数,去掉维度为1的。这样我们就可以得到图片的高宽大小,将它展现出来:

在这里插入图片描述

3. 创建DataLoader(数据加载器)

在PyTorch中,创建DataLoader的主要作用是将数据集(Dataset)加载到模型中,以便进行训练或推理。DataLoader通过封装数据集,提供了一个高效、灵活的方式来处理数据。

DataLoader通过batch_size参数将数据集自动划分为多个小批次(batch),每一批次的放入模型训练,减少内存的使用,提高训练速度。

import torch
from torch.utils.data import DataLoader
"""
创建数据DataLoader(数据加载器)
batch_size:将数据集分成多份,每一份为batch_size(指定数值)个数据。
优点:减少内存的使用,提高训练速度
"""
train_dataloder = DataLoader(training_data,batch_size=64)# 64张图片为一个包
test_datalodar = DataLoader(test_data,batch_size=64)
# 查看打包好的数据
for x,y in test_datalodar: #x是表示打包好的每一个数据包
    print(f"Shape of x [N, C, H, W]:{x.shape}")
    print(f"Shape of y:{y.shape} {y.dtype}")
    break
-----------------------
Shape of x [N, C, H, W]:torch.Size([64, 1, 28, 28])
Shape of y:torch.Size([64]) torch.int64

4. 选择处理器

我们知道,电脑中的处理器有CPU和GPU两种,CPU擅长执行复杂的指令和逻辑操作,而GPU则擅长处理大量并行计算任务。

所以,在可以的条件下,我们选择使用GPU处理器来学习深度学习,因为计算量比较大:

"""---判断当前设备是否支持GPU,其中mps是苹果m系列芯片的GPU"""
device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
print(f"Using {device} device")
----------------
Using cuda device

5. 神经网络模型

通过调用类的形式来使用神经网络,神经网络的模型:nn.module。

构建模型

我们在构建时,得明确神经网络模型的结构:输入层–隐藏层–输出层,而在每一个隐藏层进入下一层时,都会有一个激活函数计算,所以我们也按着这个架构层次定义函数:

class NeuralNetwork(nn.Module): #通过调用类的形式来使用神经网络,神经网络的模型:nn.module
    def __init__(self): # self类自己本身
        super().__init__() #继承的父类初始化
        self.flatten = nn.Flatten()# 输入层,展开一个对象flatten
        self.hidden1 = nn.Linear(28*28,256)# 隐藏层,第1个参数:有多少神经元传入进来;第二个参数,有多少数据传出去
        self.hidden2 = nn.Linear(256,128)
        self.hidden3 = nn.Linear(128,64)
        self.hidden4 = nn.Linear(64,32)
        self.out = nn.Linear(32,10)#输出层,输出必须与类别数量相同,输入必须是上一层的个数
    def forward(self,x): #前向传播(该名字不要轻易改),告诉它数据的流向
        x = self.flatten(x)
        x = self.hidden1(x)
        x = torch.sigmoid(x) #激活函数
        x = self.hidden2(x)
        x = torch.sigmoid(x)
        x = self.hidden3(x)
        x = torch.sigmoid(x)
        x = self.hidden4(x)
        x = torch.sigmoid(x)
        x = self.out(x)
        return x
model = NeuralNetwork().to(device) #将刚刚创建的模型传入到GPU
print(model)
-----------------------
NeuralNetwork(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (hidden1): Linear(in_features=784, out_features=256, bias=True)
  (hidden2): Linear(in_features=256, out_features=128, bias=True)
  (hidden3): Linear(in_features=128, out_features=64, bias=True)
  (hidden4): Linear(in_features=64, out_features=32, bias=True)
  (out): Linear(in_features=32, out_features=10, bias=True)
)

6. 训练数据

训练数据时,需要注意的参数:

  • optimizer优化器

在PyTorch中,创建Optimizer的主要作用是管理并更新模型中可学习参数(即权重和偏置)的值,以便最小化某个损失函数(loss function)。

  1. 梯度清零:在每次迭代开始时,Optimizer会调用**.zero_grad()**方法来清除之前累积的梯度,这是因为在PyTorch中,梯度是累加的,如果不清零,则下一次的梯度计算会包含前一次的梯度,导致错误的更新。
  2. 梯度计算:在模型进行前向传播(forward pass)和损失计算之后,Optimizer并不直接参与梯度的计算。梯度的计算是通过调用损失函数的**.backward()**方法完成的,该方法会计算损失函数关于模型中所有可学习参数的梯度,并将这些梯度存储在相应的参数对象中。
  3. 参数更新:在梯度计算完成后,Optimizer会调用**.step()**方法来根据计算得到的梯度以及选择的优化算法(如SGD、Adam等)来更新模型的参数。这一步骤是优化过程中最关键的部分,它决定了模型学习的方向和速度。
optimizer = torch.optim.Adam(model.parameters(),lr=0.001)
  • loss_fn损失函数

在PyTorch中,**nn.CrossEntropyLoss()**是一个常用的损失函数,它结合了 nn.LogSoftmax()nn.NLLLoss()(负对数似然损失)在一个单独的类中。

loss_fn = nn.CrossEntropyLoss()

训练集数据

from torch import nn #导入神经网络模块
def train(dataloader,model,loss_fn,optimizer):
    model.train()# 设置模型为训练模式

    batch_size_num =1# 迭代次数 
    for x,y in dataloader:
        x,y = x.to(device),y.to(device)  # 将数据和标签发送到指定设备  
        pred = model.forward(x)  # 前向传播  
        loss = loss_fn(pred,y)  # 计算损失  

        optimizer.zero_grad()  # 清除之前的梯度  
        loss.backward()  # 反向传播  
        optimizer.step()  # 更新模型参数  

        loss_value = loss.item()  # 获取损失值
        if batch_size_num %200 == 0:  # 每200次迭代打印一次损失  
            print(f"loss:{loss_value:>7f} [number:{batch_size_num}]")
        batch_size_num += 1
------------------------
loss:1.039446 [number:200]
loss:0.754774 [number:400]
loss:0.553383 [number:600]
loss:0.573400 [number:800]

测试集数据

def test(dataloader,model,loss_fn):
    size = len(dataloader.dataset) # 获取测试集的总大小。
    num_batches = len(dataloader) # 计算数据加载器中的批次数量。
    model.eval() # 将模型设置为评估模式。
    test_loss,correct = 0,0 # 初始化总损失和正确预测的数量。
    with torch.no_grad():
        for x,y in dataloader:
            x,y = x.to(device),y.to(device)
            pred = model.forward(x)
            test_loss += loss_fn(pred,y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
            a = (pred.argmax(1) == y)
            b = (pred.argmax(1) == y).type(torch.float)
    test_loss /= num_batches
    correct /= size
    correct = round(correct, 4)
    print(f"Test result: \n Accuracy:{(100*correct)}%,Avg loss:{test_loss}")
 ---------------------
Test result: 
 Accuracy:89.96%,Avg loss:0.36642977581092506

我们可以看到,这个模型的正确率不是特别的高,那么接下来我们来提高模型的学习率。

7. 提高模型学习率

遍历了指定的训练周期(epochs)数,并在每个周期中调用 train 函数来训练模型。

"""-----调整学习率-----"""
epochs = 10
for t in range(epochs):
    print(f"Epoch {t+1} \n-------------------------")
    train(train_dataloder,model,loss_fn,optimizer)
print("Done!")
test(test_datalodar,model,loss_fn)
---------------
仅展示优化后的结果:
Test result: 
 Accuracy:97.33000000000001%,Avg loss:0.10455594740913303

总结

本篇介绍了:

  1. PyTorch的框架
  2. 数据类型张量,数据集的获取
  3. 如何构建对应神经网络的模型
  4. 如何优化算法:一、修改optimizer优化器的算法;二、遍历合适的训练周期(epochs)数

标签:loss,孙怡,模型,torch,张量,--,PyTorch,数据,self
From: https://blog.csdn.net/m0_74896766/article/details/142319893

相关文章

  • 文心一言 VS 讯飞星火 VS chatgpt (349)-- 算法导论23.2 8题
    八、Borden教授提出了一个新的分治算法来计算最小生成树。该算法的原理如下:给定图,将划分为两个集合和,使得和的差最多为1。设为端点全部在中的边的集合,为端点全部在中的边的集合。我们递归地解决两个子图和的最小生成树问题。最后,在边集合中选择横跨切割和的最小权重的边来将求出的......
  • 操作系统知识强化内存映射文件(25王道)
    内存映射文件本文根据25王道操作系统内存映射文件这一章所作跟课笔记什么是内存映射文件首先来看看什么是内存映射文件。简单来说,这是操作系统向上层的程序员提供的一个系统调用功能。通过这个功能,程序员可以很方便的去访问文件数据,另外这个功能也可以很方便的让多个进程......
  • 动态表单生成
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>DynamicForm</title>......
  • 周也带你进阶OpenCV (1)--采样、直方图即均衡化、掩膜
    文章目录OpenCV高阶操作一、上、下采样1.上采样2.下采样3.恢复原图二、直方图1.plt.hist()绘图2.cv2.calcHist()绘图三、mask掩膜1.原图2.创建黑白图像3.掩膜4.绘制曲线图四、直方图均衡化1.直方图均衡化2.自适应直方图均衡化(局部直方图处理)总结......
  • 音频播放器
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>AudioPlayer</title>......
  • 孙怡带你深度学习(1)--神经网络
    文章目录深度学习神经网络1.感知器2.多层感知器偏置3.神经网络的构造4.模型训练损失函数总结深度学习深度学习(DL,DeepLearning)是机器学习(ML,MachineLearning)领域中一个新的研究方向。从上方的内容包含结果,我们可以知道,在学习深度学习之前,我们还需要......
  • 示例 28: 联系我们页面
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>ContactUs</title>......
  • Vue3.5+ 侦听器的3个更新
    你好同学,我是沐爸,欢迎点赞、收藏、评论和关注。在Vue3.5+中,对于侦听器的更新有以下几个方面:暂停/恢复侦听器、副作用清理/onWatcherCleanup和deep遍历深度,如果对此熟悉可以直接划走了,如果没有划走就一起看看吧。暂停/恢复侦听器在Vue3.5之前,watch和watchEffect有......
  • 升级数据飞轮:数据中台如何助力企业实现数据价值最大化
    #有了数据中台,是否需要升级到数据飞轮?需要怎么做?#这个话题中提到了两个问题。问题一:分别是有了数据中台,是否需要升级到数据飞轮?问题二:以及需要怎么做?以我个人的经验,从技术层面来看,第一个问题我的答案是有必要,下面我从三个方面来说明我的理由。第一点,数据中台和数据飞轮的关系。数据......
  • Android13 屏蔽ANR和Crash弹窗
    前言Android系统在应用发生Crash/ANR的时候,总会弹出一个提示对话框,但是现在部分客户不想要这样的对话框,要求移除一、ApplicationCrash表现:程序崩溃或闪退,界面上通常会出现“应用已停止运行”的提示。常见原因(Java异常):错误类型详细描述NullPointerException尝试在需要......