题目重点:从平方损失推导权重和偏置梯度,用SGD同时更新并通过有限差分验证,不把框架API当推导。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练例一维标量输入y_hat=w*x+b,loss=平均平方误差的一半;SGD按固定输入顺序遍历。
- 示例复用已验证的标量SGD实现,Amazon与Apple来源分开,不能声称两公司原题相同细节。
- 多特征推广使用矩阵表达,但本文代码不声称实现任意tensor框架或自动求导。
解题路线
- 计算r_i=w*x_i+b-y_i,J=(1/(2n))Σr_i²。链式法则dJ/dw=mean(r_i*x_i),dJ/db=mean(r_i);1/2抵消导数中的2。
- 单样本SGD用同一旧w,b先求r,再同时更新w-=lr*r*x、b-=lr*r。若先更新w又重新计算r更新b,就是另一算法。
- 向量特征推广为grad_w=X^T r/n、grad_b=sum(r)/n;核对batch维、broadcast和bias。手写backprop关键在shape与归一化一致。
- 梯度验证用中心有限差分(J(theta+ε)-J(theta-ε))/(2ε),使用双精度小随机输入并比较绝对/相对误差;有限差分是debug工具,不是训练替代。
- 学习率与特征尺度决定收敛,训练前特征标准化参数只由训练集拟合。一个batch loss下降不足证明实现正确,要用已知线性数据、梯度检查、扰动方向及独立验证集。
- 题目未明确L1/L2或正则项;若扩展L2且不罚bias,梯度新增lambda*w,损失系数要一致。异常值改变平方损失影响,可讨论鲁棒损失但不冒充原题要求。
手动走一遍
训练单样本x=2,y=5,初始w=b=0,r=-5,单样本梯度dw=-10,db=-5。lr=0.01同时更新得到w=0.1,b=0.05;若代码梯度相反,损失会朝错误方向变化。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def loss_and_gradient(xs, ys, weight, bias):
if len(xs) != len(ys) or not xs:
raise ValueError("equal nonempty arrays required")
residuals = [weight * x + bias - y for x, y in zip(xs, ys)]
n = len(xs)
return (
sum(r * r for r in residuals) / (2 * n),
sum(r * x for r, x in zip(residuals, xs)) / n,
sum(residuals) / n,
)
def fit_sgd(xs, ys, learning_rate=0.01, epochs=1000):
if len(xs) != len(ys) or not xs or learning_rate <= 0 or epochs < 0:
raise ValueError("invalid training inputs")
weight = bias = 0.0
for _ in range(epochs):
for x, y in zip(xs, ys):
residual = weight * x + bias - y
weight, bias = weight - learning_rate * residual * x, bias - learning_rate * residual
return weight, bias
复杂度
标量每epoch O(n)时间、训练O(epochs·n)、参数O(1);批量loss函数示例存n个residual O(n)辅助空间。d维矩阵训练O(epochs·n·d),不含框架额外状态。
易错点与追问
容易失分的边界
- 损失用平均但梯度漏n。
- 先改w后重算r更新b。
- 训练集以外数据参与标准化造成泄漏。
- 只看一次loss下降而不查梯度。
继续深挖
- 特征维度增加如何推导?
- L2和weight decay在这个SGD例里如何比较?
- batch、mini-batch和SGD的噪声与成本?
