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

解决使用SymPy时的format string冲突问题

问题:SymPy求解损失函数导数时触发TypeError错误

报错信息:

TypeError: unsupported format string passed to Pow.format

原实现代码

import numpy as np
import sympy as sp

def predict(X, w, b):
    return np.dot(X, w) + b

def loss(X, w, b, Y):
    return np.mean((predict(X, w, b) - Y) ** 2)

X, Y = np.loadtxt("code/02_first/pizza.txt", unpack=True, skiprows=1)

# Convert X and Y to sympy symbols
X, w, b, Y = sp.symbols("X w b Y")

def gradient(X, w, b, Y):
    loss_expr = loss(X, w, b, Y)
    dw_dX = sp.diff(loss_expr, w)
    db_dX = sp.diff(loss_expr, b)
    return dw_dX, db_dX

def train(X, Y, iterations, lr):
    w = sp.symbols('w')
    b = sp.symbols('b')
    
    for i in range(iterations):
        loss_value = loss(X, w, b, Y)
        print(f"Iteration: {i:4d}, Loss: {loss_value:.10f}")
        dw_dX, db_dX = gradient(X, w, b, Y)
        w -= dw_dX * lr
        b -= db_dX * lr
    return w, b

w, b = train(X, Y, iterations=20000, lr=0.001)

print(f"\nw = {w:.10f}, b = {b:.10f}")
print(f"Prediction: x = 20 => y = {predict(20, w, b):.2f}")

数据集内容

Reservations  Pizzas
13            33
2             16
14            32
23            51
13            27
1             16
18            34
10            17
26            29
3             15
3             15
21            32
7             22
22            37
2             13
27            44
6             16
10            21
18            37
15            30
9             26
26            34
8             23
15            39
10            27
21            37
5             17
6             18
13            25
13            23

错误原因

  • 符号与数值变量混淆:先加载了numpy数组X、Y,随后用sp.symbols重新定义同名符号变量,导致后续函数中的X、Y变成符号而非数值数组,计算出的loss是符号表达式,不是数值,无法用:.10f这类数值格式化字符串处理。
  • 符号变量赋值错误:train函数内重复定义w、b符号,且符号变量不能像数值那样直接执行w -= dw_dX * lr这种赋值操作,符号运算需要通过表达式替换实现。
  • numpy与SymPy函数混用:predict和loss函数使用了numpy的np.dot、np.mean,这些函数仅支持数值数组,无法处理SymPy符号,导致生成的符号表达式结构异常,最终触发格式化错误。

正确的SymPy实现脚本

核心思路:先用SymPy推导导数的符号表达式,再将表达式转换为可处理numpy数组的数值函数,最后用numpy执行训练循环。

import numpy as np
import sympy as sp

# 1. 定义SymPy符号,推导导数表达式
x_sym, y_sym, w_sym, b_sym = sp.symbols('x y w b')

# 定义符号形式的预测和损失函数
predict_sym = w_sym * x_sym + b_sym
loss_sym = sp.Mean((predict_sym - y_sym)**2)

# 对w和b求导
dw_sym = sp.diff(loss_sym, w_sym)
db_sym = sp.diff(loss_sym, b_sym)

# 将符号表达式转换为可处理numpy数组的数值函数
dw_func = sp.lambdify((x_sym, y_sym, w_sym, b_sym), dw_sym, 'numpy')
db_func = sp.lambdify((x_sym, y_sym, w_sym, b_sym), db_sym, 'numpy')
loss_func = sp.lambdify((x_sym, y_sym, w_sym, b_sym), loss_sym, 'numpy')

# 2. 加载数据集
X, Y = np.loadtxt("code/02_first/pizza.txt", unpack=True, skiprows=1)

# 3. 训练函数
def train(X, Y, iterations, lr):
    w = 0.0  # 初始化数值权重
    b = 0.0  # 初始化数值偏置
    for i in range(iterations):
        # 计算当前损失、梯度
        loss_val = loss_func(X, Y, w, b)
        dw = dw_func(X, Y, w, b)
        db = db_func(X, Y, w, b)
        # 更新参数
        w -= dw * lr
        b -= db * lr
        # 每1000次迭代打印一次状态
        if i % 1000 == 0:
            print(f"Iteration: {i:4d}, Loss: {loss_val:.10f}")
    return w, b

# 执行训练
w, b = train(X, Y, iterations=20000, lr=0.001)

# 结果输出
print(f"\nw = {w:.10f}, b = {b:.10f}")
# 定义数值版预测函数
def predict_num(x, w, b):
    return x * w + b
print(f"Prediction: x = 20 => y = {predict_num(20, w, b):.2f}")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:23:10