
本文详解如何修正梯度下降算法中因梯度推导错误、参数更新逻辑混乱导致的θ值发散或不收敛问题,重点展示基于解析梯度(而非链式误算)的向量化更新实现,并通过可视化验证不同初值的收敛域。
本文详解如何修正梯度下降算法中因梯度推导错误、参数更新逻辑混乱导致的θ值发散或不收敛问题,重点展示基于解析梯度(而非链式误算)的向量化更新实现,并通过可视化验证不同初值的收敛域。
在实现梯度下降时,参数(如权重 $ w $ 和偏置 $ b $)能否稳定收敛至成本函数极小点,核心取决于两点:梯度是否准确、更新逻辑是否严谨。原代码存在多个关键缺陷:
- ❌ 错误地将输入 $ X $ 和目标 $ Y_{\text{sol}} $ 硬编码进
gradient()函数,导致梯度与实际损失函数erreurJ脱节; - ❌ 在
pasfixe中嵌套了冗余的for i in range(len(theta))循环,且在循环内反复重算h和Y,破坏了梯度方向的一致性; - ❌ 使用未经验证的数值近似梯度(甚至混用符号导数与前向传播变量),而未采用从
erreurJ严格推导出的解析梯度。
✅ 正确做法是:直接对损失函数 erreurJ(theta) 求关于 $ \theta = [w, b] $ 的偏导,得到精确解析梯度 grad(theta),并在每次迭代中执行单次向量化更新:
<code class="python">theta = theta - eta * grad(theta)</code>
本例中,损失函数为: $$ J(w,b) = \frac{1}{4}\left[\sigma(b)^2 + \sigma(w+b)^2\right], \quad \text{其中 } \sigma(z) = z^2 - 1 $$ 经符号求导可得:
- $ \frac{\partial J}{\partial w} = 2b^3 + 3b^2 w + 3b w^2 - 2b + w^3 - w $
- $ \frac{\partial J}{\partial b} = b^3 + 3b^2 w + 3b w^2 - b + w^3 - w $
该解析梯度已完整实现在 grad(theta) 函数中(注意返回 np.array 以支持向量化运算)。
此外,还需注意以下工程实践要点:
-
学习率
eta需调低:原设0.1易导致震荡,改为0.01更稳健; -
初始化与类型安全:将
theta显式转为np.float64数组,避免整型溢出或精度丢失; -
发散防护:使用
np.any(np.abs(theta) > 100)统一判断整体发散,替代原代码中对单个分量的孤立检查; -
解耦输入依赖:
pasfixe不再接收X,Y,Ysol等无关参数,仅聚焦于theta的纯数学优化过程。
最终,通过在 5000 个随机初始点上运行修正后的梯度下降,并按收敛结果(如 [-2,1]、[2,-1] 等局部极小点)着色,可复现目标收敛域图——不同颜色区域清晰对应不同吸引子 basin,直观验证算法的正确性与鲁棒性。此方法不仅适用于本例的自定义激活函数,更是通用梯度优化实践的范本:永远优先使用解析梯度,杜绝“黑箱链式求导”陷阱。










