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

scipy curve_fit结合mpmath拟合时报cannot create mpf from错误

Scipy curve_fit 结合mpmath拟合报错修复

报错核心原因

  • curve_fit 接口调用规则不匹配:该接口要求传入的模型函数第一个参数必须为自变量,后续参数为待拟合的标量参数,原代码定义的函数入参顺序为(参数列表c, 自变量t),顺序完全相反;且调用时写为function(c,x['Time (sec)']),是提前执行函数把返回的数组传给了curve_fit,而非传入函数本身,导致curve_fit内部迭代传参时把整个参数列表当成单个值传入计算,mpmath接收到列表类型无法转换为高精度浮点数,触发类型错误。
  • mpmath与numpy混用逻辑错误:mpmath原生仅支持标量输入,无法直接处理numpy数组、Python列表类型的批量输入,直接传入列表/数组时会触发类型报错。
  • 拟合完成后的函数调用参数顺序、参数个数均和原函数定义不匹配,即使前面拟合成功也会运行报错。

修复方案

  • 调整模型函数的入参顺序,严格遵循curve_fit要求:自变量t作为第一个入参,5个待拟合参数作为单独的后续入参,避免参数打包传递导致的顺序混乱。
  • 对mpmath的标量函数做向量化包装,使其支持numpy数组的批量计算,无需手动转list传递,同时避免类型错误。
  • 修正curve_fit调用逻辑:直接传入函数名(不要加括号提前执行),按参数顺序传入初始猜测值p0。
  • 统一数值计算逻辑:numpy原生支持的指数、对数运算直接用numpy实现,比mpmath运算速度快2~3个数量级,也不会出现类型兼容问题;仅polylog这类numpy没有的特殊函数保留mpmath实现,同时替换原代码中2.71**的近似写法为np.exp,提升计算精度。
  • 修正拟合完成后的预测值计算逻辑,参数顺序和新的函数定义保持一致。

修复后完整代码

import mpmath as mpm
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import numpy as np

# 将mpmath的标量函数包装为支持numpy数组批量计算的向量化版本
polylog_vec = np.vectorize(mpm.polylog)
mp_exp_vec = np.vectorize(mpm.exp)
mp_log_vec = np.vectorize(mpm.log)

# 读取实验数据
x = pd.read_csv('pyex.csv')
n = len(x['Time (sec)'])
# 常量定义
T = 303.15
R = 0.082 
P0 = 17.18

# 模型函数:第一个入参为自变量t,后续依次为5个待拟合参数
def function(t, c0, c1, c2, c3, c4):
    A11 = 1.0 + mp_exp_vec((-t/c0) + c1)
    A22 = c2 * np.exp(-c3/(R*T))
    A33 = (P0/c4) - 1
    AA = np.abs(polylog_vec(2, A11))
    b11 = (1/(1-A11))**2
    b22 = mp_log_vec(A11**2)
    B1 = mp_log_vec(b11) + b22
    C11 = A11/(A11-1)
    C = mp_log_vec(mp_exp_vec(c1)*C11)
    Z = c0*(AA + 0.5*(B1 - C)*C)
    D = 1 + np.exp(c1)
    E = np.abs(polylog_vec(2, D))
    G = np.log(np.exp(-2*c1))
    H = np.log(D**2) - np.log(D)
    const = -c0*(E + 0.5*(G+H)*np.log(D))
    I = Z + const
    return 1 - np.exp(A22*A33*I)

# 初始参数猜测值,顺序和函数入参一一对应
p0 = [255.00, 0.055, 0.01, 0.007, 16.63]
# 绘制初始参数对应的曲线
y_init = function(x['Time (sec)'].values, *p0)
plt.plot(x['Time (sec)'], x['F (exp)'], 'o', label='实验数据')
plt.plot(x['Time (sec)'], y_init, 'r', label='初始参数曲线')
plt.xlabel('Time (sec)')
plt.ylabel('F (exp)')
plt.legend()
plt.show()

# 提取拟合用的数组格式数据
t = x['Time (sec)'].values.flatten()
hr = x['F (exp)'].values.flatten()
# 正确调用curve_fit执行拟合
popt, pcov = curve_fit(function, t, hr, p0=p0)
print("拟合得到的参数:c0={:.4f}, c1={:.4f}, c2={:.4f}, c3={:.4f}, c4={:.4f}".format(*popt))

# 绘制拟合结果
y_fit = function(t, *popt)
plt.plot(t, hr, 'o', label='实验数据')
plt.plot(t, y_fit, 'r', label='拟合曲线')
plt.xlabel('Time (sec)')
plt.ylabel('F (exp)')
plt.legend()
plt.show()

注意:如果拟合过程中出现RuntimeWarning提示除零、对数无效等问题,可根据参数的物理意义给curve_fit传入bounds参数设置合理的参数取值范围,避免迭代过程中参数取到非法值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 21:06:21