线性回归与优化算法
线性回归与优化算法
一、线性回归基础
线性回归是监督学习中最经典、最基础的模型之一,核心目标是学习一个线性映射关系,将输入特征映射到连续的输出标签。它广泛应用于房价预测、销量预估、气温预测等连续值预测场景,同时也是深度学习很多复杂模型的基础组件。
1.1 模型定义
单变量线性回归
假设输入特征只有1个(记为\(x\)),输出标签为\(y\),单变量线性回归的模型表达式为:
其中,\(\hat{y}\)是模型的预测值,\(w\)是权重参数,\(b\)是偏置参数,这两个是模型需要学习的参数。
多变量线性回归
当输入特征有\(n\)个(记为\(x_1, x_2, ..., x_n\))时,模型扩展为多变量线性回归:
为了方便矩阵运算,可将其表示为向量形式:
其中,\(\boldsymbol{w} = [w_1, w_2, ..., w_n]^T\)是权重向量,\(\boldsymbol{x} = [x_1, x_2, ..., x_n]^T\)是输入特征向量。
1.2 损失函数
为了衡量模型预测值\(\hat{y}\)与真实值\(y\)的差异,需要定义损失函数。线性回归中最常用的是平方损失函数(均方误差MSE),其定义为:
其中,\(m\)是样本数量,\(\hat{y}_i\)是第\(i\)个样本的预测值,\(y_i\)是第\(i\)个样本的真实值。模型学习的目标就是找到最优的\(w\)和\(b\),使得损失函数\(L(w, b)\)最小。
1.3 最小二乘原理
平方损失函数的最小化可以通过数学推导直接求解,即正规方程法。对损失函数\(L(w, b)\)分别关于\(w\)和\(b\)求偏导,并令偏导数为0,可得到最优参数的解析解:
其中,\(\boldsymbol{X}\)是\(m \times (n+1)\)的设计矩阵(每行对应一个样本,最后一列全为1以包含偏置\(b\)),\(\boldsymbol{y}\)是\(m \times 1\)的真实标签向量。
正规方程法的优点是无需迭代,直接得到最优解,但缺点是当特征维度\(n\)较大(如\(n>10000\))时,矩阵\(\boldsymbol{X}^T \boldsymbol{X}\)的逆计算复杂度极高(\(O(n^3)\)),此时不再适用。
二、优化算法核心
当正规方程法不适用时,需要通过迭代优化的方式逐步逼近最优参数,这也是深度学习中最常用的参数更新方式。核心思想是:沿着损失函数的梯度方向,不断调整参数,使得损失函数逐渐减小。
2.1 梯度下降(Gradient Descent, GD)
基本原理
梯度是损失函数对参数的偏导数向量,它指向损失函数增长最快的方向,因此沿着梯度的反方向更新参数,可以使损失函数快速减小。
对于参数向量\(\boldsymbol{\theta} = [w_1, w_2, ..., w_n, b]^T\),梯度下降的参数更新公式为:
其中,\(\eta\)是学习率(步长),控制每次参数更新的幅度;\(\nabla L(\boldsymbol{\theta})\)是损失函数关于\(\boldsymbol{\theta}\)的梯度。
三种梯度下降变体
| 类型 | 核心思想 | 优点 | 缺点 |
|---|---|---|---|
| 批量梯度下降(BGD) | 每次使用全部样本计算梯度 | 梯度估计准确,收敛稳定 | 数据量大时计算耗时,内存占用高 |
| 随机梯度下降(SGD) | 每次使用1个样本计算梯度 | 计算速度快,内存占用低 | 梯度波动大,收敛路径曲折 |
| 小批量梯度下降(MBGD) | 每次使用\(k\)个样本(mini-batch)计算梯度 | 兼顾速度与稳定性,是深度学习主流选择 | 需要调整批量大小\(k\) |
2.2 学习率的选择
学习率\(\eta\)是梯度下降的关键超参数:
- 学习率过大会导致参数震荡,甚至无法收敛;
- 学习率过小会导致收敛速度极慢,需要大量迭代次数。
实际应用中,通常选择0.001、0.01、0.1等常见值,或通过学习率调度策略(如学习率衰减)动态调整。
2.3 其他优化算法
动量(Momentum)
模拟物理中的动量概念,积累之前的梯度方向,加速收敛并减少震荡:
其中,\(\gamma\)是动量系数(通常取0.9),\(v_t\)是累计动量。
自适应学习率算法
- Adagrad:为不同参数分配不同学习率,适合稀疏数据;
- RMSProp:解决Adagrad学习率衰减过快的问题;
- Adam:结合动量和RMSProp的优点,自适应调整学习率,是目前最常用的优化算法之一。
三、代码实现(PyTorch)
下面基于PyTorch框架实现线性回归模型的训练与优化,包含数据生成、模型定义、训练过程和结果可视化。
3.1 环境准备
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt
3.2 生成模拟数据
# 生成多变量线性回归数据
np.random.seed(42)
torch.manual_seed(42)
# 样本数量
m = 1000
# 特征维度
n = 3
# 真实参数
true_w = torch.tensor([[2.5], [-1.8], [3.2]], dtype=torch.float32)
true_b = torch.tensor([4.7], dtype=torch.float32)
# 生成输入特征 X (m, n),服从正态分布
X = torch.randn(m, n, dtype=torch.float32)
# 生成真实标签 y = X @ true_w + true_b + 噪声
y = X @ true_w + true_b + 0.1 * torch.randn(m, 1, dtype=torch.float32)
3.3 定义线性回归模型
class LinearRegression(nn.Module):
def __init__(self, input_dim):
super(LinearRegression, self).__init__()
# 线性层:input_dim -> 1
self.linear = nn.Linear(input_dim, 1)
def forward(self, x):
# 前向传播:输入x -> 线性变换 -> 输出
return self.linear(x)
# 初始化模型
model = LinearRegression(input_dim=n)
3.4 定义损失函数和优化器
# 损失函数:均方误差
criterion = nn.MSELoss()
# 优化器:随机梯度下降(SGD)
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 可选:使用Adam优化器
# optimizer = optim.Adam(model.parameters(), lr=0.01)
3.5 模型训练
# 训练轮数
epochs = 100
# 批量大小
batch_size = 32
# 记录损失变化
losses = []
# 构建数据加载器
dataset = torch.utils.data.TensorDataset(X, y)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True)
for epoch in range(epochs):
model.train() # 训练模式
epoch_loss = 0.0
for batch_X, batch_y in dataloader:
# 1. 前向传播:计算预测值
outputs = model(batch_X)
# 2. 计算损失
loss = criterion(outputs, batch_y)
# 3. 反向传播:计算梯度
optimizer.zero_grad() # 清空之前的梯度
loss.backward() # 反向传播求梯度
# 4. 参数更新
optimizer.step()
# 累计批次损失
epoch_loss += loss.item() * batch_X.size(0)
# 计算本轮平均损失
avg_loss = epoch_loss / m
losses.append(avg_loss)
# 每10轮打印一次损失
if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch+1}/{epochs}], Loss: {avg_loss:.6f}')
3.6 结果分析
3.6.1 损失曲线可视化
plt.plot(range(epochs), losses)
plt.xlabel('Epoch')
plt.ylabel('MSE Loss')
plt.title('Training Loss Curve')
plt.show()
3.6.2 模型参数对比
# 输出学习到的参数
learned_w = model.linear.weight.data
learned_b = model.linear.bias.data
print(f'真实权重: {true_w.squeeze().numpy()}')
print(f'学习权重: {learned_w.squeeze().numpy()}')
print(f'真实偏置: {true_b.item()}')
print(f'学习偏置: {learned_b.item()}')
3.6.3 预测结果验证
model.eval() # 评估模式
with torch.no_grad(): # 禁用梯度计算
y_pred = model(X)
# 计算最终损失
final_loss = criterion(y_pred, y).item()
print(f'Final MSE Loss: {final_loss:.6f}')
# 可视化预测值与真实值(取第一个特征)
plt.scatter(X[:, 0].numpy(), y.numpy(), alpha=0.5, label='True Value')
plt.scatter(X[:, 0].numpy(), y_pred.numpy(), alpha=0.5, label='Predicted Value')
plt.xlabel('Feature 1')
plt.ylabel('Label')
plt.title('True vs Predicted Values')
plt.legend()
plt.show()
四、关键问题与优化技巧
4.1 特征缩放
梯度下降类算法对特征尺度敏感,若不同特征的数值范围差异较大(如年龄:0-100,收入:0-100000),会导致损失函数等高线呈椭圆形,收敛速度变慢。常用的特征缩放方法:
- 标准化:\(x' = \frac{x - \mu}{\sigma}\)(均值\(\mu\),标准差\(\sigma\))
- 归一化:\(x' = \frac{x - \min(x)}{\max(x) - \min(x)}\)(缩放到[0,1])
4.2 过拟合与正则化
当模型复杂度高于数据真实分布时,会出现过拟合(训练损失小,测试损失大)。线性回归中可通过L1正则化(Lasso) 或L2正则化(Ridge) 缓解:
- L2正则化损失:\(L(w, b) = \frac{1}{m}\sum_{i=1}^m (\hat{y}_i - y_i)^2 + \lambda \cdot \|\boldsymbol{w}\|^2\)
- PyTorch实现:在优化器中添加权重衰减(weight_decay)
optimizer = optim.SGD(model.parameters(), lr=0.01, weight_decay=0.001)
4.3 批量大小的选择
- 批量大小\(k\)过小:梯度估计方差大,收敛路径震荡,训练不稳定;
- 批量大小\(k\)过大:梯度估计准确,但计算效率低,内存占用高;
- 常用批量大小:32、64、128(需根据GPU内存调整)。
五、总结
线性回归通过学习输入特征与输出标签的线性映射关系,实现连续值预测,其核心是最小化平方损失函数。优化算法是模型学习的关键,梯度下降及其变体(小批量GD、SGD)是深度学习的基础优化方法,而Adam等自适应算法则在实际应用中因其稳定性和高效性被广泛使用。
通过PyTorch框架,我们可以快速实现线性回归模型的构建、训练与评估。在实际应用中,需注意特征缩放、正则化、超参数调优(学习率、批量大小)等关键问题,以确保模型的泛化能力和训练效率。
线性回归虽然简单,但它是理解深度学习中“模型定义-损失函数-优化算法”核心流程的最佳入门案例,后续的神经网络、深度学习模型本质上都是这一流程的扩展与深化。

浙公网安备 33010602011771号