欢迎光临
我们一直在努力

进阶篇-机器学习篇-6--什么是线性回归?从原理到代码,彻底搞懂

《什么是线性回归?从原理到代码,彻底搞懂》

作者:Weisian
发布时间:2026年3月

在这里插入图片描述

为什么线性回归是机器学习的“Hello World”?

你是不是觉得机器学习高深莫测,满脑子都是神经网络、Transformer、大模型?
但我想告诉你:所有复杂的模型,都始于一个简单的直线方程。

线性回归(Linear Regression)不仅是统计学中最经典的算法,更是机器学习大厦的基石。它简单、直观、可解释性强,更重要的是——它蕴含了机器学习最核心的思想:通过数据学习规律,用损失函数衡量误差,用优化算法寻找最优解。

在这里插入图片描述

如果你能彻底搞懂线性回归,你就掌握了打开机器学习大门的钥匙。今天,我不讲枯燥的数学推导,而是带你从直观理解 → 核心公式 → 手撕代码 → sklearn实战 → 可视化验证,一步步把线性回归吃透。


第一部分:先搞懂:线性回归到底在做什么?

1.1 一个生活化的类比:预测房价

想象一下,你想买房子,手头有一组数据:

  • 房屋面积(平方米):50, 60, 70, 80, 90…
  • 对应房价(万元):150, 180, 210, 240, 270…

你发现:面积越大,房价越高,而且大致呈一条直线关系。
于是你画了一条直线,试图用这条直线去预测任意面积对应的房价。

在这里插入图片描述

这就是线性回归在做的事:找到一条最佳拟合直线,让预测值尽可能接近真实值。

1.2 线性回归的核心思想

线性回归假设目标变量 yyy 和特征变量 xxx 之间存在线性关系:

y=w⋅x+b
y = w \\cdot x + b
y=wx+b

其中:

  • yyy:预测值(如房价)
  • xxx:输入特征(如面积)
  • www:权重(斜率,表示xxxyyy的影响程度)
  • bbb:偏置(截距,当x=0x=0x=0时的基础值)

我们的任务就是:从数据中学习出最佳的 wwwbbb,使得预测误差最小。

在这里插入图片描述

1.3 线性回归要解决的两个核心问题

  • 如何衡量预测的好坏? → 损失函数(Loss Function)
  • 如何找到最优的 wwwbbb? → 优化算法(最小二乘法 / 梯度下降)
  • 接下来,我们逐一拆解。


    第二部分:核心原理——从公式到直观理解

    2.1 损失函数:如何衡量预测误差?

    我们需要一个指标来判断直线拟合的效果,这就是损失函数(Loss Function)。

    直观理解:
    对于每个数据点,预测值和真实值之间会有误差:

    误差 = 真实值 – 预测值 = y_true – y_pred

    我们希望所有数据点的误差总和最小。

    最常用的损失函数是均方误差(MSE, Mean Squared Error):

    MSE=1n∑i=1n(yi−y^i)2
    \\text{MSE} = \\frac{1}{n} \\sum_{i=1}^{n} (y_i – \\hat{y}_i)^2
    MSE=n1i=1n(yiy^i)2

    其中:

    • yiy_iyi:真实值
    • y^i=w⋅xi+b\\hat{y}_i = w \\cdot x_i + by^i=wxi+b:预测值
    • nnn:样本数量

    线性回归的目标:找到一组w和b,让MSE最小。

    在这里插入图片描述

    直观理解:
    MSE计算的是"预测值与真实值差的平方的平均值"。

    • 差得越远,平方后惩罚越大
    • 我们希望MSE越小越好

    找到最小MSE的过程,就是"优化"。我们有两种核心方法:最小二乘法和梯度下降。

    2.2 最小二乘法:解析解的直接求解

    最小二乘法(Least Squares)的思想很简单:找到一组 wwwbbb,使得MSE最小。过程基本就是对MSE求导,令导数为0,直接解出w和b的解析解。

    对于一元线性回归,最小二乘法有解析解(可以直接用公式算出来):

    w=∑i=1n(xi−xˉ)(yi−yˉ)∑i=1n(xi−xˉ)2
    w = \\frac{\\sum_{i=1}^{n} (x_i – \\bar{x})(y_i – \\bar{y})}{\\sum_{i=1}^{n} (x_i – \\bar{x})^2}
    w=i=1n(xixˉ)2i=1n(xixˉ)(yiyˉ)

    b=yˉ−w⋅xˉ
    b = \\bar{y} – w \\cdot \\bar{x}
    b=yˉwxˉ

    其中 xˉ\\bar{x}xˉyˉ\\bar{y}yˉ 分别是 xxxyyy 的平均值。

    优点:计算快,一次搞定
    缺点:只适用于简单线性回归,复杂模型无法用解析解

    在这里插入图片描述

    2.3 梯度下降:迭代优化的通用方法

    当模型变复杂(比如多元线性回归、神经网络),解析解就不存在了。这时我们需要梯度下降(Gradient Descent)。

    核心思想:
    想象你站在山上,想走到最低点(损失最小)。你每次往最陡的下坡方向走一小步,重复这个过程,最终到达谷底。

    求解过程:

  • 随机初始化w和b
  • 计算当前MSE的梯度(斜率)
  • 沿着梯度反方向调整w和b:w = w – α×梯度
  • 重复步骤2-3,直到MSE不再下降
  • α(学习率):每一步走多远

    • α太大:步子太大,可能错过最低点
    • α太小:收敛太慢,浪费计算资源

    优点:适合高维数据,可扩展性强
    缺点:需要调参(学习率、迭代次数)

    数学表达:
    w:=w−α⋅∂MSE∂w
    w := w – \\alpha \\cdot \\frac{\\partial \\text{MSE}}{\\partial w}
    w:=wαwMSE

    b:=b−α⋅∂MSE∂b
    b := b – \\alpha \\cdot \\frac{\\partial \\text{MSE}}{\\partial b}
    b:=bαbMSE

    其中:

    • α\\alphaα:学习率(步长,太大容易 overshoot,太小收敛慢)
    • ∂MSE∂w\\frac{\\partial \\text{MSE}}{\\partial w}wMSE:MSE对www的偏导数(梯度)

    直观理解:

    • 梯度告诉我们应该往哪个方向调整参数
    • 学习率决定我们走多大步
    • 反复迭代,直到损失不再明显下降

    在这里插入图片描述

    2.4 核心概念对比

    方法原理适用场景优点缺点
    最小二乘法 数学公式直接求解 特征少(<1000) 计算快、结果精确 高维数据计算复杂
    梯度下降 迭代优化 特征多(>1000) 通用性强、易实现 需要调参、收敛慢

    在这里插入图片描述


    第三部分:实战演练——从零实现线性回归

    环境准备

    pip install numpy pandas matplotlib scikit-learn

    3.1 第一步:生成模拟数据

    我们用代码生成一组"面积-房价"的模拟数据,方便演示。

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

    # 设置中文字体(Windows)
    # 如果是在Mac或Linux下运行,可能需要改为 'Arial Unicode MS' 或 'WenQuanYi Micro Hei'
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False

    # 设置随机种子,确保结果可复现
    np.random.seed(42)

    # 生成模拟数据:y = 3x + 5 + 噪声
    X = 2 * np.random.rand(100, 1) # 面积:0-2之间
    y = 3 * X + 5 + np.random.randn(100, 1) # 房价:3*面积+5+噪声

    print(f"数据形状: X={X.shape}, y={y.shape}")
    print(f"前5个样本:\\nX={X[:5].flatten()}\\ny={y[:5].flatten()}")

    # 可视化原始数据
    plt.figure(figsize=(8, 6))
    plt.scatter(X, y, alpha=0.6, label='原始数据')
    plt.xlabel('房屋面积 (x)')
    plt.ylabel('房价 (y)')
    plt.title('模拟房屋面积与房价关系')
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.show()

    运行结果:
    在这里插入图片描述

    运行结果分析:

    • 生成了100个样本点
    • 真实关系是 y=3x+5y = 3x + 5y=3x+5,但加了随机噪声
    • 散点图显示大致呈线性趋势

    3.2 第二步:手撕最小二乘法(解析解)

    我们自己实现最小二乘法公式,不依赖sklearn。

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

    # 设置中文字体(Windows)
    # 如果是在Mac或Linux下运行,可能需要改为 'Arial Unicode MS' 或 'WenQuanYi Micro Hei'
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False

    # 设置随机种子,确保结果可复现
    np.random.seed(42)

    # 生成模拟数据:y = 3x + 5 + 噪声
    X = 2 * np.random.rand(100, 1) # 面积:0-2之间
    y = 3 * X + 5 + np.random.randn(100, 1) # 房价:3*面积+5+噪声

    print("\\n" + "="*70)
    print("📌 方法一:手撕最小二乘法(解析解)")
    print("="*70)

    # 计算均值
    x_mean = X.mean()
    y_mean = y.mean()

    # 计算分子和分母
    # 注意:np.sum 返回的是标量 (scalar)
    numerator = np.sum((X x_mean) * (y y_mean))
    denominator = np.sum((X x_mean) ** 2)

    # 计算 w 和 b
    w_ls = numerator / denominator # 这里 w_ls 是一个标量 (float),不再是数组
    b_ls = y_mean w_ls * x_mean # 这里 b_ls 也是一个标量

    # 【修复点】:直接打印标量,不要使用 [0][0] 索引
    print(f"最小二乘法结果:")
    print(f" w (斜率) = {w_ls:.4f}")
    print(f" b (截距) = {b_ls:.4f}")
    print(f" 拟合方程: y = {w_ls:.4f} * x + {b_ls:.4f}")

    # 预测
    # numpy 支持标量与数组直接运算,无需 reshape
    y_pred_ls = w_ls * X + b_ls

    # 评估
    mse_ls = mean_squared_error(y, y_pred_ls)
    r2_ls = r2_score(y, y_pred_ls)

    print(f" MSE: {mse_ls:.4f}")
    print(f" R²: {r2_ls:.4f}")

    # 可视化
    plt.figure(figsize=(8, 6))
    plt.scatter(X, y, alpha=0.6, label='原始数据')
    # 绘制拟合线,因为 X 是有序的或者散乱的,plot 会按 X 的顺序连线
    # 为了线条平滑,通常建议对 X 排序后绘制,但这里直接用原数据也能画出折线效果
    # 如果想画直线,可以取最小和最大X值来计算两端点
    x_line = np.linspace(X.min(), X.max(), 100).reshape(1, 1)
    y_line = w_ls * x_line + b_ls

    plt.plot(x_line, y_line, 'r-', linewidth=2, label=f'最小二乘法拟合\\ny={w_ls:.2f}x+{b_ls:.2f}')
    plt.xlabel('房屋面积 (x)')
    plt.ylabel('房价 (y)')
    plt.title('最小二乘法拟合效果')
    plt.legend()
    plt.grid(True, alpha=0.3)
    plt.show()

    运行结果:

    ======================================================================
    📌 方法一:手撕最小二乘法(解析解)
    ======================================================================
    最小二乘法结果:
    w (斜率) = 2.7701
    b (截距) = 5.2151
    拟合方程: y = 2.7701 * x + 5.2151
    MSE: 0.8066
    R²: 0.7693

    在这里插入图片描述

    关键观察:

    • 学到的 w≈3w \\approx 3w3b≈5b \\approx 5b5,非常接近真实值
    • R²=0.77,说明模型解释了77%的方差,拟合效果还可以

    3.3 第三步:手撕梯度下降(迭代优化)

    现在我们用梯度下降法,从零开始迭代优化。

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

    # 设置中文字体(Windows)
    # 如果是在Mac或Linux下运行,可能需要改为 'Arial Unicode MS' 或 'WenQuanYi Micro Hei'
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False

    # 设置随机种子,确保结果可复现
    np.random.seed(42)

    # 生成模拟数据:y = 3x + 5 + 噪声
    X = 2 * np.random.rand(100, 1) # 面积:0-2之间
    y = 3 * X + 5 + np.random.randn(100, 1) # 房价:3*面积+5+噪声

    print("\\n" + "="*70)
    print("📌 方法二:手撕梯度下降(迭代优化)")
    print("="*70)

    # 初始化参数
    w_gd = np.random.randn(1, 1)
    b_gd = np.random.randn(1, 1)

    # 超参数
    learning_rate = 0.1
    n_iterations = 1000
    m = len(X) # 样本数量

    # 记录损失变化
    loss_history = []

    for iteration in range(n_iterations):
    # 预测
    y_pred = w_gd * X + b_gd

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

    # 更新参数
    w_gd = w_gd learning_rate * dw
    b_gd = b_gd learning_rate * db

    # 计算当前损失
    mse = np.mean((y_pred y) ** 2)
    loss_history.append(mse)

    if iteration % 100 == 0:
    print(f"迭代 {iteration}: MSE = {mse:.4f}, w = {w_gd[0][0]:.4f}, b = {b_gd[0][0]:.4f}")

    print(f"\\n梯度下降最终结果:")
    print(f" w (斜率) = {w_gd[0][0]:.4f}")
    print(f" b (截距) = {b_gd[0][0]:.4f}")
    print(f" 拟合方程: y = {w_gd[0][0]:.4f} * x + {b_gd[0][0]:.4f}")

    # 预测
    y_pred_gd = w_gd * X + b_gd

    # 评估
    mse_gd = mean_squared_error(y, y_pred_gd)
    r2_gd = r2_score(y, y_pred_gd)

    print(f" MSE: {mse_gd:.4f}")
    print(f" R²: {r2_gd:.4f}")

    # 可视化1:拟合效果
    plt.figure(figsize=(12, 5))

    plt.subplot(1, 2, 1)
    plt.scatter(X, y, alpha=0.6, label='原始数据')
    plt.plot(X, y_pred_gd, 'g-', linewidth=2, label=f'梯度下降拟合\\ny={w_gd[0][0]:.2f}x+{b_gd[0][0]:.2f}')
    plt.xlabel('房屋面积 (x)')
    plt.ylabel('房价 (y)')
    plt.title('梯度下降拟合效果')
    plt.legend()
    plt.grid(True, alpha=0.3)

    # 可视化2:损失下降曲线
    plt.subplot(1, 2, 2)
    plt.plot(loss_history)
    plt.xlabel('迭代次数')
    plt.ylabel('MSE损失')
    plt.title('梯度下降损失收敛过程')
    plt.grid(True, alpha=0.3)

    plt.tight_layout()
    plt.show()

    运行结果:

    ======================================================================
    📌 方法二:手撕梯度下降(迭代优化)
    ======================================================================
    迭代 0: MSE = 43.8471, w = 1.4013, b = 2.7244
    迭代 100: MSE = 0.8068, w = 2.7902, b = 5.1923
    迭代 200: MSE = 0.8066, w = 2.7708, b = 5.2144
    迭代 300: MSE = 0.8066, w = 2.7701, b = 5.2151
    迭代 400: MSE = 0.8066, w = 2.7701, b = 5.2151
    迭代 500: MSE = 0.8066, w = 2.7701, b = 5.2151
    迭代 600: MSE = 0.8066, w = 2.7701, b = 5.2151
    迭代 700: MSE = 0.8066, w = 2.7701, b = 5.2151
    迭代 800: MSE = 0.8066, w = 2.7701, b = 5.2151
    迭代 900: MSE = 0.8066, w = 2.7701, b = 5.2151

    梯度下降最终结果:
    w (斜率) = 2.7701
    b (截距) = 5.2151
    拟合方程: y = 2.7701 * x + 5.2151
    MSE: 0.8066
    R²: 0.7693

    在这里插入图片描述

    关键观察:

    • 梯度下降经过约1000次迭代后收敛
    • 最终结果与最小二乘法几乎一致
    • 损失曲线显示MSE快速下降后趋于平稳

    3.4 第四步:sklearn实现(一行代码搞定)

    实际工作中,我们直接用sklearn,省时省力。

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

    # 设置中文字体(Windows)
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False

    # 设置随机种子
    np.random.seed(42)

    # 生成模拟数据
    X = 2 * np.random.rand(100, 1)
    y = 3 * X + 5 + np.random.randn(100, 1)

    # — 方法一:最小二乘法 —
    x_mean = X.mean()
    y_mean = y.mean()
    numerator = np.sum((X x_mean) * (y y_mean))
    denominator = np.sum((X x_mean) ** 2)

    w_ls = numerator / denominator # 标量
    b_ls = y_mean w_ls * x_mean # 标量

    y_pred_ls = w_ls * X + b_ls
    mse_ls = mean_squared_error(y, y_pred_ls)
    r2_ls = r2_score(y, y_pred_ls)

    # — 方法二:梯度下降 —
    w_gd = np.random.randn(1, 1)
    b_gd = np.random.randn(1, 1)
    learning_rate = 0.1
    n_iterations = 1000
    m = len(X)
    loss_history = []

    for iteration in range(n_iterations):
    y_pred = w_gd * X + b_gd
    dw = (2/m) * np.dot(X.T, (y_pred y))
    db = (2/m) * np.sum(y_pred y)
    w_gd = w_gd learning_rate * dw
    b_gd = b_gd learning_rate * db
    mse = np.mean((y_pred y) ** 2)
    loss_history.append(mse)

    y_pred_gd = w_gd * X + b_gd
    mse_gd = mean_squared_error(y, y_pred_gd)
    r2_gd = r2_score(y, y_pred_gd)

    # — 方法三:sklearn —
    model = LinearRegression()
    model.fit(X, y)
    w_sklearn = model.coef_[0][0]
    b_sklearn = model.intercept_[0] # 注意:新版sklearn intercept_可能是标量,旧版是数组,这里兼容处理
    if isinstance(b_sklearn, np.ndarray):
    b_sklearn = b_sklearn[0]

    y_pred_sklearn = model.predict(X)
    mse_sklearn = mean_squared_error(y, y_pred_sklearn)
    r2_sklearn = r2_score(y, y_pred_sklearn)

    # — 打印对比表格 (修复点在这里) —
    print("\\n" + "="*70)
    print("📊 三种方法结果对比")
    print("="*70)
    print(f"{'方法':<15} {'w (斜率)':<12} {'b (截距)':<12} {'MSE':<10} {'R²':<10}")
    print("-"*60)

    # 【修复】:直接使用变量名,不要加 [0][0],因为 w_ls 和 b_ls 已经是标量了
    print(f"{'最小二乘法':<15} {w_ls:<12.4f} {b_ls:<12.4f} {mse_ls:<10.4f} {r2_ls:<10.4f}")

    # 梯度下降的结果 w_gd 和 b_gd 仍然是数组 (1,1),所以保留 [0][0]
    print(f"{'梯度下降':<15} {w_gd[0][0]:<12.4f} {b_gd[0][0]:<12.4f} {mse_gd:<10.4f} {r2_gd:<10.4f}")

    # sklearn 的结果我们上面已经提取为标量了
    print(f"{'sklearn':<15} {w_sklearn:<12.4f} {b_sklearn:<12.4f} {mse_sklearn:<10.4f} {r2_sklearn:<10.4f}")

    print("="*60)
    print("✅ 三种方法结果高度一致!")

    运行结果:

    ======================================================================
    📊 三种方法结果对比
    ======================================================================
    方法 w (斜率) b (截距) MSE R²
    ————————————————————
    最小二乘法 2.7701 5.2151 0.8066 0.7693
    梯度下降 2.7701 5.2151 0.8066 0.7693
    sklearn 2.7701 5.2151 0.8066 0.7693
    ============================================================
    ✅ 三种方法结果高度一致!


    第四部分:进阶——多元线性回归实战

    现实世界中,影响房价的不只是面积,还有房龄、地段、楼层等多个因素。这就是多元线性回归。

    4.1 多元线性回归公式

    y=w1⋅x1+w2⋅x2+…+wn⋅xn+b
    y = w_1 \\cdot x_1 + w_2 \\cdot x_2 + … + w_n \\cdot x_n + b
    y=w1x1+w2x2++wnxn+b

    写成矩阵形式:
    y=X⋅w+b
    \\mathbf{y} = \\mathbf{X} \\cdot \\mathbf{w} + b
    y=Xw+b

    4.2 实战代码:预测波士顿房价(简化版)

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

    # 设置中文字体(Windows)
    # 如果是在Mac或Linux下运行,可能需要改为 'Arial Unicode MS' 或 'WenQuanYi Micro Hei'
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False

    print("\\n" + "="*70)
    print("📌 进阶:多元线性回归实战")
    print("="*70)

    # 加载糖尿病数据集(替代波士顿房价,因为波士顿数据集已被弃用)
    diabetes = load_diabetes()
    X_multi = diabetes.data # 10个特征
    y_multi = diabetes.target # 疾病进展指标

    print(f"数据集形状: X={X_multi.shape}, y={y_multi.shape}")
    print(f"特征名称: {diabetes.feature_names}")

    # 划分训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(
    X_multi, y_multi, test_size=0.2, random_state=42
    )

    print(f"训练集: {X_train.shape}, 测试集: {X_test.shape}")

    # 训练模型
    model_multi = LinearRegression()
    model_multi.fit(X_train, y_train)

    # 预测
    y_train_pred = model_multi.predict(X_train)
    y_test_pred = model_multi.predict(X_test)

    # 评估
    train_mse = mean_squared_error(y_train, y_train_pred)
    test_mse = mean_squared_error(y_test, y_test_pred)
    train_r2 = r2_score(y_train, y_train_pred)
    test_r2 = r2_score(y_test, y_test_pred)

    print(f"\\n多元线性回归结果:")
    print(f" 训练集 MSE: {train_mse:.2f}, R²: {train_r2:.4f}")
    print(f" 测试集 MSE: {test_mse:.2f}, R²: {test_r2:.4f}")

    print(f"\\n学到的权重系数:")
    for i, (name, coef) in enumerate(zip(diabetes.feature_names, model_multi.coef_)):
    print(f" {name}: {coef:.4f}")
    print(f" 截距 b: {model_multi.intercept_:.4f}")

    # 可视化:真实值 vs 预测值
    plt.figure(figsize=(10, 5))

    plt.subplot(1, 2, 1)
    plt.scatter(y_train, y_train_pred, alpha=0.6)
    plt.plot([y_train.min(), y_train.max()], [y_train.min(), y_train.max()], 'r–', linewidth=2)
    plt.xlabel('真实值 (训练集)')
    plt.ylabel('预测值 (训练集)')
    plt.title('训练集:真实值 vs 预测值')
    plt.grid(True, alpha=0.3)

    plt.subplot(1, 2, 2)
    plt.scatter(y_test, y_test_pred, alpha=0.6, color='orange')
    plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r–', linewidth=2)
    plt.xlabel('真实值 (测试集)')
    plt.ylabel('预测值 (测试集)')
    plt.title('测试集:真实值 vs 预测值')
    plt.grid(True, alpha=0.3)

    plt.tight_layout()
    plt.show()

    运行结果:

    ======================================================================
    📌 进阶:多元线性回归实战
    ======================================================================
    数据集形状: X=(442, 10), y=(442,)
    特征名称: ['age', 'sex', 'bmi', 'bp', 's1', 's2', 's3', 's4', 's5', 's6']
    训练集: (353, 10), 测试集: (89, 10)

    多元线性回归结果:
    训练集 MSE: 2868.55, R²: 0.5279
    测试集 MSE: 2900.19, R²: 0.4526

    学到的权重系数:
    age: 37.9040
    sex: -241.9644
    bmi: 542.4288
    bp: 347.7038
    s1: -931.4888
    s2: 518.0623
    s3: 163.4200
    s4: 275.3179
    s5: 736.1989
    s6: 48.6707
    截距 b: 151.3456

    在这里插入图片描述

    运行结果分析:

    • 多元线性回归同时考虑10个特征
    • 训练集R²约0.52,测试集R²约0.45,有一定泛化能力
    • 散点图越靠近对角线,预测越准确

    第五部分:完整的线性回归代码模板

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

    # 设置中文字体(Windows)
    # 如果是在Mac或Linux下运行,可能需要改为 'Arial Unicode MS' 或 'WenQuanYi Micro Hei'
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False

    def linear_regression_demo():
    print("="*70)
    print("🚀 线性回归完整流程演示")
    print("="*70)

    # 1. 生成/加载数据
    np.random.seed(42)
    X = 2 * np.random.rand(100, 1)
    y = 3 * X + 5 + np.random.randn(100, 1)

    # 2. 划分数据集
    X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
    )

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

    # 4. 预测
    y_train_pred = model.predict(X_train)
    y_test_pred = model.predict(X_test)

    # 5. 评估
    train_mse = mean_squared_error(y_train, y_train_pred)
    test_mse = mean_squared_error(y_test, y_test_pred)
    train_r2 = r2_score(y_train, y_train_pred)
    test_r2 = r2_score(y_test, y_test_pred)

    print(f"\\n模型参数:")
    print(f" w = {model.coef_[0][0]:.4f}")
    print(f" b = {model.intercept_[0]:.4f}")
    print(f"\\n评估结果:")
    print(f" 训练集 MSE: {train_mse:.4f}, R²: {train_r2:.4f}")
    print(f" 测试集 MSE: {test_mse:.4f}, R²: {test_r2:.4f}")

    # 6. 可视化
    plt.figure(figsize=(12, 5))

    plt.subplot(1, 2, 1)
    plt.scatter(X_train, y_train, alpha=0.6, label='训练数据')
    plt.scatter(X_test, y_test, alpha=0.6, label='测试数据', color='orange')
    plt.plot(X, model.predict(X), 'r-', linewidth=2, label='拟合直线')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.title('线性回归拟合效果')
    plt.legend()
    plt.grid(True, alpha=0.3)

    plt.subplot(1, 2, 2)
    plt.scatter(y_test, y_test_pred, alpha=0.6)
    plt.plot([y_test.min(), y_test.max()],
    [y_test.min(), y_test.max()], 'r–', linewidth=2)
    plt.xlabel('真实值')
    plt.ylabel('预测值')
    plt.title('测试集:真实值 vs 预测值')
    plt.grid(True, alpha=0.3)

    plt.tight_layout()
    plt.show()

    if __name__ == "__main__":
    linear_regression_demo()

    运行结果:

    ======================================================================
    🚀 线性回归完整流程演示
    ======================================================================

    模型参数:
    w = 2.7993
    b = 5.1429

    评估结果:
    训练集 MSE: 0.8477, R²: 0.7582
    测试集 MSE: 0.6537, R²: 0.8072

    在这里插入图片描述

    第六部分:常见问题与解答

    Q1:线性回归只能处理直线关系吗?

    A: 不是!通过特征变换,线性回归可以拟合曲线。

    # 例子:拟合抛物线
    X = np.random.uniform(3, 3, 100)
    y = X**2 + np.random.randn(100) * 0.5

    # 添加平方特征
    X_poly = np.column_stack([X, X**2])
    model = LinearRegression()
    model.fit(X_poly, y)

    print(f"学习到的关系: y = {model.coef_[0]:.2f}x + {model.coef_[1]:.2f}x² + {model.intercept_:.2f}")

    Q2:什么时候不能用线性回归?

  • 非线性关系太强:比如周期性数据
  • 存在多重共线性:特征之间高度相关
  • 异常值太多:线性回归对异常值敏感
  • 数据量太少:容易过拟合
  • Q3:R²是什么意思?

    **R²(决定系数)**表示模型解释了目标变量多少方差:

    • R²=1:完美拟合
    • R²=0:不如直接用平均值
    • R²<0:比直接用平均值还差

    Q4:梯度下降的学习率怎么选?

    • 太大:可能震荡不收敛
    • 太小:收敛太慢
    • 常用值:0.01、0.001、0.0001,可以试试逐步衰减

    在这里插入图片描述


    写在最后:线性回归教会我们的事

    线性回归看似简单,但它蕴含了机器学习的三大核心思想:

  • 假设驱动:先假设数据符合某种规律(线性关系)
  • 损失量化:用数学公式衡量预测有多"错"
  • 优化求解:通过算法不断调整参数,让错误最小
  • 这些思想,在深度学习、强化学习等高级模型中依然适用。学好线性回归,不是终点,而是起点。

    在这里插入图片描述


    📌 核心要点回顾

  • 线性回归公式:y=w⋅x+by = w \\cdot x + by=wx+b
  • 损失函数:MSE(均方误差),越小越好
  • 两种求解方法:
    • 最小二乘法:解析解,适合简单模型
    • 梯度下降:迭代优化,适合复杂模型
  • 评估指标:
    • MSE:平均平方误差
    • R²:决定系数,越接近1越好
  • sklearn使用:model = LinearRegression()
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)

  • 关键技巧:
    • 一定要划分训练集和测试集
    • 关注R²和MSE,判断模型好坏
    • 可视化帮助理解模型表现
  • 在这里插入图片描述


    下一步学习建议:

    • ✅ 搞懂线性回归后,可以学习**正则化(Ridge/Lasso)**防止过拟合
    • ✅ 然后进入逻辑回归,解决分类问题
    • ✅ 再逐步深入决策树、随机森林、神经网络

    记住:所有复杂的模型,都始于一条简单的直线。

    希望这篇实战指南对你有帮助!所有代码都可以直接复制运行。如果你有任何问题,欢迎在评论区留言讨论!

    赞(0)
    未经允许不得转载:171主机测评 » 进阶篇-机器学习篇-6--什么是线性回归?从原理到代码,彻底搞懂
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址