使用PyTorch的基本流程:
-
数据准备:通过make_regression生成回归数据,使用
TensorDataset
和DataLoader
来封装数据。 -
模型定义:使用
nn.Module
或内置层(如nn.Linear
)来定义模型结构。 -
损失函数和优化器:定义用于衡量误差的损失函数和用于优化参数的优化器。案例使用均方误差作为损失函数,用随机梯度下降法优化模型参数。
-
训练过程:通过前向传播计算预测值,使用损失函数计算损失值,反向传播计算梯度,最后更新模型参数,迭代训练模型。
-
评估模型:在测试集上评估模型的性能。
-
可视化结果:绘制损失变化曲线和模型预测结果与真实数据的对比,帮助理解模型的训练效果。
以线性回归案例来讲解:
# • 使用PyTorch的基本流程:
# 1. 数据准备:通过make_regression生成回归数据,
#. 并使用TensorDataset和DataLoader封装数据,以支持批量训练。
# 2. 定义模型:使用nn.Linear定义一个线性模型,输入输出均为1。
# 3. 损失函数和优化器:使用均方误差作为损失函数,用随机梯度下降法优化模型参数。
# 4. 训练过程:通过前向传播计算预测值,使用损失函数计算损失值,
#. 反向传播计算梯度,最后更新模型参数。
# 5. 可视化结果:绘制损失变化曲线和模型预测结果与真实数据的对比,
#. 帮助理解模型的训练效果。
# 导入相关模块
import torch
from torch.utils.data import TensorDataset, DataLoader # 构造数据集对象和数据加载器
from torch import nn, optim # nn模块包含神经网络相关功能,optim模块包含优化器
from sklearn.datasets import make_regression # 用于生成回归模型的数据集
import matplotlib.pyplot as plt
# 配置matplotlib参数以显示中文和负号
plt.rcParams['font.family'] = 'PingFang HK' # 设置mac 电脑的基本使用字体
plt.rcParams['axes.unicode_minus'] = False # 解决坐标轴负号显示问题
def create_dataset():
"""
创建用于线性回归的数据集,数据包括输入特征x和目标y。
返回值包括生成的数据x, y和真实系数coef。
"""
x, y, coef = make_regression(n_samples=100, # 样本数
n_features=1, # 特征数
noise=20, # 噪声等级
coef=True, # 返回回归系数
random_state=0, # 固定随机种子,保证结果一致性
bias=1.5) # 偏置值
# 转换为PyTorch张量类型
x = torch.tensor(x, dtype=torch.float32)
y = torch.tensor(y, dtype=torch.float32)
return x, y, coef
if __name__ == '__main__':
# 生成的数据
x, y, coef = create_dataset()
# 构造数据集对象,将x和y封装到TensorDataset中
dataset = TensorDataset(x, y)
# 使用DataLoader批量加载数据,batch_size表示每次训练使用16个样本,shuffle=True表示随机打乱数据
dataloader = DataLoader(dataset=dataset, batch_size=16, shuffle=True)
# 定义线性模型:输入特征为1(x),输出为1(y),即简单的线性回归模型
# • in_features=1:输入的特征数量是一维的,即一个特征。
# • out_features=1:输出也是一维的,即输出一个预测的值。
# 这个配置是典型的用于简单线性回归的模型,因为我们只需要输入一个特征并输出一个预测结果。
model = nn.Linear(in_features=1, out_features=1)
# 定义损失函数为均方误差MSE,用于计算模型预测与真实值的差异
criterion = nn.MSELoss()
# 使用随机梯度下降(SGD)优化器,学习率为0.01
# • optim.SGD:创建了一个随机梯度下降优化器,用来调整模型的参数。
# SGD 是 Stochastic Gradient Descent(随机梯度下降) 的缩写。它是一种常用的优化算法。简单来说,梯度下降是一种通过计算损失函数的梯度来逐步优化模型参数的方法。
# • model.parameters():告诉优化器要更新模型中的哪些参数。
# model.parameters() 返回的是模型中的可训练参数,即模型的权重和偏置。权重(weight):用来对输入数据进行线性变换的参数。偏置(bias):模型中的偏置项,用于调整输出。
# • lr=0.01:定义了学习率,表示每次参数更新时沿梯度的步长大小。
# lr 是 learning rate(学习率) 的缩写。学习率是优化器中的一个重要超参数,它控制每次更新时,模型参数的变化幅度。
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 定义训练轮数(epochs)
num_epochs = 100
# 用于存储每个训练轮次epoch的平均损失值
loss_per_epoch = []
# 开始训练过程
for epoch in range(num_epochs):
total_loss = 0.0 # 每轮训练的总损失
total_samples = 0 # 总样本数
# 迭代每个批次的数据
for batch_x, batch_y in dataloader:
# 前向传播:将输入数据通过模型得到预测值
predictions = model(batch_x)
# 计算损失值(均方误差):预测值,真实值
# batch_y.view(-1, 1) 将目标值调整为 [N, 1] 的形状,以便和 predictions 匹配。
loss = criterion(predictions, batch_y.view(-1, 1))
# 梯度清零,避免累积
optimizer.zero_grad()
# 反向传播计算梯度
loss.backward()
# 优化模型参数
optimizer.step()
# 累积损失和样本数
total_loss += loss.item()
total_samples += len(batch_x)
# 计算平均损失并保存
avg_loss = total_loss / total_samples
loss_per_epoch.append(avg_loss)
# 绘制损失函数随着训练轮数的变化曲线
plt.plot(range(num_epochs), loss_per_epoch, label='训练损失')
plt.title('损失函数变化曲线')
plt.xlabel('Epoch')
plt.ylabel('平均损失')
plt.grid(True)
plt.legend()
plt.show()
# 绘制真实的线性回归结果和模型预测结果的比较
plt.scatter(x, y, label='数据点') # 原始数据点
# 使用模型预测的线性回归曲线
# 在x轴上生成连续的点
x_line = torch.linspace(x.min(), x.max(), 1000).view(-1, 1)
y_pred = model(x_line).detach() # 使用模型预测并脱离计算图
plt.plot(x_line, y_pred, label='模型预测', color='r')
# 将 coef 转换为 PyTorch 张量,避免类型冲突
coef_tensor = torch.tensor(coef, dtype=torch.float32)
# 绘制真实的线性回归曲线
y_true = coef_tensor * x_line + 1.5 # 真实的线性回归直线
plt.plot(x_line, y_true, label='真实直线', color='g')
plt.title('真实直线与模型预测对比')
plt.xlabel('x')
plt.ylabel('y')
plt.grid(True)
plt.legend()
plt.show()
# 定义训练轮数(epochs)为10次的时候 num_epochs = 10
# 定义训练轮数(epochs)为100次的时候 num_epochs = 100,可见和真实值拟合更好了。
梯度的趋势,也是越来越小的趋势,所以证明我们拟合的还不错。上面就是我们通过线性回归的案例来讲解 pytorch 的基本使用过程。
我们总结下:
使用 PyTorch 的基本流程:
-
数据准备:
-
通常你需要将数据转换为 PyTorch 张量。对于小数据集,可以使用手动创建的张量,对于大数据集,
-
可以使用
torch.utils.data.Dataset
和torch.utils.data.DataLoader
来进行批量加载。 -
例如,可以使用
make_regression
或make_classification
来生成用于回归或分类任务的测试数据集,并将其转换为张量。
from sklearn.datasets import make_regression import torch # 生成样本数据 x, y = make_regression(n_samples=100, n_features=1, noise=20) x = torch.tensor(x, dtype=torch.float32) y = torch.tensor(y, dtype=torch.float32)
-
-
构建数据集和数据加载器:
-
使用
TensorDataset
和DataLoader
来封装数据并支持批量训练。DataLoader
可以帮助你随机打乱数据,并在每次训练时提供一部分样本。
from torch.utils.data import TensorDataset, DataLoader # 封装数据 dataset = TensorDataset(x, y) dataloader = DataLoader(dataset, batch_size=16, shuffle=True)
-
-
定义模型:
-
你可以通过继承
torch.nn.Module
或使用内置的torch.nn.Linear
等层来构建你的模型。模型的forward
方法负责定义前向传播的过程。
import torch.nn as nn # 定义线性模型,只有一个x, 一个y 的模型 model = nn.Linear(in_features=1, out_features=1)
-
-
定义损失函数和优化器:
-
损失函数用于衡量模型的预测值与真实值之间的差距,PyTorch 提供了许多常用的损失函数,例如
nn.MSELoss()
(用于回归),nn.CrossEntropyLoss()
(用于分类)。 -
优化器用于根据损失值来调整模型的参数。常见的优化器有
optim.SGD()
和optim.Adam()
等。
import torch.optim as optim # 定义损失函数和优化器 criterion = nn.MSELoss() # 均方误差损失函数 optimizer = optim.SGD(model.parameters(), lr=0.01) # 随机梯度下降
-
-
训练过程:
-
训练模型通常包括以下几个步骤:
-
前向传播:将输入数据传入模型,计算预测值。
-
计算损失:使用损失函数计算预测值与真实值之间的差距。
-
反向传播:调用
loss.backward()
来计算梯度。 -
更新参数:使用优化器的
optimizer.step()
更新模型参数。 -
梯度清零:使用
optimizer.zero_grad()
清除上一轮迭代的梯度。
-
# 定义训练轮数 num_epochs = 100 for epoch in range(num_epochs): total_loss = 0.0 for batch_x, batch_y in dataloader: # 前向传播 predictions = model(batch_x) # 计算损失 loss = criterion(predictions, batch_y.view(-1, 1)) # 梯度清零 optimizer.zero_grad() # 反向传播 loss.backward() # 更新参数 optimizer.step() # 累积损失 total_loss += loss.item() print(f'Epoch {epoch+1}, Loss: {total_loss}')
-
-
评估模型:
-
在模型训练完成后,通常会使用验证集或测试集来评估模型的性能。你可以通过在训练结束后使用模型进行预测,并计算测试数据上的损失来进行评估。
model.eval() # 切换到评估模式 with torch.no_grad(): # 禁止计算梯度 predictions = model(x_test) # x_test 是测试数据 test_loss = criterion(predictions, y_test) print(f'Test Loss: {test_loss.item()}')
-
-
可视化训练结果:
-
通常我们会绘制损失函数随训练轮次变化的曲线,以观察模型是否在收敛。
-
你还可以将模型的预测结果与真实数据进行对比,进一步评估模型的性能。
import matplotlib.pyplot as plt plt.plot(range(num_epochs), loss_per_epoch) plt.title('训练损失变化') plt.xlabel('Epochs') plt.ylabel('Loss') plt.show()
-
总结:
-
数据准备:使用
TensorDataset
和DataLoader
来封装数据。 -
模型定义:使用
nn.Module
或内置层(如nn.Linear
)来定义模型结构。 -
损失函数和优化器:定义用于衡量误差的损失函数和用于优化参数的优化器。
-
训练过程:通过前向传播、反向传播和参数更新,迭代训练模型。
-
评估模型:在测试集上评估模型的性能。
-
可视化结果:绘制损失变化曲线和预测结果,以分析模型表现。