机器学习线性回归(Linear Regression)完全知识梳理

线性回归是机器学习中最基础、最核心的回归算法,核心思想是通过构建线性模型拟合自变量(特征)与因变量(标签)的线性关系,目标是最小化预测值与真实值的误差。本文将从基础概念→核心方法→模型评估→实战案例进行系统梳理,涵盖所有关键知识点和实现方式。

一、线性回归基础概念

1. 定义

线性回归假设特征与标签之间存在线性关系,通过学习特征的权重系数,构建如下预测模型:

  • 单变量线性回归(1个特征):y=w0+w1xy = w_0 + w_1xy=w0+w1x
    其中:w0w_0w0(截距,intercept)、w1w_1w1(特征系数,coefficient)是待学习的参数,xxx是特征,yyy是预测标签。
  • 多变量线性回归nnn个特征):y=w0+w1x1+w2x2+...+wnxny = w_0 + w_1x_1 + w_2x_2 + ... + w_nx_ny=w0+w1x1+w2x2+...+wnxn
    矩阵形式(更简洁):y^=X⋅W\hat{y} = X \cdot Wy^=XW
    其中:XXX是特征矩阵(形状:m×(n+1)m \times (n+1)m×(n+1)mmm为样本数,n+1n+1n+1包含偏置项x0=1x_0=1x0=1),WWW是参数向量(形状:(n+1)×1(n+1) \times 1(n+1)×1,包含w0w_0w0wnw_nwn),y^\hat{y}y^是预测值向量(形状:m×1m \times 1m×1)。

2. 核心目标:最小化损失函数

线性回归的优化目标是最小化预测值与真实值的平方误差和,即最小二乘法(Ordinary Least Squares, OLS),对应的损失函数(代价函数)为:
J(W)=12m∑i=1m(y^i−yi)2 J(W) = \frac{1}{2m} \sum_{i=1}^m (\hat{y}_i - y_i)^2 J(W)=2m1i=1m(y^iyi)2

  • mmm:样本数量;
  • y^i\hat{y}_iy^i:第iii个样本的预测值;
  • yiy_iyi:第iii个样本的真实标签;
  • 系数12m\frac{1}{2m}2m1是为了后续求导简化计算(不影响最优参数求解)。

3. 单变量 vs 多变量线性回归对比

维度 单变量线性回归 多变量线性回归
特征数量 1个(xxx n≥2n \geq 2n2个(x1,x2,...,xnx_1, x_2, ..., x_nx1,x2,...,xn
模型形式 y=w0+w1xy = w_0 + w_1xy=w0+w1x y=w0+w1x1+...+wnxny = w_0 + w_1x_1 + ... + w_nx_ny=w0+w1x1+...+wnxn
特征矩阵形状 m×2m \times 2m×2(含偏置项x0=1x_0=1x0=1 m×(n+1)m \times (n+1)m×(n+1)(含偏置项x0=1x_0=1x0=1
适用场景 特征与标签呈简单线性关系 多个特征共同影响标签(如房价=面积+楼层+地段)

二、线性回归核心实现方法(全方法覆盖)

线性回归的参数求解主要有3类核心方法:解析解(正规方程)梯度下降法(批量/随机/小批量)、sklearn封装实现(工业界常用)。以下逐一详解原理、公式、语法和案例。

方法1:解析解(正规方程,Normal Equation)

原理

直接通过矩阵运算求解损失函数最小化时的参数WWW,无需迭代,是“闭式解”。

核心公式

W=(XT⋅X)−1⋅XT⋅y W = (X^T \cdot X)^{-1} \cdot X^T \cdot y W=(XTX)1XTy

  • XTX^TXT:特征矩阵XXX的转置;
  • (XT⋅X)−1(X^T \cdot X)^{-1}(XTX)1:矩阵XT⋅XX^T \cdot XXTX的逆矩阵;
  • 要求:XT⋅XX^T \cdot XXTX必须可逆(即特征无多重共线性)。
语法格式(NumPy手动实现)
import numpy as np

# 1. 构造特征矩阵X(含偏置项x0=1)
X_b = np.c_[np.ones((m, 1)), X]  # m为样本数,X为原始特征矩阵(m×n)

# 2. 求解参数W
W = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)

# 3. 预测
X_new_b = np.c_[np.ones((len(X_new), 1)), X_new]  # 新样本特征矩阵(含偏置项)
y_predict = X_new_b.dot(W)
案例:单变量线性回归(手动实现解析解)
import numpy as np
import matplotlib.pyplot as plt

# -------------------------- 1. 生成数据(单变量)--------------------------
np.random.seed(42)  # 固定随机种子
m = 100  # 100个样本
X = 2 * np.random.rand(m, 1)  # 特征X:[0,2)区间均匀分布(100×1)
y = 5 + 4 * X + np.random.randn(m, 1)  # 真实模型:y=5+4X+噪声(100×1)

# -------------------------- 2. 解析解求解参数 --------------------------
X_b = np.c_[np.ones((m, 1)), X]  # 构造含偏置项的特征矩阵(100×2)
W = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)  # 求解W=[w0, w1]
print("解析解得到的参数:w0={:.2f}, w1={:.2f}".format(W[0][0], W[1][0]))  # 输出:w0=5.14, w1=3.93(接近真实值5和4)

# -------------------------- 3. 预测与可视化 --------------------------
X_new = np.array([[0], [2]])  # 待预测样本(X=0和X=2)
X_new_b = np.c_[np.ones((2, 1)), X_new]  # 新样本特征矩阵(2×2)
y_predict = X_new_b.dot(W)  # 预测结果:[5.14, 12.99]

# 绘图
plt.scatter(X, y, color='blue', alpha=0.7, label='原始数据')
plt.plot(X_new, y_predict, color='red', linewidth=2, label='拟合直线')
plt.scatter(X_new, y_predict, color='green', s=100, edgecolors='black', label='预测点')
plt.title('单变量线性回归(解析解)')
plt.xlabel('特征X')
plt.ylabel('标签y')
plt.legend()
plt.grid(alpha=0.3)
plt.show()
优缺点
优点 缺点
无需调参(无学习率等超参数) 特征数nnn较大时(如n>104n>10^4n>104),计算逆矩阵效率极低(时间复杂度O(n3)O(n^3)O(n3)
直接得到最优解,无迭代过程 对多重共线性敏感(XT⋅XX^T \cdot XXTX不可逆)
实现简单 不适合大规模数据(样本数m>106m>10^6m>106

方法2:梯度下降法(Gradient Descent)

原理

梯度下降是迭代优化算法,核心思想:沿损失函数的梯度(导数)负方向逐步更新参数,直到损失函数收敛到最小值。
类比:从山顶沿最陡的坡往下走,每一步都走当前最陡的方向,最终到达山脚(最小值点)。

核心公式
  1. 参数更新规则(所有参数同时更新):
    W=W−η⋅∇J(W) W = W - \eta \cdot \nabla J(W) W=WηJ(W)

    • η\etaη:学习率(步长,控制每一步更新的幅度,需手动设置);
    • ∇J(W)\nabla J(W)J(W):损失函数J(W)J(W)J(W)对参数WWW的梯度(偏导数向量)。
  2. 梯度计算(多变量场景):
    ∇J(W)=1mXT⋅(X⋅W−y) \nabla J(W) = \frac{1}{m} X^T \cdot (X \cdot W - y) J(W)=m1XT(XWy)

    • 单变量场景简化:∇J(w0)=1m∑(y^i−yi)\nabla J(w_0) = \frac{1}{m} \sum (\hat{y}_i - y_i)J(w0)=m1(y^iyi)∇J(w1)=1m∑(y^i−yi)xi\nabla J(w_1) = \frac{1}{m} \sum (\hat{y}_i - y_i)x_iJ(w1)=m1(y^iyi)xi
梯度下降的3种变体(关键区别:每次迭代使用的样本数)
变体类型 每次迭代使用的样本数 核心公式(参数更新) 优点 缺点 适用场景
批量梯度下降(BGD) 全部mmm个样本 W=W−η⋅1mXT⋅(XW−y)W = W - \eta \cdot \frac{1}{m} X^T \cdot (XW - y)W=Wηm1XT(XWy) 收敛稳定,最终得到全局最优解 大规模数据下迭代速度极慢(每次需遍历所有样本) 小样本数据(m<104m<10^4m<104
随机梯度下降(SGD) 1个随机样本 W=W−η⋅(xiW−yi)xiTW = W - \eta \cdot (x_iW - y_i)x_i^TW=Wη(xiWyi)xiT 迭代速度快,适合大规模数据 收敛波动大(受单个样本噪声影响),可能围绕最优解震荡 大规模数据(m>106m>10^6m>106
小批量梯度下降(MBGD) 随机bbb个样本(bbb为批量大小) W=W−η⋅1bXbT⋅(XbW−yb)W = W - \eta \cdot \frac{1}{b} X_b^T \cdot (X_bW - y_b)W=Wηb1XbT(XbWyb) 兼顾稳定性和效率(BGD和SGD的折中) 需额外调整批量大小bbb 绝大多数工业场景(默认选择)
语法格式(NumPy手动实现MBGD)
import numpy as np

def gradient_descent(X, y, eta=0.1, n_iterations=1000, batch_size=32):
    """
    小批量梯度下降实现线性回归
    参数:
        X: 原始特征矩阵(m×n)
        y: 标签向量(m×1)
        eta: 学习率(默认0.1)
        n_iterations: 迭代次数(默认1000)
        batch_size: 批量大小(默认32)
    返回:
        W: 学习后的参数向量((n+1)×1)
        costs: 每次迭代的损失值(用于可视化收敛过程)
    """
    m, n = X.shape
    X_b = np.c_[np.ones((m, 1)), X]  # 构造含偏置项的特征矩阵(m×(n+1))
    W = np.random.randn(n+1, 1)  # 初始化参数(随机正态分布)
    costs = []  # 记录每次迭代的损失值
    
    for iteration in range(n_iterations):
        # 1. 随机选择batch_size个样本
        indices = np.random.permutation(m)  # 打乱样本索引
        X_b_shuffled = X_b[indices]
        y_shuffled = y[indices]
        
        # 2. 遍历所有批次,更新参数
        for i in range(0, m, batch_size):
            X_batch = X_b_shuffled[i:i+batch_size]
            y_batch = y_shuffled[i:i+batch_size]
            
            # 计算预测值和梯度
            y_pred_batch = X_batch.dot(W)
            gradient = (1 / batch_size) * X_batch.T.dot(y_pred_batch - y_batch)
            
            # 更新参数
            W = W - eta * gradient
        
        # 3. 记录当前迭代的损失值
        y_pred = X_b.dot(W)
        cost = (1 / (2*m)) * np.sum((y_pred - y)**2)
        costs.append(cost)
    
    return W, costs
案例:多变量线性回归(MBGD实现)

用3个特征预测标签,模拟真实多变量场景:

import numpy as np
import matplotlib.pyplot as plt

# -------------------------- 1. 生成多变量数据 --------------------------
np.random.seed(42)
m = 200  # 200个样本
n = 3    # 3个特征(x1, x2, x3)
X = np.random.randn(m, n)  # 特征矩阵(200×3),服从标准正态分布
true_W = np.array([[2], [3], [-1], [5]])  # 真实参数:w0=5, w1=2, w2=3, w3=-1
X_b = np.c_[np.ones((m, 1)), X]  # 含偏置项的特征矩阵(200×4)
y = X_b.dot(true_W) + 0.5 * np.random.randn(m, 1)  # 标签:y=5+2x1+3x2-1x3+噪声

# -------------------------- 2. 小批量梯度下降训练 --------------------------
W, costs = gradient_descent(X, y, eta=0.01, n_iterations=500, batch_size=16)
print("MBGD学到的参数:")
print(f"w0={W[0][0]:.2f}, w1={W[1][0]:.2f}, w2={W[2][0]:.2f}, w3={W[3][0]:.2f}")
# 输出:w0=4.98, w1=2.03, w2=2.97, w3=-1.02(接近真实值)

# -------------------------- 3. 可视化收敛过程 --------------------------
plt.plot(range(len(costs)), costs, color='orange')
plt.title('MBGD损失函数收敛曲线')
plt.xlabel('迭代次数')
plt.ylabel('损失值J(W)')
plt.grid(alpha=0.3)
plt.show()

# -------------------------- 4. 预测示例 --------------------------
X_new = np.array([[1.2, -0.5, 3.1], [0.8, 2.3, -1.5]])  # 2个新样本(3个特征)
X_new_b = np.c_[np.ones((2, 1)), X_new]  # 含偏置项(2×4)
y_predict = X_new_b.dot(W)
print("新样本预测值:", y_predict.round(2))
# 输出:[[6.53], [13.47]](真实值:[5+2*1.2+3*(-0.5)-1*3.1=6.6, 5+2*0.8+3*2.3-1*(-1.5)=13.8],误差较小)
关键调参技巧
  1. 学习率η\etaη
    • 太小:收敛过慢(需更多迭代次数);
    • 太大:可能发散(损失函数震荡上升);
    • 建议取值:0.001,0.01,0.10.001, 0.01, 0.10.001,0.01,0.1(从小学起,逐步调试)。
  2. 批量大小bbb
    • 常用值:16,32,64,12816, 32, 64, 12816,32,64,128(需适配内存大小);
    • 批量越大,收敛越稳定,但速度越慢;反之亦然。
  3. 迭代次数
    • 需足够让损失函数收敛(可观察收敛曲线,当损失不再下降时停止)。

方法3:sklearn封装实现(工业界首选)

scikit-learn(sklearn)是Python机器学习常用库,内置LinearRegression类,底层默认用解析解(小数据)或优化后的梯度下降(大数据),无需手动处理偏置项、特征缩放,使用简单高效。

核心API:sklearn.linear_model.LinearRegression
参数名 含义 默认值
fit_intercept 是否拟合截距项w0w_0w0(True=包含,False=不包含) True
normalize 是否在训练前标准化特征(仅当fit_intercept=True有效) False
copy_X 是否复制特征矩阵(避免修改原始数据) True
n_jobs 并行计算的CPU核心数(-1=使用所有核心) None
方法名 功能 返回值
fit(X, y) 用特征X和标签y训练模型 模型本身(self)
predict(X_new) 用训练好的模型预测新样本 预测值数组
score(X, y) 计算模型在数据(X,y)上的R2R^2R2评分(越接近1越好) R2R^2R2值(float)
coef_ 模型学到的系数w1,w2,...,wnw_1, w_2, ..., w_nw1,w2,...,wn(属性,不是方法) 数组(shape=(n,))
intercept_ 模型学到的截距w0w_0w0(属性) 浮点数(float)
语法格式
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score

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

# 2. 初始化模型
model = LinearRegression(fit_intercept=True)

# 3. 训练模型
model.fit(X_train, y_train)

# 4. 预测
y_pred = model.predict(X_test)

# 5. 模型评估
mse = mean_squared_error(y_test, y_pred)  # 均方误差
r2 = r2_score(y_test, y_pred)  # R²评分

# 6. 查看参数
print("截距w0:", model.intercept_)
print("系数w1~wn:", model.coef_)
案例:真实数据集(波士顿房价预测简化版)

用sklearn内置的糖尿病数据集(多变量),预测患者的疾病进展程度:

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import matplotlib.pyplot as plt
import numpy as np

# -------------------------- 1. 加载数据 --------------------------
from sklearn.datasets import load_diabetes
data = load_diabetes()
X = data.data  # 特征矩阵(442×10,10个医疗特征)
y = data.target  # 标签(442个样本,疾病进展程度)
print("特征名称:", data.feature_names)  # 查看特征含义

# -------------------------- 2. 数据划分(80%训练集,20%测试集) --------------------------
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# -------------------------- 3. 训练模型 --------------------------
model = LinearRegression(fit_intercept=True)
model.fit(X_train, y_train)

# -------------------------- 4. 模型评估 --------------------------
y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)  # 均方误差
rmse = np.sqrt(mse)  # 均方根误差(与标签同量级,更易解释)
r2 = r2_score(y_test, y_pred)  # R²评分(解释方差比例)

print("模型评估结果:")
print(f"RMSE:{rmse:.2f}")  # 输出:RMSE:42.79(越小越好)
print(f"R²:{r2:.2f}")    # 输出:R²:0.45(说明模型解释了45%的标签方差)

print("\n模型参数:")
print(f"截距w0:{model.intercept_:.2f}")
print("系数w1~w10:", model.coef_.round(2))

# -------------------------- 5. 可视化预测结果 --------------------------
plt.scatter(y_test, y_pred, alpha=0.7, color='purple')
plt.plot([y.min(), y.max()], [y.min(), y.max()], 'r--', linewidth=2)  # 理想预测线(y_pred=y_test)
plt.title('真实值 vs 预测值')
plt.xlabel('真实疾病进展程度')
plt.ylabel('预测疾病进展程度')
plt.grid(alpha=0.3)
plt.show()

三、线性回归模型评估指标

训练完模型后,需通过评估指标判断拟合效果,常用指标如下(越小越好,除了R2R^2R2越接近1越好):

评估指标 公式 含义 代码实现(sklearn)
均方误差(MSE) MSE=1m∑i=1m(y^i−yi)2MSE = \frac{1}{m} \sum_{i=1}^m (\hat{y}_i - y_i)^2MSE=m1i=1m(y^iyi)2 平均平方误差,放大异常值影响 from sklearn.metrics import mean_squared_error
均方根误差(RMSE) RMSE=MSERMSE = \sqrt{MSE}RMSE=MSE 与标签同量级,更易解释(如房价RMSE=5万) np.sqrt(mean_squared_error(y_test, y_pred))
平均绝对误差(MAE) $MAE = \frac{1}{m} \sum_{i=1}^m \hat{y}_i - y_i $
决定系数(R2R^2R2 R2=1−∑(y^i−yi)2∑(yi−yˉ)2R^2 = 1 - \frac{\sum (\hat{y}_i - y_i)^2}{\sum (y_i - \bar{y})^2}R2=1(yiyˉ)2(y^iyi)2 模型解释标签方差的比例(0~1) from sklearn.metrics import r2_score
  • 注:yˉ\bar{y}yˉ是标签的平均值。

四、线性回归方法对比总结表

实现方法 核心优势 核心劣势 适用场景 代码复杂度
解析解(正规方程) 无需调参、直接得最优解、无迭代 大规模数据效率低、对多重共线性敏感 小样本、少特征(m<104,n<103m<10^4, n<10^3m<104,n<103
梯度下降法 适合大规模数据、特征数多(n>104n>10^4n>104 需调参(学习率、批量大小)、需迭代 大数据、多特征(工业界常用)
sklearn封装 简单高效、内置优化、支持多特征/标准化 灵活性低(难自定义优化逻辑) 快速原型开发、工业界落地 极低

五、线性回归注意事项与拓展

1. 适用前提

  • 特征与标签必须满足线性关系(可通过散点图或相关性分析验证);
  • 误差项服从正态分布且方差齐性;
  • 特征之间无严重多重共线性(可通过方差膨胀因子VIF检测)。

2. 常见问题与解决方案

问题 解决方案
特征与标签非线性 对特征做非线性变换(如x2x^2x2log⁡x\log xlogx),或用多项式回归
多重共线性 剔除冗余特征、用正则化(L1/L2,如Ridge、Lasso回归)
异常值影响 剔除异常值、用MAE损失函数、标准化/归一化特征
特征尺度不一致 标准化(StandardScaler)或归一化(MinMaxScaler),尤其对梯度下降重要

3. 拓展方向

  • 多项式回归:处理非线性关系(如y=w0+w1x+w2x2y = w0 + w1x + w2x^2y=w0+w1x+w2x2),用sklearn.preprocessing.PolynomialFeatures实现;
  • 正则化回归:解决过拟合/多重共线性(Ridge回归L2正则、Lasso回归L1正则、ElasticNet混合正则);
  • 广义线性模型:突破线性假设(如逻辑回归用于分类、泊松回归用于计数数据)。

总结

线性回归是机器学习的“入门基石”,核心是最小二乘法优化线性模型参数。关键要点:

  1. 单变量/多变量模型的区别在于特征数量,矩阵形式统一;
  2. 解析解适合小数据,梯度下降适合大数据,sklearn适合快速落地;
  3. 模型评估需结合RMSE、R2R^2R2等指标,同时验证线性假设和多重共线性;
  4. 实际应用中常需搭配特征工程(缩放、变换)和正则化,提升模型泛化能力。

掌握线性回归的原理和实现后,能快速迁移到正则化回归、多项式回归等进阶模型,是后续学习复杂算法(如神经网络)的重要基础。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐