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

梯度下降函数输出极大负值问题排查求助

梯度下降算法参数更新方向错误排查

我正在用Python编写梯度下降算法,第一段代码用于绘制2D(wx+b)和1D(wx)场景下的误差函数图,第二段是单独保存的梯度下降函数。从绘制的图像来看,min_w和min_b应为正值,但梯度下降函数却输出极大的负值。从w=0、b=0开始迭代时,参数立刻变为负值(对应误差曲线的上升方向),正确的下降方向应该是正值方向。我试过调整步长、迭代次数和初始值,都没解决问题,求排查错误原因。

主代码

import numpy as np
import matplotlib.pyplot as plt

x_train = np.array([1.0, 1.7, 2.0, 2.5, 3.0, 3.2])
x_mean = np.mean(x_train)
x_std = np.std(x_train)
x_train_normalized = (x_train - x_mean) / x_std
y_train = np.array([250, 300, 480,  430,   630, 730,])
w=np.random.rand(200) * 2 - 1
b=np.random.rand(200) * 2 - 1
W, B = np.meshgrid(w, b)
J=np.zeros((len(w),len(b)))
J1=np.zeros((len(w)))
y_bar = np.zeros((len(w), len(x_train)))
m = len(x_train)
    
x_new=x_train_normalized[:,np.newaxis,np.newaxis]
y_new=y_train[:,np.newaxis,np.newaxis]
y_bar=W*x_new+B
sum_squared_errors=np.sum((y_bar-y_new)**2,axis=0)
J=(1/(2*m))*sum_squared_errors
from GD import gd2D
min_w,min_b=gd2D(y_new,x_new,m,np)
     
y_bar1=W*x_new
sum_squared_errors1=np.sum((y_bar1-y_new)**2,axis=0)
J1=(1/(2*m))*sum_squared_errors1
       
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(W, B, J, cmap='viridis', edgecolor='none')
ax.set_xlabel('W-axis')
ax.set_ylabel('B-axis')
ax.set_zlabel('J-axis')
ax.view_init(elev=20, azim=-60)  # 调整视角以便更好可视化
fig.colorbar(surf)  # 添加侧边颜色条
plt.show()
       
plt.scatter(W,J1,marker='X',c='r',s=10)
plt.title("ABS")
plt.ylabel("J")
plt.xlabel("w")
plt.show()

梯度下降函数代码

def gd2D(y_new,x_new,m,np):
    itr = 5000
    alpha = 0.01
    w=0
    b=0
    for i in range(itr):
        y_bar=w*x_new+b
        dw=(np.sum((y_new-y_bar)*x_new))/m
        db=(np.sum(y_new-y_bar))/m
        w=w-alpha*dw
        b=b-alpha*db
    return w,b

错误原因及修正方案

问题核心是梯度计算的符号错误,导致参数更新方向完全相反:

均方误差损失函数定义为:
$$J(w,b) = \frac{1}{2m}\sum_{i=1}^m (y_i - (wx_i + b))^2$$

对w和b求偏导的正确结果是:
$$\frac{\partial J}{\partial w} = -\frac{1}{m}\sum_{i=1}^m (y_i - \hat{y}i)x_i$$
$$\frac{\partial J}{\partial b} = -\frac{1}{m}\sum
{i=1}^m (y_i - \hat{y}_i)$$

你的代码中,dw和db的计算没有添加负号,相当于得到了损失梯度的相反数。而梯度下降的更新规则是参数 = 参数 - 学习率 × 损失函数的梯度,这就导致实际更新时变成了沿着损失上升的方向移动,自然会跑到错误的极值点。

修正后的梯度下降函数

def gd2D(y_new,x_new,m,np):
    itr = 5000
    alpha = 0.01
    w=0
    b=0
    for i in range(itr):
        y_bar=w*x_new+b
        # 添加负号,得到正确的损失梯度
        dw = -np.sum((y_new - y_bar) * x_new) / m
        db = -np.sum(y_new - y_bar) / m
        w = w - alpha * dw
        b = b - alpha * db
    return w,b

或者也可以保持dw和db的计算不变,调整更新公式的符号:

w = w + alpha * dw
b = b + alpha * db

两种方式效果完全一致。

额外提示:x_new和y_new被处理成了三维数组,虽然求和后不影响梯度计算,但直接使用一维数组会让代码更简洁。

内容的提问来源于stack exchange,提问作者Tariq Islam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 08:18:13