如何用偏导数实现梯度下降?x²+y²优化代码int不可调用报错求解
问题排查及修复方案
报错核心原因
- 命名冲突:
grad2函数的第二个形参命名为grad,和全局定义的梯度计算函数grad重名。Python运行时优先使用局部作用域变量,若调用grad2时给该位置传入整数,函数内部的grad就会被覆盖为整数类型,此时尝试调用grad(x0,y0)就会触发TypeError: 'int' object is not callable报错。 - 梯度取值逻辑错误:全局
grad函数返回的是长度为2的列表,分别对应x、y方向的偏导数值,原代码直接将整个列表和学习率alpha相乘后赋值给单变量xnew、ynew,运算逻辑完全错误,解决命名冲突后也无法正常运行。 - 缺少收敛终止条件:原代码只设置了最大迭代次数,没有设置函数值收敛到0附近的终止判断,会无意义跑满1000次迭代。
修复后代码
def f(x,y): return x**2 + y**2 def dfdx(x,y): return 2*x def dfdy(x,y): return 2*y def grad(x,y): return [dfdx(x,y), dfdy(x,y)] x0 = 1 y0 = 1 # 删除和全局函数重名的grad形参,添加收敛阈值参数tol def grad2(f, x0, y0, alpha, tol=1e-6): iterations = 0 maxIterations = 1000 while iterations < maxIterations: current_grad = grad(x0, y0) # 分别取x、y方向梯度计算新值 xnew = x0 - alpha * current_grad[0] ynew = y0 - alpha * current_grad[1] # 函数值收敛到阈值内就终止迭代 if abs(f(xnew, ynew)) < tol: break x0 = xnew y0 = ynew iterations += 1 return xnew, ynew, iterations # 调用示例,学习率设置为0.1 res_x, res_y, iters = grad2(f, 1, 1, 0.1) print(f"迭代次数:{iters},最终点:({res_x:.6f}, {res_y:.6f}),函数值:{f(res_x, res_y):.8f}")
效果验证
运行上述代码,迭代约70次即可将函数值降至1e-6以下,符合将函数值优化到0附近的需求。
内容的提问来源于stack exchange,提问作者username123
相关产品推荐
相关产品推荐

