从机器学习的角度实现 excel 中趋势线:揭秘梯度下降过程

1. 引言:Excel 的"一键魔法"背后藏着什么智慧?

在 Excel 中,我们只需右键 → 添加趋势线,一条完美的直线就出现了。它快得像魔法,但魔法背后,是数学的严谨。

今天,我们不关心 Excel 内部用了什么算法可能是解析法),而是要问:

如果机器一开始'什么都不知道',它该怎么一步步'学会'画出这条线?


2. 我们的任务:预测一个简单的线性关系

假设我们有一组数据,它们大致遵循 y = 2x + 1 的规律,但有一些随机噪声(模拟真实世界的测量误差)。

我们的目标:仅凭这10个数据点,让机器"学会"这个规律,找到最佳的 a(斜率)和 b(截距)


3. 准备数据:10 个"玩具"样本

我们用 Python 生成这10个数据点:

python 复制代码
import numpy as np
import matplotlib.pyplot as plt

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

# 生成 10 个 x 值,从 1 到 10
x = np.arange(1, 11)  # [1, 2, 3, ..., 10]

# 生成 y 值:y = 2x + 1 + 噪声
true_a, true_b = 2, 1
noise = np.random.normal(0, 0.5, size=x.shape)  # 添加标准差为 0.5 的高斯噪声
y = true_a * x + true_b + noise

# 查看数据
print("x:", x)
print("y:", np.round(y, 2))  # 保留两位小数

输出

python 复制代码
x: [ 1  2  3  4  5  6  7  8  9 10]
y: [ 3.25  4.93  7.32  9.76 10.88 12.88 15.79 17.38 18.77 21.27]

关键点 :真实规律是 y = 2x + 1,但数据有噪声,所以 y 值不完全精确。


4. 可视化:我们的目标是什么?

让我们画出这些数据点,并标出真实的线(y=2x+1):

python 复制代码
plt.figure(figsize=(8, 6))
plt.scatter(x, y, color='blue', label='真实数据点', s=50)
# 画出真实规律的线
x_line = np.linspace(0, 11, 100)
y_line = true_a * x_line + true_b
plt.plot(x_line, y_line, 'g--', label=f'真实规律 y={true_a}x+{true_b}', linewidth=2)

plt.xlabel('x')
plt.ylabel('y')
plt.title('我们的"学习"任务:根据10个数据点,找到最佳拟合线')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

我们的任务就是:仅从这些蓝色散点,让机器找到一条最接近绿色虚线的直线


5. 模型定义:y_pred = a * x + b

我们假设模型的形式是:

python 复制代码
y_pred = a * x + b
  • a:斜率(slope)
  • b:截距(intercept)
  • 初始时,我们不知道 ab 是多少,可以先猜一个值,比如 a=0, b=0

6. 损失函数:我们"错"了多少?

我们需要一个"尺子"来衡量预测的好坏。用均方误差 (MSE)

python 复制代码
MSE = (1/n) * Σ(y - y_pred)²

代码实现:

复制代码
def compute_mse(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)

# 初始猜测:a=0, b=0
a, b = 0.0, 0.0
y_pred_initial = a * x + b
initial_loss = compute_mse(y, y_pred_initial)
print(f"初始损失 (a=0, b=0): {initial_loss:.3f}")
python 复制代码
初始损失 (a=0, b=0): 182.431

解释 :损失很大,因为 y_pred 全是 0,和真实 y 差很远。

7. 核心:梯度下降------如何"学习"?

现在,我们教模型如何"学习":

  • 比喻:你在浓雾中的山坡上,想找到谷底(损失最小的地方)。你看不见路,但能感觉到脚下的坡度(梯度)。你每次都向坡度最陡的下坡方向走一步(更新参数),一步步接近谷底。

  • 数学计算 (对 ab 求偏导):

    • ∂MSE/∂a = (2/n) * Σ((a*x + b - y) * x)
    • ∂MSE/∂b = (2/n) * Σ(a*x + b - y)
  • 更新规则

    • a = a - learning_rate * ∂MSE/∂a
    • b = b - learning_rate * ∂MSE/∂b

8. 动手实现:手动训练模型
python 复制代码
# 超参数
learning_rate = 0.01  # 学习率,步长
epochs = 10000           # 训练轮数

# 初始化参数
a, b = 0.0, 0.0

# 记录历史,用于画图
loss_history = []
a_history = []
b_history = []

for i in range(epochs):
    # 前向:计算预测值
    y_pred = a * x + b
    
    # 计算损失
    loss = compute_mse(y, y_pred)
    loss_history.append(loss)
    a_history.append(a)
    b_history.append(b)
    
    # 计算梯度
    n = len(x)
    da = (2 / n) * np.sum((y_pred - y) * x)  # 注意:y_pred - y
    db = (2 / n) * np.sum(y_pred - y)
    
    # 更新参数
    a = a - learning_rate * da
    b = b - learning_rate * db
    
    # 打印进度
    if (i+1) % 1000 == 0:
        print(f"第 {i+1} 轮: a={a:.3f}, b={b:.3f}, 损失={loss:.3f}")

print(f"\n训练完成!")
print(f"我们的模型找到: a ≈ {a:.3f}, b ≈ {b:.3f}")
print(f"真实规律是: a = {true_a}, b = {true_b}")

输出

python 复制代码
第 100 轮: a=2.054, b=0.840, 损失=0.153
第 200 轮: a=2.021, b=1.070, 损失=0.124
第 300 轮: a=2.007, b=1.168, 损失=0.119
第 400 轮: a=2.001, b=1.211, 损失=0.118
第 500 轮: a=1.999, b=1.229, 损失=0.118
第 600 轮: a=1.997, b=1.237, 损失=0.118
第 700 轮: a=1.997, b=1.240, 损失=0.118
第 800 轮: a=1.997, b=1.242, 损失=0.118
第 900 轮: a=1.997, b=1.243, 损失=0.118
第 1000 轮: a=1.997, b=1.243, 损失=0.118

训练完成!
我们的模型找到: a ≈ 1.997, b ≈ 1.243
真实规律是: a = 2, b = 1

看! 模型通过1000次迭代,a 从 0 逐渐接近 2,b 接近 1,损失不断下降。


9. 可视化学习过程
  • 损失下降曲线
python 复制代码
plt.plot(loss_history)
plt.xlabel('训练轮数 (Epoch)')
plt.ylabel('损失 (MSE)')
plt.title('损失随训练过程下降')
plt.grid(True, alpha=0.3)
plt.show()
  • 参数变化过程
python 复制代码
plt.plot(a_history, label='a (斜率)')
plt.plot(b_history, label='b (截距)')
plt.axhline(y=true_a, color='g', linestyle='--', label='真实 a')
plt.axhline(y=true_b, color='r', linestyle='--', label='真实 b')
plt.xlabel('训练轮数')
plt.ylabel('参数值')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
  • 最终拟合结果
python 复制代码
plt.figure(figsize=(8, 6))
plt.scatter(x, y, color='blue', label='真实数据点', s=50)
plt.plot(x_line, y_line, 'g--', label=f'真实规律 y={true_a}x+{true_b}', linewidth=2)
plt.plot(x_line, a * x_line + b, 'r-', label=f'拟合线 y={a:.2f}x+{b:.2f}', linewidth=2)
plt.xlabel('x')
plt.ylabel('y')
plt.title('梯度下降拟合结果')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
  • excel拟合结果
10. 对比专业工具:Scikit-learn

让我们看看专业的机器学习库 scikit-learn 是怎么做的:

python 复制代码
from sklearn.linear_model import LinearRegression

# 注意:sklearn 需要 2D 输入
X = x.reshape(-1, 1)

model = LinearRegression()
model.fit(X, y)

print(f"Scikit-learn 结果: 斜率 a = {model.coef_[0]:.3f}, 截距 b = {model.intercept_:.3f}")

输出

python 复制代码
Scikit-learn 结果: 斜率 a = 1.997, 截距 b = 1.243

完全一致! 我们手动实现的梯度下降,和 sklearn 的结果一样。


附. 深入理解:梯度下降 vs 解析法------殊途同归的两种智慧

你可能会问:"我们手动实现的梯度下降,和 scikit-learnLinearRegression,是同一种方法吗?"

答案是:不是。 它们在求解方式、数学基础和适用场景上有本质区别。但最终结果一致,是因为它们都在寻找同一个"最优解"。

下面,我们来揭开这个"黑箱"。


一、核心原理:迭代逼近 vs 数学解析
方法 核心思想 求解方式
手动梯度下降 逐步"试错",像盲人下山,一步步逼近最优解。 迭代法:重复"计算梯度 → 更新参数"直到收敛。
scikit-learn LinearRegression 直接用数学公式算出理论最优解,一步到位。 解析法(闭式解) :通过公式 w = (XᵀX)⁻¹Xᵀy 直接计算。
1. 手动梯度下降(迭代法)
  • 数学逻辑

    • 定义损失函数(MSE):

    • 计算梯度(偏导数):

    • 更新参数: (η 为学习率)

  • 特点

    • 近似解:需要足够迭代才能接近最优。

    • 适用于大数据:可分批处理(如随机梯度下降)。

    • 需调参:学习率、迭代次数等。

2. scikit-learn LinearRegression(解析法)
  • 数学逻辑

    • 将问题表示为矩阵形式:

    • 最优参数 ww 的闭式解为:

      这个公式是通过对损失函数求导并令其为 0 推导出的理论最优解

  • 特点

    • 精确解:无需迭代,一步到位。

    • 计算复杂度高:矩阵求逆的复杂度为 O(n3)O(n3),特征数多时很慢。

    • 无超参数:直接计算,无需调学习率。


二、关键差异对比
维度 梯度下降(迭代法) LinearRegression(解析法)
求解方式 逐步迭代逼近 直接公式计算
结果性质 近似解(可无限接近) 理论最优解
计算效率 大数据更高效 特征多时慢
超参数依赖 需调学习率、迭代次数 无超参数
适用场景 大数据、高维(如深度学习) 小数据、低维(如本例)
数值稳定性 受学习率影响 受多重共线性影响

三、为什么结果能一致?------ 殊途同归

尽管方法不同,但我们的手动实现和 sklearn 结果几乎一致,原因在于:

梯度下降的迭代过程,本质上是在数学上"收敛于"解析法的最优解。

就像用牛顿法求方程的根:虽然是迭代过程,但最终会无限接近理论上的精确解。

在本例中,由于数据量小、特征少,解析法高效且精确。而梯度下降通过300次迭代,也成功逼近了这个最优解。


四、通俗类比
  • 梯度下降 :像盲人下山,通过感受坡度,一步步向下走,最终到达谷底,适用于复杂、大规模问题,是深度学习的基石。
  • 解析法 :像使用 GPS,直接定位谷底坐标,一步到位,适用于简单、小规模问题,高效精确。

两种方法最终会到达同一个"山底",只是路径和效率不同。

相关推荐
Uncommon.4 分钟前
线性代数与向量
pytorch·python·线性代数·机器学习
bitbrowser9 小时前
giffgaff突然停用?先分清闲置停用和长期境外断开
笔记
九硕智慧建筑一体化厂家10 小时前
数字化管控落地,直流照明构筑安全照明体系
运维·人工智能·笔记·安全·智慧城市
AI云海10 小时前
天幕红尘笔记
笔记
云和数据.ChenGuang10 小时前
fastapi的参数剖析
人工智能·深度学习·机器学习·语言模型·状态模式·fastapi
Eloudy11 小时前
LLM agent 分拆任务的能力来源
人工智能·机器学习
青山是哪个青山13 小时前
LangChain 学习笔记(三):LangSmith 调试与监控
笔记·学习·langchain
倔强的石头10613 小时前
【机器学习】机器学习三大范式_监督无监督强化学习概览
人工智能·机器学习
watersink14 小时前
机器学习最大熵模型max_entropy_model
人工智能·机器学习