当前位置: 首页 > article >正文

【第十四周】PyTorch深度学习实践1

目录

  • 摘要
  • Abstract
  • 1.反向传播
  • 2.线性回归
    • 2.1.准备数据集
    • 2.2.设计模型
    • 2.3.定义损失函数和优化器
    • 2.4.模型训练
  • 3.逻辑回归
  • 4.处理多维特征的输入
  • 5.加载数据集
    • 5.1.导入必要的库
    • 5.2.准备数据集
    • 5.3.定义模型
    • 5.4.构建损失函数和优化器
    • 5.5.训练模型
  • 总结

摘要

本周主要通过B站刘二大人的视频对 PyTorch 进行实践学习,了解了PyTorch 中各个常用的类以及方法,学习了搭建神经网络的四个步骤,为后面手动复现模型提供了实践基础。其中,最重要的是学习到了看文档的能力,对于新学习到的类和方法能够通过查询文档去理解用法和作用。

Abstract

This week, I mainly focused on practical learning with PyTorch, understanding the various commonly used classes and methods within it. I learned the four steps to building a neural network, which provided a practical foundation for manually reproducing models in the future. Most importantly, I developed the ability to read documentation, allowing me to understand the usage and function of newly learned classes and methods by consulting the documentation.

本周学习内容来自于《PyTorch深度学习实践》完结合集 1~8课

参考资料来自于PyTorch 英文文档

1.反向传播

在这里插入图片描述
对于简单的线性模型可以通过解析式来求对参数的导数。

在这里插入图片描述
一个复杂的神经网络中含有成千上百个参数,分别对这些参数求解析是一个很繁重的任务,因此我们需要一个新的办法——反向传播算法

在这里插入图片描述
线性函数叠加之后总是可以化简成 W ⋅ X + b W·X+b WX+b的形式,这样子多层叠加就没有意义了,所以要在每一层的结果处加上一个非线性函数。

在这里插入图片描述
前馈过程求解中间值和局部导数,反向传播过程求解对各个参数的偏导。

在这里插入图片描述
PyTorch中 Tensor(张量)包含两个成员,一个是保存参数的 Data,一个是保存导数的 Grad。同样这两个成员也是 Tensor。

torch.Tensor 和 torch.tensor的区别

代码如下:

import torch

x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

# 创建一个 Tensor 类型,方便求梯度
w = torch.tensor([1.0])    
w.requires_grad = True      

# 前向传播
def forward(x):
    return x * w

# 计算损失,创建计算图
def loss(x, y):
    y_pred = forward(x)
    return (y_pred - y) ** 2


print("predict before training", 4, forward(4).item())

for epoch in range(100):
    for x, y in zip(x_data, y_data):   # 选择一个样本更新梯度值
        l = loss(x, y)
        l.backward()
        print('\tgrad:', x, y, w.grad.item())
        w.data = w.data - 0.01 * w.grad.data

        # 每次更新完梯度要清除梯度
        w.grad.data.zero_()

    print("progress:", epoch, l.item())

print("predict after training", 4, forward(4).item())

结果如下:

在这里插入图片描述

2.线性回归

在这里插入图片描述
神经网络模型的搭建遵循上图的四个流程。

2.1.准备数据集

x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

2.2.设计模型

在这里插入图片描述

定义 LinearModel 类

class LinearModel(torch.nn.Module):

这里定义了一个名为 LinearModel 的类,它继承自 torch.nn.Module。torch.nn.Module 是所有神经网络模块的基类,包含了一些有用的属性和方法,用于管理模型参数、前向传播等。

def __init__(self):
    super(LinearModel, self).__init__()
    self.linear = torch.nn.Linear(1, 1)
  • _init_ 方法是 Python 中类的构造函数,当创建类的实例时会自动调用。
  • super(LinearModel, self).init() 调用了父类 torch.nn.Module 的构造函数,这是必要的步骤,以确保父类能够正确地初始化。
  • self.linear = torch.nn.Linear(1, 1) 创建了一个线性层(全连接层),输入维度为1,输出维度也为1。这意味着该模型将接受一个标量作为输入,并产生一个标量作为输出。

前向传播

def forward(self, x):
    y_pred = self.linear(x)
    return y_pred
  • forward 方法定义了模型的前向传播逻辑,即如何从输入数据 x 计算出输出 y_pred。
  • self.linear(x) 使用之前定义的线性层对输入 x 进行变换。
  • return y_pred 返回前向传播的结果,即预测值 y_pred。

2.3.定义损失函数和优化器

在这里插入图片描述
定义损失和优化器

criterion = torch.nn.MSELoss(size_average=False)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

model.parameters() 返回模型中所有需要优化的参数。

2.4.模型训练

在这里插入图片描述

for epoch in range(100):
    y_pred = model(x_data)
    loss = criterion(y_pred, y_data)
    print(epoch, loss.item())
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

print('w = ', model.linear.weight.item())
print('b = ', model.linear.bias.item())

x_test = torch.tensor([[4.0]])
y_test = model(x_test)
print('y_pred = ', y_test.data)

结果如下:
在这里插入图片描述

3.逻辑回归

在这里插入图片描述
在这里插入图片描述
为什么交叉熵可以衡量两个分布的差异呢?
交叉熵 H ( P , Q ) H(P,Q) H(P,Q) 可以理解为使用概率分布 Q Q Q编码来自概率分布P的数据所需的平均比特数。具体来说:如果 P ( x ) P(x) P(x) Q ( x ) Q(x) Q(x) 完全相同,即 P ( x ) = Q ( x ) P(x)=Q(x) P(x)=Q(x),那么 H ( P , Q ) H(P,Q) H(P,Q) 等于 H ( P ) H(P) H(P),也就是真实分布的熵。如果 P ( x ) P(x) P(x) Q ( x ) Q(x) Q(x) 不同,那么 H ( P , Q ) H(P,Q) H(P,Q) 会大于 H ( P ) H(P) H(P),因为使用不准确的概率分布Q来编码数据会导致更多的冗余信息,从而需要更多的比特数。

在这里插入图片描述

代码如下:

import torch
import torch.nn.functional as F

# prepare dataset
x_data = torch.Tensor([[1.0], [2.0], [3.0]])
y_data = torch.Tensor([[0], [0], [1]])


# design model using class
class LogisticRegressionModel(torch.nn.Module):
    def __init__(self):
        super(LogisticRegressionModel, self).__init__()
        self.linear = torch.nn.Linear(1, 1)

    def forward(self, x):
        y_pred = F.sigmoid(self.linear(x))
        return y_pred


model = LogisticRegressionModel()

# construct loss and optimizer
# 默认情况下,loss会基于element平均,如果size_average=False的话,loss会被累加。
criterion = torch.nn.BCELoss(size_average=False)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

# training cycle forward, backward, update
for epoch in range(1000):
    y_pred = model(x_data)
    loss = criterion(y_pred, y_data)
    print(epoch, loss.item())

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

print('w = ', model.linear.weight.item())
print('b = ', model.linear.bias.item())

x_test = torch.Tensor([[4.0]])
y_test = model(x_test)
print('y_pred = ', y_test.data)

结果如下:

在这里插入图片描述

4.处理多维特征的输入

在这里插入图片描述

上图为预测一个人在一年之后糖尿病病情加重概率的例子,这时每个样本会有八个不同的特征,通过八个不同的特征来预测是否病情会加重。
在这里插入图片描述
对于多维的特征输入我们需要把每一个特征x乘以相应的权重。在进行逻辑回归时,把每一个维度的x乘相应的权值的和加上一个偏置量。然后再把每个样本的式子写成矩阵乘法的形式。

import numpy as np
import torch
import matplotlib.pyplot as plt
 
# prepare dataset
xy = np.loadtxt('diabetes.csv', delimiter=',', dtype=np.float32)
x_data = torch.from_numpy(xy[:, :-1]) # 第一个‘:’是指读取所有行,第二个‘:’是指从第一列开始,最后一列不要
y_data = torch.from_numpy(xy[:, [-1]]) # [-1] 最后得到的是个矩阵
 
# design model using class
 
 
class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = torch.nn.Linear(8, 6) # 输入数据x的特征是8维,x有8个特征
        self.linear2 = torch.nn.Linear(6, 4)
        self.linear3 = torch.nn.Linear(4, 1)
        self.sigmoid = torch.nn.Sigmoid() # 将其看作是网络的一层,而不是简单的函数使用
 
    def forward(self, x):
        x = self.sigmoid(self.linear1(x))
        x = self.sigmoid(self.linear2(x))
        x = self.sigmoid(self.linear3(x)) # y hat
        return x
 
 
model = Model()
 
# construct loss and optimizer
# criterion = torch.nn.BCELoss(size_average = True)
criterion = torch.nn.BCELoss(reduction='mean')  
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
 
epoch_list = []
loss_list = []
# training cycle forward, backward, update
for epoch in range(100):
    y_pred = model(x_data)
    loss = criterion(y_pred, y_data)
    print(epoch, loss.item())
    epoch_list.append(epoch)
    loss_list.append(loss.item())
 
    optimizer.zero_grad()
    loss.backward()
 
    optimizer.step()
 
 
plt.plot(epoch_list, loss_list)
plt.ylabel('loss')
plt.xlabel('epoch')
plt.show()

torch.sigmoid、torch.nn.Sigmoid和torch.nn.functional.sigmoid的区别

结果如下:
在这里插入图片描述

在这里插入图片描述

5.加载数据集

5.1.导入必要的库

import torch
import numpy as np
from torch.utils.data import Dataset
from torch.utils.data import DataLoader

5.2.准备数据集

class DiabetesDataset(Dataset):
    def __init__(self, filepath):
        xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32)
        self.len = xy.shape[0]
        self.x_data = torch.from_numpy(xy[:, :-1])
        self.y_data = torch.from_numpy(xy[:, [-1]])

    def __getitem__(self, index):
        return self.x_data[index], self.y_data[index]

    def __len__(self):
        return self.len
  • DiabetesDataset 继承自 Dataset 类,其中 Dataset 是抽象类,不可被实例化。
  • _init_ 方法:
    读取CSV文件并将其转换为NumPy数组。
    self.len 存储数据集的样本数量。
    self.x_data存储特征数据,self.y_data 存储标签数据。
  • _getitem_ 方法:
    返回指定索引处的特征和标签。
  • _len_ 方法:
    返回数据集的长度(样本数量)。

创建数据加载器

dataset = DiabetesDataset('diabetes.csv')
train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=0)

5.3.定义模型

class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = torch.nn.Linear(8, 6)
        self.linear2 = torch.nn.Linear(6, 4)
        self.linear3 = torch.nn.Linear(4, 1)
        self.sigmoid = torch.nn.Sigmoid()

    def forward(self, x):
        x = self.sigmoid(self.linear1(x))
        x = self.sigmoid(self.linear2(x))
        x = self.sigmoid(self.linear3(x))
        return x
  • Model 继承自 torch.nn.Module 类。

  • _init_ 方法:
    定义了三个全连接层(Linear)和一个Sigmoid激活函数。

  • forward 方法:
    定义了前向传播过程,输入数据依次通过三个全连接层和Sigmoid激活函数。

5.4.构建损失函数和优化器

criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

5.5.训练模型

if __name__ == '__main__':
    for epoch in range(100):
        for i, data in enumerate(train_loader, 0):
            inputs, labels = data
            y_pred = model(inputs)
            loss = criterion(y_pred, labels)
            print(epoch, i, loss.item())

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

运行结果和上一小节类似,这一小节主要学习的是 dataloader 的具体作用和理解 epoch、batch 和 iteration 之间的关系。

总结

构建一个通用的神经网络模型是一个系统而精细的过程,大致可以分为四个关键步骤。首先,准备数据集是整个流程的基石,这一步骤不仅包括收集所需的数据,还需要对数据进行清洗、预处理以及划分训练集与测试集,确保数据的质量和适用性。接着,模型搭建阶段需要根据任务需求选择合适的网络架构,如卷积神经网络(CNN)用于图像识别,循环神经网络(RNN)适合序列数据处理等,并确定每一层的具体参数。第三步,定义损失函数和选择优化器是调整模型以达到最佳性能的关键,损失函数衡量预测值与真实值之间的差异,而优化器则通过反向传播算法最小化这种差异。最后,训练模型涉及迭代地将数据输入网络中,不断调整权重直至模型在训练集上表现良好,并通过验证集或测试集评估其泛化能力。掌握这一系列流程,就可以自己动手搭建绝大多数神经网络。


http://www.kler.cn/a/324787.html

相关文章:

  • 购物车demo全代码-对接支付宝沙箱环境
  • PyAEDT:Ansys Electronics Desktop API 简介
  • 效率工具-tig的使用
  • 零基础利用实战项目学会Pytorch
  • 移除元素(leetcode 27)
  • kafka消费者出现频繁Rebalance
  • 浅说差分算法(上)
  • excel-VBA知识点记录
  • 服务器数据恢复—SAN环境下LUN映射出错导致文件系统一致性出错的数据恢复案例
  • 物联网系统中OLED屏主流驱动方案详解
  • 每日OJ题_牛客_HJ108求最小公倍数_C++_Java
  • unixODBC编程(四)插入数据
  • 【js】Node.js的fs的使用方法
  • 长沙某公司.Net高级开发面试题
  • 【C语言零基础入门篇 - 15】:单链表
  • 甄选范文“论应用服务器基础软件”,软考高级论文,系统架构设计师论文
  • 静态路由和默认路由(实验)
  • 海滨体育馆管理系统:SpringBoot实现技巧与案例
  • 活动在线报名小程序源码系统 自主提交表单+创建表单 带完整的安装代码包以及搭建部署教程
  • LiveGBS流媒体平台GB/T28181功能-支持电子放大拉框放大直播视频拉框放大录像视频流拉框放大电子放大
  • 小阿轩yx-Ansible部署与应用基础
  • linux semaphore信号量操作
  • 基于nodejs+vue的农产品销售管理系统
  • 如何制作小程序商城
  • NLP任务的详细原理与步骤的详细讲解
  • 算法 求最大葫芦数