Skip to content

PyTorch - 线性回归

线性回归(Linear regression)是一种基础的监督机器学习(supervised machine learning)算法,用于模拟因变量(目标变量,target)与一个或多个自变量(预测变量或特征,predictors or features)之间的线性关系。在其最简单的形式(简单线性回归)中,我们尝试找到穿过数据点集的最佳拟合直线。

这种关系通过以下方程建模:

Y = wX + b

其中 Y 是预测的目标值,X 是输入特征,w 是权重(直线的斜率),b 是偏置(y 轴截距)。我们的目标是找到最优的 w 和 b 值,以最小化预测的 Y 与实际目标值之间的差异。

这涉及两个关键概念:

  • 成本函数(Cost Function):衡量模型表现好坏的函数。对于线性回归,通常使用均方误差(Mean Squared Error, MSE)。
  • 梯度下降(Gradient Descent):一种优化算法,通过迭代调整模型参数(w 和 b)沿着成本函数的梯度相反方向移动,从而最小化成本函数。

对于方程 Y = wX + b:

  • ‘w’(权重或斜率)的值表示当 X 变化一个单位时,Y 变化多少。
  • ‘b’(偏置或 y 轴截距)的值表示当 X 为 0 时,Y 的值。
  • 训练的目标是找到 ‘w’ 和 ‘b’,使得直线 Y = wX + b 能够最好地拟合训练数据。

从图形上看,线性回归试图找到一条直线,使其尽可能紧密地穿过二维平面上绘制的所有数据点(对于简单线性回归)。

让我们使用 PyTorch 实现线性回归:

我们将需要 torch 用于 PyTorch 功能,numpy 用于创建样本数据,以及 matplotlib 用于绘图。

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
# For a slightly nicer plot style (optional)
# import seaborn as sns
# sns.set_style(style='whitegrid')
# plt.rcParams["patch.force_edgecolor"] = True

让我们创建一些具有已知线性关系并添加一些噪声的合成数据。

# Define true parameters
# 定义真实参数
true_w = 2.0
true_b = 3.0
num_samples = 256
# Generate random x values
# 生成随机 x 值
X_numpy = np.random.rand(num_samples, 1).astype(np.float32)
# Generate y values based on y = w*x + b + noise
# 根据 y = w*x + b + 噪声 生成 y 值
noise = np.random.randn(num_samples, 1).astype(np.float32) * 0.2 # Smaller noise
y_numpy = X_numpy * true_w + true_b + noise
# Convert NumPy arrays to PyTorch tensors
# 将 NumPy 数组转换为 PyTorch 张量
X_tensor = torch.from_numpy(X_numpy)
y_tensor = torch.from_numpy(y_numpy)
# Optional: Plot the raw data
# 可选:绘制原始数据
# plt.figure(figsize=(8, 5))
# plt.scatter(X_numpy, y_numpy, label='Original data', s=10)
# plt.xlabel('x')
# plt.ylabel('y')
# plt.legend()
# plt.show()

步骤 3:使用 PyTorch 实现线性回归

Section titled “步骤 3:使用 PyTorch 实现线性回归”

我们将使用 torch.nn.Module 定义一个简单的线性回归模型。

# Define the model
# 定义模型
class LinearRegressionModel(nn.Module):
def __init__(self, input_dim, output_dim):
super().__init__() # Modern Python 3 super() call
# 现代 Python 3 的 super() 调用
self.linear = nn.Linear(input_dim, output_dim)
def forward(self, x):
out = self.linear(x)
return out
# Model parameters
# 模型参数
input_dim = 1 # Single feature
# 单个特征
output_dim = 1 # Single output value
# 单个输出值
# Instantiate the model
# 实例化模型
model = LinearRegressionModel(input_dim, output_dim)
# Define loss function (Mean Squared Error)
# 定义损失函数 (均方误差)
criterion = nn.MSELoss()
# Define optimizer (Stochastic Gradient Descent)
# 定义优化器 (随机梯度下降)
learning_rate = 0.1
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
# Training loop
# 训练循环
epochs = 100
for epoch in range(epochs):
# Forward pass: Compute predicted y by passing x to the model
# 前向传播:将 x 输入模型计算预测 y 值
predictions = model(X_tensor)
# Compute loss
# 计算损失
loss = criterion(predictions, y_tensor)
# Backward pass: Zero gradients, perform backpropagation, and update weights
# 反向传播:清零梯度,执行反向传播,更新权重
optimizer.zero_grad() # Clear previous gradients
# 清除之前的梯度
loss.backward() # Compute gradients of loss w.r.t. model parameters
# 计算损失相对于模型参数的梯度
optimizer.step() # Update model parameters
# 更新模型参数
if (epoch + 1) % 10 == 0:
# Get current learned parameters (w, b)
# 获取当前学习到的参数 (w, b)
# .item() gets the value as a Python number from a single-element tensor
# .item() 从单个元素张量获取 Python 数字值
# .data gives access to the tensor without gradient tracking
# .data 提供对张量的访问,不跟踪梯度
learned_w = model.linear.weight.data.item()
learned_b = model.linear.bias.data.item()
print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}, Learned w: {learned_w:.3f}, Learned b: {learned_b:.3f}')
# Plot the results after training
# 训练后绘制结果
def plot_fit(title="Fitted Line"):
plt.figure(figsize=(10, 6))
plt.title(title)
plt.scatter(X_numpy, y_numpy, s=15, label='Original data')
# Get predictions from the trained model
# 从训练好的模型获取预测值
with torch.no_grad(): # Disable gradient calculation for inference
# 推断时禁用梯度计算
predicted_values = model(X_tensor).numpy()
plt.plot(X_numpy, predicted_values, color='red', label='Fitted line')
plt.xlabel('x (input)')
plt.ylabel('y (target/predicted)')
plt.legend()
plt.grid(True)
plt.show()
plot_fit('Linear Regression Fit After Training')
# You can also inspect the final learned parameters:
# 你也可以查看最终学习到的参数:
final_w = model.linear.weight.item()
final_b = model.linear.bias.item()
print(f'\nTrue w: {true_w}, True b: {true_b}')
print(f'Learned w: {final_w:.4f}, Learned b: {final_b:.4f}')

输出将首先在训练过程中按间隔打印损失值和学习到的参数。最后,它将显示一个包含原始数据点和 PyTorch 模型拟合的回归线的图。学习到的 ‘w’ 和 ‘b’ 应该接近用于生成数据的真实值 true_w 和 true_b。