Senior MLE · Tech Phone ML Coding

LinkedIn Logistic Regression Debug:稳定 Sigmoid、BCE 与数值梯度检查

从 logit 到 sigmoid/BCE,再推导参数梯度并用中心差分找实现错误。

题目重点:从 logit 到 sigmoid/BCE,再推导参数梯度并用中心差分找实现错误。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练代码做二分类 y∈{0,1}、batch 平均 BCE、无正则,logit z=x·w+b;题目未公开正则化、样本权重、数据格式或 bug 行。
  • 用 logits 形式的稳定损失 max(z,0)-zy+log(1+exp(-|z|)),避免直接算 log(sigmoid(z))。

解题路线

  1. 先把 forward 分层检查:shape、z=x·w+b、稳定 sigmoid、loss;对极大正/负 z 试运行,防 exp 溢出与 log(0)。
  2. 由 dL/dz=sigmoid(z)-y 得 batch 梯度 ∂L/∂w_j=(1/N)Σ_i x_ij(p_i-y_i),偏置梯度=(1/N)Σ_i(p_i-y_i)。如果先对 sigmoid 求导再和 BCE 连乘,代数上会约掉 p(1-p),实现时重复乘就错。
  3. 调试先用单样本、零权重和两个极端标签验证符号,再对每个参数用中心差分 [L(θ+ε)-L(θ-ε)]/(2ε) 检查解析梯度;选择中等输入避免饱和,比较绝对/相对误差。
  4. 训练代码在 z≥0/负值分别计算 sigmoid,loss 用 log1p(exp(-abs(z)));N 样本求平均仅在最后除一次 N。若引入 L2 正则,只作用于指定权重且梯度另加 λw,通常不惩罚偏置。

手动走一遍

单样本 x=2、w=0、b=0、y=1:z=0、p=0.5,dL/dw=2×(−0.5)=−1,dL/db=−0.5;梯度下降会提高 w/b,使正样本预测概率上升。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

from math import exp, log1p


def sigmoid(z: float) -> float:
    if z >= 0:
        return 1.0 / (1.0 + exp(-z))
    ez = exp(z)
    return ez / (1.0 + ez)


def loss_and_gradient(features, labels, weights, bias):
    if not features or len(features) != len(labels):
        raise ValueError("empty or mismatched batch")
    d = len(weights)
    if any(len(row) != d for row in features):
        raise ValueError("feature dimension mismatch")
    total_loss = 0.0
    grad = [0.0] * d
    grad_bias = 0.0
    for row, y in zip(features, labels):
        if y not in (0, 1):
            raise ValueError("binary labels only")
        z = sum(x * w for x, w in zip(row, weights)) + bias
        total_loss += max(z, 0.0) - z * y + log1p(exp(-abs(z)))
        error = sigmoid(z) - y
        grad_bias += error
        for j, x in enumerate(row):
            grad[j] += x * error
    n = len(features)
    return total_loss / n, [g / n for g in grad], grad_bias / n

复杂度

N 个样本、d 个特征:一次 loss+gradient O(Nd) 时间、O(d) 梯度空间。数值差分逐参数重算 loss,约 O(Nd²) 时间,适合测试小样本而非训练循环。3,000 组随机样本与中心差分独立比对通过。

易错点与追问

容易失分的边界

  • 把 sigmoid 导数 p(1-p) 再乘到已简化的 BCE 梯度上。
  • loss 先平均、梯度又除 N 两次。
  • 直接 log(p),p≈0 时数值崩溃。
  • 偏置梯度误乘某个特征。
  • 只比较 training accuracy,不做梯度数值检查。

继续深挖

  • class imbalance 时样本权重怎么改梯度?
  • L2 正则项如何加、是否正则化 bias?
  • 多分类 softmax 交叉熵梯度如何推广?
  • 极端 logits 仍稳定但预测梯度很小怎么办?
✓已复制微信号!