【深度学习教程——01_深度基石(Foundation)】01_机器如何自动学习?线性模型与梯度下降
01_机器如何自动学习?线性模型与梯度下降
本章目标:不使用任何深度学习框架,仅用 Python 原生代码手动实现线性回归。从"暴力穷举"到"梯度下降",理解机器"学习"的本质。
📖 目录 (Table of Contents)
- 问题定义:从一组考试分数说起
- 直觉:我们在寻找什么?
- 方法一:暴力穷举 (Exhaustive Search)
- 方法二:梯度下降 (Gradient Descent)
- 进阶:Batch GD vs Stochastic GD
- 总结与预告
1. 问题定义:从一组考试分数说起
假设我们有一组简单的学习时间 ( x x x) 和考试分数 ( y y y) 的数据:
| 学习时间 ( x x x) | 考试分数 ( y y y) |
|---|---|
| 1 小时 | 2 分 |
| 2 小时 | 4 分 |
| 3 小时 | 6 分 |
核心任务:让机器找到 x x x 和 y y y 之间的关系,并预测:学习 4 小时能得多少分?
作为人类,你一眼就能看出规律是 y = 2 x y = 2x y=2x。但在机器的眼中,数据只是一堆数字。它最开始可能会瞎猜 y = 0.5 x y = 0.5x y=0.5x 或者 y = 100 x y = 100x y=100x。
所谓的"机器学习",就是让计算机通过不断试错,自动把参数校准到 2.0 2.0 2.0 的过程。
2. 直觉:我们在寻找什么?
为了简化问题,我们假设模型是一个简单的线性函数(不带偏置 b b b):
y ^ = x ⋅ ω \hat{y} = x \cdot \omega y^=x⋅ω
- x x x: 输入数据 (Input)
- ω \omega ω: 权重 (Weight) —— 这就是我们要找的"魔法数字"。
- y ^ \hat{y} y^: 模型的预测值 (Prediction)
我们需要一个标准来衡量模型猜得"准不准"。这就引入了 损失函数 (Loss Function)。在线性回归中,最常用的是 均方误差 (MSE, Mean Square Error):
L o s s = ( y ^ − y ) 2 = ( x ⋅ ω − y ) 2 Loss = (\hat{y} - y)^2 = (x \cdot \omega - y)^2 Loss=(y^−y)2=(x⋅ω−y)2
看看下面这张图,理解"残差"(预测值与真实值的距离)是如何构成 Loss 的:

图解说明:
- 蓝点:真实数据 (1,2), (2,4), (3,6)。
- 黄线:当前的猜测模型 y = 1.2 x y = 1.2x y=1.2x。
- 红虚线:残差 (Residuals)。
- x = 1 x=1 x=1: 预测 1.2 1.2 1.2,真实 2.0 2.0 2.0,误差 0.8 0.8 0.8。
- x = 2 x=2 x=2: 预测 2.4 2.4 2.4,真实 4.0 4.0 4.0,误差 1.6 1.6 1.6。
- x = 3 x=3 x=3: 预测 3.6 3.6 3.6,真实 6.0 6.0 6.0,误差 2.4 2.4 2.4。
- Loss: 就是这三根红线的长度平方和 (MSE)。
3. 方法一:暴力穷举 (Exhaustive Search)
在不知道怎么"智能"优化之前,最简单粗暴的方法就是:把所有可能的 w w w 都试一遍!
让我们画出 w w w 从 0.0 0.0 0.0 到 4.0 4.0 4.0 变化时,Loss 的变化曲线。
🐍 代码实现 (Exhaustive Search)
import numpy as np
import matplotlib.pyplot as plt
# 1. 准备数据 (Training Set)
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
# 2. 定义模型 (Model)
def forward(x, w):
return x * w
# 3. 定义损失函数 (Loss Function)
def loss(x, y, w):
y_pred = forward(x, w)
return (y_pred - y) ** 2
# 4. 穷举过程
w_list = []
mse_list = []
print("开始穷举...")
for w in np.arange(0.0, 4.1, 0.1):
print(f"w={w:.1f}")
l_sum = 0
for x_val, y_val in zip(x_data, y_data):
y_pred_val = forward(x_val, w)
l = loss(x_val, y_val, w)
l_sum += l
print(f"\tval: {x_val}, {y_val}, pred: {y_pred_val:.2f}, loss: {l:.2f}")
mse = l_sum / 3 # 计算平均损失
w_list.append(w)
mse_list.append(mse)
# 5. 画图 (Visualization)
# plt.plot(w_list, mse_list)
# plt.show()
运行这段代码,你会得到一个完美的U型曲线(抛物线)。这就引出了深度学习中最著名的概念 —— Loss Surface (损失曲面)。
4. 方法二:梯度下降 (Gradient Descent)
穷举法在 w w w 只有一个时还能用。但现代神经网络动辄上亿个参数,穷举法会让计算机算到宇宙毁灭。我们需要一种贪心算法,能告诉我们:“别瞎试了,往右走一步就能变好!”
这就是 梯度下降。
4.1 数学推导:梯度的物理意义
想象你被蒙住双眼放在一个山谷里。你想下山(由高 Loss 走向低 Loss)。
你的脚能感觉到地面的坡度。
- 如果左边高右边低(斜率为负),你就往右走。
- 如果右边高左边低(斜率为正),你就往左走。
数学上,这个"坡度"就是导数(梯度):
- 损失函数:
L o s s = ( x ⋅ ω − y ) 2 Loss = (x \cdot \omega - y)^2 Loss=(x⋅ω−y)2 - 求导(根据链式法则):
∂ L o s s ∂ ω = 2 ⋅ ( x ⋅ ω − y ) ⋅ x \frac{\partial Loss}{\partial \omega} = 2 \cdot (x \cdot \omega - y) \cdot x ∂ω∂Loss=2⋅(x⋅ω−y)⋅x - 权重更新公式:
ω n e w = ω o l d − η ⋅ ∂ L o s s ∂ ω \omega_{new} = \omega_{old} - \eta \cdot \frac{\partial Loss}{\partial \omega} ωnew=ωold−η⋅∂ω∂Loss
为什么要减去梯度?
- 当 w = 0 w=0 w=0 时,斜率是负的(指向下方)。
- − η ⋅ ( 负数 ) = 正数 -\eta \cdot (\text{负数}) = \text{正数} −η⋅(负数)=正数。所以 w w w 会增加,向右移动。
- 反之亦然。这个负号是梯度下降的核心。
4.2 代码实战:手撕梯度下降
我们要用代码实现这个公式。
# 初始权重随便猜,比如 1.0
w = 1.0
# 前向传播
def forward(x):
return x * w
# 【核心】梯度计算 (手动求导公式)
def gradient(x, y):
return 2 * x * (x * w - y)
# 训练配置
learning_rate = 0.01 # 步长 (Learning Rate)
print("Predict (before training)", 4, forward(4))
# 开始训练 100 轮
for epoch in range(100):
for x_val, y_val in zip(x_data, y_data):
# 1. 计算梯度 (grad)
grad = gradient(x_val, y_val)
# 2. 更新权重 (Update)
w = w - learning_rate * grad
print(f"\tgrad: {x_val}, {y_val}, grad: {grad:.2f}")
# 计算当前 Loss 仅仅为了观察
l_sum = 0
for x_val, y_val in zip(x_data, y_data):
l_sum += loss(x_val, y_val, w)
print(f"Epoch: {epoch}, w={w:.3f}, loss={l_sum/3:.3f}")
print("Predict (after training)", 4, forward(4))
运行结果:
Epoch: 99, w=1.999, loss=0.000
Predict (after training) 4 7.9999
机器成功找到了 w ≈ 2.0 w \approx 2.0 w≈2.0!
5. 进阶:Batch GD vs Stochastic GD
- Batch Gradient Descent (BGD): 全班同学(所有样本)都发完言,取平均意见,再走一步。稳,但慢。
- Stochastic Gradient Descent (SGD): 听一个同学发言,就走一步。快,但抖。
- Mini-Batch SGD: 折中方案。听一组同学发言。这是深度学习的主流。
6. 总结与预告
本章我们完成了一个壮举:不依赖任何框架,从零实现了机器学习的核心逻辑。
- Model: y ^ = x ⋅ w \hat{y} = x \cdot w y^=x⋅w
- Loss: MSE
- Optimization: 梯度下降
现在的痛点:
这里的梯度公式 2 * x * (x * w - y) 是我们手算的。如果模型变成了复杂的神经网络(几十层),手算梯度几乎是不可能的。
下一章预告:
我们将引入 反向传播 (Backpropagation) —— 神经网络自动求导的秘密武器。我们将看到计算图是如何像"传话游戏"一样,把梯度这一层层传回来的。
更多推荐

所有评论(0)