<p>梯度下降更新公式为 theta = theta - learning_rate * gradient,其中 gradient 必须是当前参数下损失函数对 theta 的真实偏导,且需特征归一化、合理设 learning_rate 与 batch_size 才能稳定收敛。</p>

梯度下降更新公式怎么写才不跑偏
梯度下降本质是用负梯度方向去逼近损失最小点,关键不是“写出来”,而是每一步更新是否真的在减小损失。常见错误是直接套公式但忘了 learning_rate 太大导致发散,或没对特征做归一化让梯度方向歪掉。
-
theta = theta - learning_rate * gradient是通用形式,但gradient必须是当前参数下的真实梯度(比如对loss关于theta求偏导) - 线性回归中,
gradient就是X.T @ (X @ theta - y) / m(批量),注意除以样本数m保证梯度量级稳定 - 如果
X各列量纲差十倍(比如年龄 vs 收入),梯度会严重偏向大数值特征,训练抖动甚至不收敛——必须先做StandardScaler或手动归一化 - 用
np.allclose(loss_history[-2:], atol=1e-6)判断收敛比固定迭代次数更可靠
批量梯度下降(BGD)的 Python 实现要点
BGD 每次用全部数据算梯度,更新稳但慢,适合小数据集或需要精确解的场景。容易被忽略的是矩阵运算维度和内存占用。
- 输入
X应为(m, n),y为(m, 1)或(m,);若y是一维,X @ theta - y会触发广播,但结果仍是正确形状 - 别写
for i in range(m): grad += ...——纯 Python 循环太慢,必须用向量化:grad = X.T @ (X @ theta - y) / m - 如果
m超过 10 万,X.T @ X可能爆内存,此时即使叫“批量”,也得切块或换 SGD - 示例核心片段:
theta = np.zeros((X.shape[1], 1))<br>for _ in range(max_iter):<br> pred = X @ theta<br> grad = X.T @ (pred - y) / len(y)<br> theta -= lr * grad
随机梯度下降(SGD)为什么 loss 曲线跳得厉害
SGD 每次只用一个样本算梯度,更新快、省内存,但梯度噪声大,loss 不单调下降是正常现象,不是 bug。
- 不能直接用
np.random.choice每次抽一个——那样可能漏样本或重复太多;应先np.random.shuffle(indices),再按序遍历 - 学习率必须衰减,比如
lr = lr0 / (1 + decay * t),否则后期更新幅度过大会绕着最优点打转 - 单样本梯度是
x_i.T @ (x_i @ theta - y_i)(无除法),注意x_i是行向量,需转成列向量再参与运算,否则shape报错 - 验证时别用单个样本算 loss,要用全量或 mini-batch 验证,否则评估失真
mini-batch SGD 怎么设 batch_size 才合理
这是实际项目中最常用的折中方案,batch_size 太小接近 SGD 噪声大,太大接近 BGD 内存压力高。
立即学习“Python免费学习笔记(深入)”;
- 常见取值:16、32、64、128 —— 优先选 2 的幂,GPU 显存对齐更高效
- 如果显存允许,
batch_size=64在多数中小数据集上训练稳定性与速度平衡得最好 - 不要设
batch_size=len(X)还叫 mini-batch;也不要把batch_size=1当成 mini-batch——那是 SGD - PyTorch/TensorFlow 里
DataLoader自动处理切片和 drop_last,手写时注意最后一批不足batch_size时要不要丢弃(drop_last=True更稳)
梯度下降真正难的不是写几行代码,而是每次更新前确认:梯度算对了没、学习率跟得上当前 loss 曲率没、数据有没有悄悄破坏了假设。这些地方一松懈,模型就只是在拟合噪声。









