深度学习实战(基于pytroch)系列(五)线性回归的pytorch实现

线性回归的pytorch实现

实践中,我们通常可以用比上一节深度学习实战(基于pytroch)系列(四)更简洁的代码来实现同样的模型。在本节中,我们将介绍如何使用pytorch提供的接口更方便地实现线性回归的训练。

导包及设置随机种子

python 复制代码
import torch
import torch.nn as nn
import torch.utils.data as data
import numpy as np

# 设置随机种子以确保结果可重现
torch.manual_seed(42)

生成数据

生成与上一节深度学习实战(基于pytroch)系列(四)中相同的数据集。其中features是训练数据特征,labels是标签。

python 复制代码
num_inputs = 2
num_examples = 1000
true_w = [2, -3.4]
true_b = 4.2

features = torch.randn(num_examples, num_inputs)

labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
labels += torch.randn(labels.shape) * 0.01

print("特征形状:", features.shape)
print("标签形状:", labels.shape)

读取数据

pytorch提供了torch.utils.data来读取数据,其中TensorDatasetDataset 的具体实现类用来处理张量数据。比如tensordataset[i] 返回了一个元组 (features[i], labels[i]) 。Dataset可以支持自定义实现来处理非张量数据,比如图像音频等数据,自定义的时候需要实现 lengetitem 方法。

其中DataLoader负责从 Dataset 中按指定规则抽取数据,并组合成批次供模型训练。它实现了:批处理、打乱、并行加载这三个核心需求。

python 复制代码
batch_size = 10

#创建数据集和数据加载器
dataset = data.TensorDataset(features, labels)
data_iter = data.DataLoader(dataset, batch_size, shuffle=True)

#读取并打印第一个小批量数据样本
for X, y in data_iter:
    print("第一个批次的特征:", X)
    print("第一个批次的标签:", y)
    break

定义模型

在上一节实现中,我们需要定义模型参数,并使用它们一步步描述模型是怎样计算的。当模型结构变得更复杂时,这些步骤将变得更繁琐。其实,pytroch提供了大量预定义的层,这使我们只需关注使用哪些层来构造模型。

首先,导入nn模块。实际上,"nn"是neural networks(神经网络)的缩写。顾名思义,该模块定义了大量神经网络的层。我们先定义一个模型变量net,它是一个Sequential实例。Sequential实例可以看作是一个串联各个层的容器。在构造模型时,我们在该容器中依次添加层。当给定输入数据时,容器中的每一层将依次计算并将输出作为下一层的输入。

python 复制代码
#使用Sequential容器定义模型
net = nn.Sequential(
    nn.Linear(num_inputs, 1)  # 全连接层,对应Gluon的Dense层
)

print("\n模型结构:")
print(net)

初始化模型参数

在使用net前,我们需要初始化模型参数,如线性回归模型中的权重和偏差。我们从nn模块导入init模块。该模块提供了模型参数初始化的各种方法。这里的initinitializer的缩写形式。我们通过`init.Normal_(m.weight, mean=0, std=0.01) 指定权重参数每个元素将在初始化时随机采样于均值为0、标准差为0.01的正态分布。偏差参数默认会初始化为零。

python 复制代码
#手动初始化权重和偏置
def init_weights(m):
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight, mean=0, std=0.01)  # 权重初始化
        nn.init.constant_(m.bias, 0)  # 偏置初始化为0

net.apply(init_weights)

print("\n初始化后的权重:", net[0].weight.data)
print("初始化后的偏置:", net[0].bias.data)

apply() 方法是PyTorch中一个非常重要的函数,它会递归地对网络中的每个子模块(包括所有层)应用指定的函数。它会遍历 net 中的每一个层,对每个层调用 init_weights 函数
normal_ 后缀的下划线表示原地操作(in-place)

定义损失函数

nn模块定义了各种损失函数,可以直接调用nn模块里面的损失函数

python 复制代码
loss = nn.MSELoss()  # 平方损失

定义优化算法

同样,我们也无须实现小批量随机梯度下降。直接调用torch.optim.SGD可以实现小批量随机梯度下降,指定学习率为0.03。

python 复制代码
learning_rate = 0.03
trainer = torch.optim.SGD(net.parameters(), lr=learning_rate)  # 随机梯度下降

训练模型

python 复制代码
num_epochs = 3

for epoch in range(1, num_epochs + 1):
    total_loss = 0
    batch_count = 0
    
    for X, y in data_iter:
        # 前向传播
        y_hat = net(X)
        l = loss(y_hat, y.view(-1, 1))  # 调整y的形状以匹配输出
        
        # 反向传播
        trainer.zero_grad()  # 梯度清零
        l.backward()         # 反向传播计算梯度
        trainer.step()       # 更新参数
         
    # 每个epoch结束后计算在整个数据集上的损失
    with torch.no_grad():
        entire_loss = loss(net(features), labels.view(-1, 1))
    
    print(f'epoch {epoch}, loss: {entire_loss.mean().item():.6f}')

item():将张量转换为Python数值

比较学到的参数和真实参数

python 复制代码
#获取学到的参数
dense = net[0]  # 第一层(也是唯一的一层)
learned_w = dense.weight.data
learned_b = dense.bias.data

print("\n参数比较:")
print("真实权重:", true_w)
print("学到的权重:", learned_w.numpy()[0])
print("真实偏置:", true_b)
print("学到的偏置:", learned_b.item())

输出结果

参数比较: 真实权重: [2, -3.4]

学到的权重: [ 2.0007157 -3.4000518]

真实偏置: 4.2

学到的偏置: 4.199595928192139

可以看到学到的参数和真实的参数非常接近

相关推荐
算法与编程之美2 小时前
探究pytorch中多个卷积层和全连接层的输出方法
人工智能·pytorch·深度学习·神经网络·cnn
钅日 勿 XiName3 小时前
一小时速通Pytorch之自动梯度(Autograd)和计算图(Computational Graph)(二)
人工智能·pytorch·python
化作星辰3 小时前
深度学习_神经网络中最常用的学习率优化算法
深度学习·神经网络·学习
PixelMind4 小时前
【IQA技术专题】 基于多模态大模型的IQA Benchmark:Q-BENCH
图像处理·深度学习·lmm·iqa
cyyt5 小时前
深度学习周报(11.3~11.9)
人工智能·深度学习
雍凉明月夜5 小时前
Ⅱ人工智能学习之深度学习(deep-learning)概述
人工智能·深度学习·学习
Nina_7176 小时前
pytorch核心组件以及流程
人工智能·pytorch·python
能来帮帮蒟蒻吗6 小时前
深度学习(3)—— 评估指标
人工智能·深度学习
一只小风华~6 小时前
HarmonyOS:ArkTS 页导航
深度学习·华为·harmonyos·鸿蒙