手写梯度下降拟合一条直线
不用 sklearn,用梯度下降从零拟合
学完本案例你将理解:不需要闭式解,只要会求梯度,参数就能自动收敛到最优值。
生活引入
投篮练习——每次调整一点角度
你站在三分线外投篮。第一次偏左了——下次往右调一点。第二次偏右了——再往左调一点。每次投完,你看一眼偏差,朝减小偏差的方向调整姿势。
机器学习训练完全一样:每次算完预测值,看一眼和真实值的差距(损失),然后朝减小差距的方向调整参数(梯度下降)。重复几百次,姿势就定型了。
直观理解
我们的目标是找到一条直线
如果从
数学定义
Python 动手实践
实例
python
import numpy as np
np.random.seed(0)
# 生成带噪声的线性数据:真实 y = 2x + 1
n = 60
x = np.random.uniform(-3, 3, n)
y = 2 * x + 1 + np.random.randn(60) * 0.8
# 手推梯度函数(对 w 和 b 分别求偏导)
def compute_gradients(w, b, x, y):
y_pred = w * x + b
error = y_pred - y # 预测值 - 真实值
dw = np.mean(2 * error * x) # dL/dw
db = np.mean(2 * error) # dL/db
return dw, db
# 梯度下降主循环
w, b = 0.0, 0.0 # 初始参数故意设成 0
lr = 0.05
epochs = 100
print("RUNOOB 梯度下降过程 (真实值 w=2, b=1):")
for epoch in range(epochs):
y_pred = w * x + b
loss = np.mean((y_pred - y) ** 2)
dw, db = compute_gradients(w, b, x, y)
w -= lr * dw
b -= lr * db
if epoch % 20 == 0:
print(f" epoch {epoch:3d} loss={loss:.4f} w={w:.3f} b={b:.3f}")
print(f"\nRUNOOB 最终: w={w:.3f}, b={b:.3f} (真实 w=2, b=1)")
print(f"拟合直线: y = {w:.2f}x + {b:.2f}")python
RUNOOB 梯度下降过程 (真实值 w=2, b=1):
epoch 0 loss=13.4515 w=0.790 b=0.057
epoch 20 loss=0.9165 w=1.868 b=0.785
epoch 40 loss=0.7316 w=1.949 b=0.918
epoch 60 loss=0.7083 w=1.971 b=0.956
epoch 80 loss=0.7055 w=1.977 b=0.967
epoch 100 loss=0.7052 w=1.979 b=0.970
RUNOOB 最终: w=1.979, b=0.970 (真实 w=2, b=1)
拟合直线: y = 1.98x + 0.97AI 中的应用场景
这个案例的代码骨架就是所有深度学习训练的模板:前向计算预测值 → 计算损失 → 反向传播求梯度 → 更新参数 → 重复。PyTorch 中的 optimizer.step() 和 loss.backward() 就是自动化了这个过程。
AI 思考中...