You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于CS229实现Batch Gradient Descent结果异常求助

批量梯度下降实现问题排查与入门建议

核心代码bug

  • 缺失梯度的1/m缩放项:CS229课程给出的批量梯度下降公式中,梯度项需要对所有样本的误差累加值取平均(乘以1/m,m为样本总数)。你的实现直接用未缩放的累加梯度做参数更新,等效于将设定的学习率放大了m倍。汽车MPG数据集样本量在300+,你设置的0.001学习率实际等效值超过0.3,直接触发梯度爆炸,参数指数增长溢出为NaN,这也是你必须把学习率压到1e-7才能避免溢出的根本原因。
  • 参数未同步更新:标准批量梯度下降要求单轮迭代中,先计算完所有参数对应的梯度,再统一更新全部参数。你的实现是算完一个参数的梯度就立刻更新该参数,后续计算其他参数梯度时,调用的假设函数已经用了更新后的新参数,不符合批量梯度下降的逻辑,会导致收敛路径偏移,参数更新方向错乱。
  • 未做特征归一化:你使用的汽车数据集中,车重字段数值范围在18005000区间,马力在50250区间,截距项对应特征恒为1,不同特征尺度差了3~4个数量级。此时损失函数等高线为极度狭长的椭圆,哪怕梯度计算逻辑正确,收敛速度也会极慢,且对学习率极其敏感。课程中提到的0.01/0.1可用学习率,默认前提是特征经过标准化缩放到相近尺度。

修正后可运行代码

def hypothesis(X: list, parameters: list) -> float:
    result = 0
    for i in range(len(X)):
        result += X[i] * parameters[i]
    return result

def batch_gradient_descent(dataset: list, learning_rate=0.01, steps=1000) -> list[float]:
    m = len(dataset[0])
    n = len(dataset) - 1
    parameters = [0.0] * (n + 1)
    for k in range(steps):
        gradients = [0.0] * (n + 1)
        # 先计算本轮所有参数的梯度,不提前更新参数
        for j in range(n + 1):
            grad_sum = 0
            for datapoint in range(m):
                x_i = [dataset[dim][datapoint] for dim in range(n+1)]
                h = hypothesis(x_i, parameters)
                y = dataset[-1][datapoint]
                grad_sum += (h - y) * dataset[j][datapoint]
            # 补全1/m缩放项
            gradients[j] = (1 / m) * grad_sum
        # 所有梯度计算完成后,统一更新参数
        for j in range(n + 1):
            parameters[j] -= learning_rate * gradients[j]
    return parameters

# 特征标准化工具,训练前对除截距项外的所有特征调用
def normalize_feature(feature: list) -> tuple[list, float, float]:
    mean = sum(feature) / len(feature)
    std = (sum((x - mean) ** 2 for x in feature) / len(feature)) ** 0.5
    normalized = [(x - mean) / std for x in feature]
    return normalized, mean, std

使用前先对马力、车重特征调用normalize_feature做标准化,学习率设为0.01~0.1即可正常收敛。

机器学习入门实践建议

  • 实现算法前逐行对应公式项,不要凭记忆写代码。写完后先用35个手动构造的小样本,手算12轮迭代的梯度和参数值,和代码输出对比确认逻辑正确,再上真实数据集。
  • 所有基于梯度下降的算法,训练前必须做特征缩放(标准化/归一化),除非所有特征天然处于同一数值区间。
  • 调试训练过程时,每轮迭代打印均方误差损失值:正常收敛时损失应当稳定单调下降,如果损失上升、震荡,优先排查梯度计算错误、学习率过大问题,不要盲目压低学习率、增加迭代次数。
  • 入门阶段优先用人工生成的、规律明确的小数据集验证代码正确性,确认输出符合预期后再替换为真实数据集。

内容的提问来源于stack exchange,提问作者Anirudh Kanaparthy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:18:17