一文读懂线性回归算法

线性回归算法详解

一、基本概念

1.1 什么是线性回归?

线性回归(Linear Regression)是机器学习和统计学中最基础且应用广泛的回归算法,主要用于建立一个或多个自变量(特征变量)与一个连续型因变量(目标变量)之间的线性关系模型

1.2 核心思想

通过一条直线(简单线性回归)或一个超平面(多元线性回归)来拟合数据,使得预测值与实际值之间的误差最小化。

1.3 算法类型

  • 监督学习:需要标签数据
  • 回归算法:预测连续值
  • 判别模型:直接建模条件概率

二、数学原理

2.1 假设函数(Hypothesis Function)

2.1.1 一元线性回归

只有一个特征的情况:

$$ h(x) = w_0 + w_1x $$

其中:

  • $h(x)$:预测值
  • $x$:输入特征
  • $w_0$:截距项(偏置)
  • $w_1$:权重系数

2.1.2 多元线性回归

有多个特征的情况:

$$ h(x) = w_0 + w_1x_1 + w_2x_2 + \cdots + w_nx_n = w^Tx $$

其中:

  • $x = [x_1, x_2, …, x_n]^T$:特征向量
  • $w = [w_0, w_1, w_2, …, w_n]^T$:权重向量
  • 通常将 $w_0$ 视为 $x_0 = 1$ 的系数

2.2 矩阵形式表示

对于 $m$ 个样本,$n$ 个特征:

$$ \mathbf{y} = \mathbf{Xw} + \mathbf{\epsilon} $$

其中:

  • $\mathbf{y} \in \mathbb{R}^{m \times 1}$:目标值向量
  • $\mathbf{X} \in \mathbb{R}^{m \times (n+1)}$:特征矩阵(包含全1列)
  • $\mathbf{w} \in \mathbb{R}^{(n+1) \times 1}$:权重向量
  • $\mathbf{\epsilon}$:误差项

三、损失函数(Loss Function)

3.1 均方误差(MSE - Mean Squared Error)

最常用的损失函数:

$$ J(w) = \frac{1}{2m} \sum_{i=1}^{m} (h(x^{(i)}) - y^{(i)})^2 $$

为什么除以2?

  • 为了求导时消去平方项的系数2,简化计算
  • 不影响最优解的位置

3.2 其他损失函数

3.2.1 平均绝对误差(MAE - Mean Absolute Error)

$$ J(w) = \frac{1}{m} \sum_{i=1}^{m} |h(x^{(i)}) - y^{(i)}| $$

特点:对异常值不敏感,但不可导

3.2.2 均方根误差(RMSE - Root Mean Squared Error)

$$ J(w) = \sqrt{\frac{1}{m} \sum_{i=1}^{m} (h(x^{(i)}) - y^{(i)})^2} $$

特点:与原始数据单位一致


四、参数优化方法

4.1 正规方程(Normal Equation)

4.1.1 原理

通过对损失函数求偏导,令导数等于0,直接求解最优参数:

$$ \frac{\partial J(w)}{\partial w} = 0 $$

4.1.2 解析解

$$ w = (\mathbf{X}^T\mathbf{X})^{-1}\mathbf{X}^T\mathbf{y} $$

4.1.3 优缺点

优点

  • 无需选择学习率
  • 无需迭代,一次求解
  • 保证找到全局最优解

缺点

  • 需要计算矩阵逆,时间复杂度 $O(n^3)$
  • 当特征数量很大时(如 $n > 10^4$),计算效率低
  • 要求 $\mathbf{X}^T\mathbf{X}$ 可逆

4.2 梯度下降法(Gradient Descent)

4.2.1 基本原理

通过迭代方式,沿着损失函数下降最快的方向(负梯度方向)更新参数。

4.2.2 更新公式

$$ w_j := w_j - \alpha \frac{\partial J(w)}{\partial w_j} $$

其中 $\alpha$ 是学习率(步长)

4.2.3 梯度计算

对于均方误差损失函数:

$$ \frac{\partial J(w)}{\partial w_j} = \frac{1}{m} \sum_{i=1}^{m} (h(x^{(i)}) - y^{(i)})x_j^{(i)} $$

完整更新公式:

$$ w_j := w_j - \alpha \frac{1}{m} \sum_{i=1}^{m} (h(x^{(i)}) - y^{(i)})x_j^{(i)} $$

4.2.4 三种梯度下降变体

1. 批量梯度下降(Batch Gradient Descent, BGD)
  • 使用全部训练数据计算梯度
  • 更新公式:$w := w - \alpha \nabla J(w)$
  • 优点:收敛稳定,保证找到全局最优解
  • 缺点:数据量大时计算慢,无法在线学习
2. 随机梯度下降(Stochastic Gradient Descent, SGD)
  • 每次使用一个样本计算梯度
  • 更新公式:$w := w - \alpha \nabla J^{(i)}(w)$
  • 优点:计算快,可在线学习
  • 缺点:收敛路径波动大,可能无法精确收敛
3. 小批量梯度下降(Mini-Batch Gradient Descent, MBGD)
  • 每次使用一小批样本(如32、64、128)计算梯度
  • 优点:兼顾BGD和SGD的优点
  • 缺点:需要选择合适的批量大小

五、特征预处理

5.1 为什么需要特征缩放?

  • 加速梯度下降收敛
  • 避免某些特征因量纲大而主导模型
  • 提高数值稳定性

5.2 常用方法

5.2.1 最小-最大归一化(Min-Max Scaling)

$$ x_{\text{norm}} = \frac{x - x_{\min}}{x_{\max} - x_{\min}} $$

  • 将特征缩放到 [0, 1] 范围
  • 对异常值敏感

5.2.2 Z-Score标准化(Standardization)

$$ x_{\text{std}} = \frac{x - \mu}{\sigma} $$

  • 将特征转换为均值为0,标准差为1的分布
  • 对异常值相对不敏感
  • 推荐使用

六、正则化(Regularization)

6.1 为什么要正则化?

  • 防止过拟合
  • 提高模型泛化能力
  • 处理多重共线性问题

6.2 L1正则化(Lasso Regression)

6.2.1 损失函数

$$ J(w) = \frac{1}{2m} \sum_{i=1}^{m} (h(x^{(i)}) - y^{(i)})^2 + \lambda \sum_{j=1}^{n} |w_j| $$

6.2.2 特点

  • 可产生稀疏解(某些权重为0)
  • 相当于特征选择
  • 适用于高维数据

6.3 L2正则化(Ridge Regression)

6.3.1 损失函数

$$ J(w) = \frac{1}{2m} \sum_{i=1}^{m} (h(x^{(i)}) - y^{(i)})^2 + \lambda \sum_{j=1}^{n} w_j^2 $$

6.3.2 特点

  • 所有权重都会被缩小,但不会为0
  • 防止过拟合效果好
  • 计算更稳定

6.4 Elastic Net

结合L1和L2正则化:

$$ J(w) = \frac{1}{2m} \sum_{i=1}^{m} (h(x^{(i)}) - y^{(i)})^2 + \lambda_1 \sum_{j=1}^{n} |w_j| + \lambda_2 \sum_{j=1}^{n} w_j^2 $$


七、模型评估指标

7.1 均方误差(MSE)

$$ \text{MSE} = \frac{1}{m} \sum_{i=1}^{m} (y^{(i)} - \hat{y}^{(i)})^2 $$

  • 值越小越好
  • 对异常值敏感

7.2 均方根误差(RMSE)

$$ \text{RMSE} = \sqrt{\frac{1}{m} \sum_{i=1}^{m} (y^{(i)} - \hat{y}^{(i)})^2} $$

  • 与原始数据单位一致
  • 更直观

7.3 平均绝对误差(MAE)

$$ \text{MAE} = \frac{1}{m} \sum_{i=1}^{m} |y^{(i)} - \hat{y}^{(i)}| $$

  • 对异常值不敏感
  • 解释性好

7.4 决定系数(R²)

$$ R^2 = 1 - \frac{\sum_{i=1}^{m} (y^{(i)} - \hat{y}^{(i)})^2}{\sum_{i=1}^{m} (y^{(i)} - \bar{y})^2} $$

  • 取值范围:$(-\infty, 1]$
  • 越接近1,模型拟合越好
  • 可为负值(模型比均值预测还差)

八、多项式回归

8.1 基本思想

通过添加特征的高次项,将线性模型扩展为非线性模型:

$$ h(x) = w_0 + w_1x + w_2x^2 + \cdots + w_dx^d $$

8.2 实现方法

将原始特征 $x$ 转换为 $[x, x^2, x^3, …, x^d]$,然后应用线性回归。

8.3 注意事项

  • 容易过拟合,需要正则化
  • 特征维度增加,计算成本上升
  • 需要特征缩放

九、应用场景

9.1 经济金融

  • 股票价格预测
  • 房价预测
  • 销售额预测
  • 经济指标分析

9.2 医疗健康

  • 药物剂量与疗效关系
  • 疾病风险因素分析
  • 医疗费用预测

9.3 工程技术

  • 材料性能预测
  • 设备寿命预测
  • 能源消耗预测

9.4 社会科学

  • 教育成绩影响因素分析
  • 收入与消费关系研究
  • 人口增长预测

十、优缺点分析

10.1 优点

简单高效:计算复杂度低,易于理解和实现
可解释性强:权重直接反映特征重要性
理论基础扎实:源于统计学,数学性质良好
计算速度快:适合大规模数据
可扩展性好:可通过多项式扩展处理非线性问题

10.2 缺点

线性假设限制:只能建模线性关系
对异常值敏感:需要数据预处理
多重共线性问题:特征高度相关时性能下降
需要特征工程:对非线性关系需要手动处理
外推能力有限:超出训练数据范围的预测不可靠


十一、实现示例

11.1 手动实现(梯度下降)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import numpy as np
import matplotlib.pyplot as plt

class LinearRegression:
def __init__(self, learning_rate=0.01, n_iterations=1000):
self.lr = learning_rate
self.n_iterations = n_iterations
self.weights = None
self.bias = None

def fit(self, X, y):
n_samples, n_features = X.shape

# 初始化参数
self.weights = np.zeros(n_features)
self.bias = 0

# 梯度下降
for _ in range(self.n_iterations):
# 预测
y_pred = np.dot(X, self.weights) + self.bias

# 计算梯度
dw = (1 / n_samples) * np.dot(X.T, (y_pred - y))
db = (1 / n_samples) * np.sum(y_pred - y)

# 更新参数
self.weights -= self.lr * dw
self.bias -= self.lr * db

def predict(self, X):
return np.dot(X, self.weights) + self.bias

def score(self, X, y):
y_pred = self.predict(X)
ss_res = np.sum((y - y_pred) ** 2)
ss_tot = np.sum((y - np.mean(y)) ** 2)
return 1 - (ss_res / ss_tot)

# 生成示例数据
np.random.seed(42)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)

# 训练模型
model = LinearRegression(learning_rate=0.1, n_iterations=1000)
model.fit(X, y)

# 预测和评估
y_pred = model.predict(X)
r2_score = model.score(X, y)

print(f"权重: {model.weights[0]:.4f}")
print(f"偏置: {model.bias:.4f}")
print(f"R²分数: {r2_score:.4f}")

# 可视化
plt.scatter(X, y, color='blue', label='实际数据')
plt.plot(X, y_pred, color='red', label='预测线')
plt.xlabel('X')
plt.ylabel('y')
plt.title('线性回归拟合')
plt.legend()
plt.grid(True)
plt.show()

11.2 使用Scikit-learn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
import pandas as pd

# 1. 准备数据
# 假设我们有一个房价数据集
np.random.seed(42)
X = np.random.rand(1000, 3) * 100 # 3个特征
y = 10 + 2*X[:, 0] + 3*X[:, 1] - 1.5*X[:, 2] + np.random.randn(1000) * 10

# 2. 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 3. 特征缩放
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 4. 训练普通线性回归模型
lr_model = LinearRegression()
lr_model.fit(X_train_scaled, y_train)

# 5. 训练岭回归模型(L2正则化)
ridge_model = Ridge(alpha=1.0)
ridge_model.fit(X_train_scaled, y_train)

# 6. 训练Lasso回归模型(L1正则化)
lasso_model = Lasso(alpha=0.1)
lasso_model.fit(X_train_scaled, y_train)

# 7. 预测
y_pred_lr = lr_model.predict(X_test_scaled)
y_pred_ridge = ridge_model.predict(X_test_scaled)
y_pred_lasso = lasso_model.predict(X_test_scaled)

# 8. 评估
print("普通线性回归:")
print(f" MSE: {mean_squared_error(y_test, y_pred_lr):.2f}")
print(f" R²: {r2_score(y_test, y_pred_lr):.4f}")
print(f" 系数: {lr_model.coef_}")

print("\n岭回归 (Ridge):")
print(f" MSE: {mean_squared_error(y_test, y_pred_ridge):.2f}")
print(f" R²: {r2_score(y_test, y_pred_ridge):.4f}")
print(f" 系数: {ridge_model.coef_}")

print("\nLasso回归:")
print(f" MSE: {mean_squared_error(y_test, y_pred_lasso):.2f}")
print(f" R²: {r2_score(y_test, y_pred_lasso):.4f}")
print(f" 系数: {lasso_model.coef_}")

11.3 多项式回归示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
import matplotlib.pyplot as plt

# 生成非线性数据
np.random.seed(42)
X = np.linspace(-3, 3, 100).reshape(-1, 1)
y = 0.5 * X**3 - 2 * X**2 + 3 * X + 5 + np.random.randn(100, 1) * 3

# 创建不同阶数的多项式回归模型
degrees = [1, 2, 3, 5, 10]
plt.figure(figsize=(15, 10))

for i, degree in enumerate(degrees):
# 创建管道:多项式特征 + 线性回归
model = Pipeline([
('poly', PolynomialFeatures(degree=degree)),
('linear', LinearRegression())
])

model.fit(X, y)
y_pred = model.predict(X)

# 计算R²
r2 = r2_score(y, y_pred)

# 绘图
plt.subplot(2, 3, i+1)
plt.scatter(X, y, color='blue', alpha=0.5, label='数据')
plt.plot(X, y_pred, color='red', linewidth=2, label=f'预测 (R²={r2:.3f})')
plt.title(f'多项式回归 (阶数={degree})')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.grid(True)

plt.tight_layout()
plt.show()

十二、工程实践建议

12.1 数据预处理

  1. 处理缺失值:删除或填充
  2. 处理异常值:识别并处理
  3. 特征缩放:标准化或归一化
  4. 特征编码:处理分类变量

12.2 模型选择

  1. 特征数量少(< 10000):优先考虑正规方程
  2. 特征数量多:使用梯度下降
  3. 存在多重共线性:使用岭回归
  4. 需要特征选择:使用Lasso回归

12.3 超参数调优

  1. 学习率:通过学习曲线选择合适值
  2. 正则化强度:使用交叉验证
  3. 迭代次数:监控损失函数收敛

12.4 模型诊断

  1. 残差分析:检查残差是否随机分布
  2. 多重共线性检测:计算VIF(方差膨胀因子)
  3. 异方差性检测:绘制残差图
  4. 正态性检验:QQ图或Shapiro-Wilk检验

12.5 避免常见陷阱

  1. 过拟合:使用正则化、交叉验证
  2. 欠拟合:增加特征、使用多项式
  3. 数据泄露:确保测试集完全独立
  4. 忽略特征交互:考虑添加交互项

总结

线性回归作为机器学习的基石算法,具有简单、高效、可解释的特点。虽然它只能建模线性关系,但通过多项式扩展特征工程,可以处理许多复杂的实际问题。

在实际应用中,线性回归的优势在于:

  • 快速原型开发:快速验证想法
  • 基准模型:作为复杂模型的对比基准
  • 可解释性需求:需要理解特征影响的场景

掌握线性回归不仅有助于解决实际问题,更是理解更复杂机器学习算法(如逻辑回归、神经网络)的基础。