楼层: 首页/ 软件技术/ Python 机器学习与深度学习/ 线性回归
3

线性回归

Linear Regression & Regularization

线性回归是 ML 的"Hello World":用一条直线(或超平面)拟合数据,预测连续值。它最简单、最可解释,也是理解所有后续模型的基石。

数学原理

论假设函数

给定 x,预测 y = θ₀ + θ₁·x(一元),推广到多元就是 y = θ₀ + θ₁x₁ + θ₂x₂ + ... + θₙxₙ。θ 是模型要学的参数。我们要找一组 θ,让预测 ŷ 和真实 y 差得最小。

损失函数(MSE):J(θ) = (1/2m) · Σ(ŷᵢ - yᵢ)²

MSE 越小,线拟合越好。两个求解方法:正规方程(解析解,一次性算出最优 θ)和梯度下降(迭代优化,适合大数据)。

正规方程:θ = (XᵀX)⁻¹ Xᵀ y(小数据用这个,10 万行以上 XᵀX 求逆太慢,用梯度下降)

过拟合与正则化:Ridge / Lasso / ElasticNet

方法在损失里加什么效果
Ridge (L2)+ α·Σθⱼ²把参数压小但不归零,适合所有特征都有用。
Lasso (L1)+ α·Σ|θⱼ|会把不重要的参数压到 0,自带特征选择。
ElasticNetL1 + L2 混合兼顾两者,特征相关时用。

正则化为什么能防过拟合

论奥卡姆剃刀

过拟合的模型参数很大、很"曲折"。正则化在损失里加一个惩罚项(L1 或 L2),让参数尽量小。参数小 = 模型简单 = 不曲折 = 不背答案。L2 让参数平滑变小,L1 让不重要参数变 0(自动特征选择)。这就是奥卡姆剃刀:如无必要,勿增实体。

Scikit-learn 实现:加州房价回归

import numpy as np from sklearn.datasets import fetch_california_housing from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LinearRegression, Ridge, Lasso from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error # 1. 数据 data = fetch_california_housing() X, y = data.data, data.target X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) # 2. 标准化(线性模型必须做) scaler = StandardScaler() X_train_s = scaler.fit_transform(X_train) X_test_s = scaler.transform(X_test) # 3. 训练普通线性回归 lr = LinearRegression() lr.fit(X_train_s, y_train) pred_lr = lr.predict(X_test_s) # 4. 训练 Ridge(L2 正则) ridge = Ridge(alpha=1.0) ridge.fit(X_train_s, y_train) pred_ridge = ridge.predict(X_test_s) # 5. 训练 Lasso(L1 正则,会稀疏化系数) lasso = Lasso(alpha=0.01) lasso.fit(X_train_s, y_train) pred_lasso = lasso.predict(X_test_s) # 6. 评估 for name, pred in zip(["Linear", "Ridge", "Lasso"], [pred_lr, pred_ridge, pred_lasso]): rmse = np.sqrt(mean_squared_error(y_test, pred)) r2 = r2_score(y_test, pred) mae = mean_absolute_error(y_test, pred) print(f"{name:8s} | RMSE={rmse:.4f} | MAE={mae:.4f} | R2={r2:.4f}") # Linear | RMSE=0.7456 | MAE=0.5333 | R2=0.5758 # Ridge | RMSE=0.7456 | MAE=0.5333 | R2=0.5758 # Lasso | RMSE=0.7500 | MAE=0.5378 | R2=0.5708 # 7. 看系数:Lasso 把哪些特征压成 0 了 print("Lasso 非零系数个数:", (lasso.coef_ != 0).sum(), "/", len(lasso.coef_)) # Lasso 非零系数个数:7 / 8

回归评估指标

指标含义
MSE均方误差,对大误差敏感(平方放大)。
RMSEMSE 开方,和目标量纲一致,好解释。
MAE平均绝对误差,对异常值不敏感。
R²决定系数,0~1,1 是完美拟合,0 等于直接预测均值。
调整 R²加了惩罚项的 R²,特征多了也不虚假上升。

手写梯度下降(理解原理)

import numpy as np # 构造数据:y = 3x + 2 + 噪声 np.random.seed(42) X = np.random.rand(100, 1) y = 3 * X + 2 + np.random.randn(100, 1) * 0.1 # 初始化参数 w = 0.; b = 0. lr = 0.1 epochs = 1000 for i in range(epochs): y_pred = w * X + b loss = np.mean((y_pred - y)**2) # MSE 对 w, b 的偏导 dw = 2 * np.mean((y_pred - y) * X) db = 2 * np.mean(y_pred - y) w -= lr * dw b -= lr * db if i % 100 == 0: print(f"Epoch {i:4d}: w={w:.3f} b={b:.3f} loss={loss:.4f}") # Epoch 0: w=0.098 b=0.153 loss=14.9784 # Epoch 100: w=1.342 b=2.841 loss=0.5032 # Epoch 500: w=2.704 b=2.241 loss=0.0135 # Epoch 900: w=2.942 b=2.069 loss=0.0098 # 最终 w≈3.0, b≈2.0,和真实值一致

多项式回归:线性模型拟合非线性

from sklearn.preprocessing import PolynomialFeatures from sklearn.pipeline import make_pipeline # 把 x 升到二次,再套线性回归 poly_model = make_pipeline( PolynomialFeatures(degree=2), LinearRegression() ) poly_model.fit(X_train, y_train) # degree=3 可能过拟合,degree=1 就是普通线性回归

本章面试题

面试 · 线性回归

Q1. L1 和 L2 正则化区别?

查看答案

L1 产生稀疏解(自动特征选择),L2 让参数小但不归零。L1 在特征相关时不稳定,L2 更稳定。

Q2. 为什么线性回归要标准化?

查看答案

量纲不同会让某些特征在损失里被放大,正则化对大系数惩罚也不公平;标准化后每个特征"话语权"一样,梯度下降收敛也快。

Q3. R² 为负是什么意思?

查看答案

说明模型还不如直接预测均值,模型完全不行。

Q4. 正规方程 vs 梯度下降怎么选?

查看答案

特征数 < 1 万、样本不大用正规方程(一次出解);特征多、样本大用梯度下降(可扩展)。

Q5. 多重共线性有什么影响?

查看答案

特征之间高度相关时,回归系数会变得不稳定、方差很大。对策:去掉冗余特征、用 Ridge、PCA 降维。VIF(方差膨胀因子)大于 10 就要警惕。