解决使用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
相关产品推荐
相关产品推荐

