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

Python实现最优步长梯度下降时,循环中numpy.norm报错咨询

带最优步长的梯度下降实现报错解决

问题描述

我在Python中实现带最优步长的梯度下降时遇到如下错误:

AttributeError: 'Float' object has no attribute 'sqrt'

if (np.linalg.norm(np.array(dk)) < eps): break

File <array_function internals>:200 in norm

File C:\ProgramData\anaconda3\Lib\site-packages\numpy\linalg\linalg.py:2512 in norm
ret = sqrt(sqnorm)

TypeError: loop of ufunc does not support argument 0 of type Float which has no callable sqrt method

我的实现代码如下:

import sympy as sp
import numpy as np

def grad(f):
    X = f.free_symbols
    Y = [f.diff(xi) for xi in X]
    return [x_k for x_k in X], Y

def descente_pas_opti(f, X0, eps = 1e-6):
    Xk = X0
    fonction = sp.sympify(f)
    X, gradform = grad(fonction)
    r=sp.symbols('r')
    dform= np.array([-df_k for df_k in gradform])
    
    while True:
        dk=np.array(
            [df_k.subs(
                [(X[k],Xk[k]) for k in range(len(X))])
                    for df_k in dform]
            )
        
        rho = sp.solve(
            np.dot(
                [df_k.subs(
                    [(X[k], Xk[k] + r*dk[k]) for k in range (len(X))] )
                        for df_k in gradform]
                , dk)
            , r)[0]
        
        Xk = [Xk[0]+rho*dk[0], Xk[1]+rho*dk[1]]

        if (np.linalg.norm(dk) < eps): break
        
    return Xk

调用参数:

descente_pas_opti('5*x**2 + 0.5*y**2 -3*(x + y)', [-2,-7])

补充:循环外单独测试相关代码正常,首次迭代时np.linalg.norm(dk)返回约25.07,但放入循环内就报错。

问题原因

报错核心是dk数组里的元素不是numpy浮点类型,而是sympy的Float对象。numpy的linalg.norm无法直接处理sympy的数值类型;第二次循环时,Xk里的元素因rho是sympy解出的符号值,与dk的sympy Float相乘后仍为sympy类型,导致后续计算dk时,subs得到的还是sympy Float,传给numpy norm就触发报错。

解决代码及说明

修改后的代码:

import sympy as sp
import numpy as np

def grad(f):
    X = f.free_symbols
    Y = [f.diff(xi) for xi in X]
    return [x_k for x_k in X], Y

def descente_pas_opti(f, X0, eps = 1e-6):
    Xk = X0
    fonction = sp.sympify(f)
    X, gradform = grad(fonction)
    r = sp.symbols('r')
    dform = np.array([-df_k for df_k in gradform])
    
    while True:
        # 计算dk并转换为numpy浮点数组
        dk = np.array(
            [float(df_k.subs([(X[k], Xk[k]) for k in range(len(X))]))
             for df_k in dform]
        )
        
        # 计算梯度点积并求解最优步长,转换为浮点值
        grad_at_xkr = [df_k.subs([(X[k], Xk[k] + r * dk[k]) for k in range(len(X))]) 
                       for df_k in gradform]
        dot_product = sum(g * dk[i] for i, g in enumerate(grad_at_xkr))
        rho = float(sp.solve(dot_product, r)[0])
        
        # 更新Xk为普通数值
        Xk = [Xk[i] + rho * dk[i] for i in range(len(X))]

        if np.linalg.norm(dk) < eps:
            break
        
    return Xk

关键修改点:

  • 计算dk时,用float()将sympy数值转为普通浮点,确保dk是numpy浮点数组;
  • 求解rho后立即转为float,避免后续计算引入sympy类型;
  • 用Python原生sum替代np.dot计算点积,避免sympy表达式与numpy数组混合运算的问题;
  • 确保Xk始终存储普通数值,保证后续subs结果能顺利转成浮点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 20:51:27