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

使用scipy.curve_fit结合mpmath.polylog拟合数据遇类型错误求助

问题描述

尝试使用scipy.optimize.curve_fit结合mpmath.polylog进行数据拟合,定义拟合函数如下:

def Vendik(x, C, T0, eps_cst, Td, xsi):
    integral = (np.pi**2)/6. + (Td/x) * np.log(1-np.cosh(Td/x)+np.sinh(Td/x)) - polylog(2, np.exp(-Td/x))
    eta = ( Td/ (2*T0) ) * ( 0.5 + 2./(Td/x)**2 * integral) -1
    term1 = np.sqrt( xsi**2 + eta**3 ) + xsi
    term2 = np.sqrt( xsi**2 + eta**3 ) - xsi 
    return eps_cst + (C*1e4/T0) / ( term1**(2./3.) + term2**(2./3.) - eta )

拟合执行代码:

xdata = data1['T(K)']
ydata = data1['epsr_STO']
p1 = np.array([5.769, 13.16, 66.7, 86.5, 0.667])
popt_Vendik, pcov_Vendik = curve_fit(Vendik, xdata, ydata, p1)

触发错误:

File /opt/anaconda3/lib/python3.9/site-packages/mpmath/ctx_mp.py:634 in _convert_fallback
    raise TypeError("cannot create mpf from " + repr(x))

但通过循环逐个调用函数(res= [Vendik(data1['T(K)'][i], 5.769, 13.16, 66.7, 86.5, 0.667) for i in range(len(data1))])无报错,且使用不依赖mpmath的拟合函数处理相同数据可正常完成。已尝试将xdata/ydata转换为np.array()或list,问题依旧。

问题原因

mpmath.polylog仅支持标量输入,而curve_fit在拟合过程中会批量传递numpy数组给拟合函数。循环调用时传入的是单个标量值,因此可正常运行;但curve_fit传入数组时,mpmath.polylog无法处理数组类型,导致类型转换错误。

解决方案

方案1:向量化mpmath.polylog

用np.vectorize包装mpmath.polylog,使其支持numpy数组输入:

import numpy as np
import mpmath
from scipy.optimize import curve_fit

# 向量化处理polylog,使其支持数组
vectorized_polylog = np.vectorize(lambda n, z: mpmath.polylog(n, z))

def Vendik(x, C, T0, eps_cst, Td, xsi):
    exp_term = np.exp(-Td/x)
    integral = (np.pi**2)/6. + (Td/x) * np.log(1-np.cosh(Td/x)+np.sinh(Td/x)) - vectorized_polylog(2, exp_term)
    eta = ( Td/ (2*T0) ) * ( 0.5 + 2./(Td/x)**2 * integral) -1
    term1 = np.sqrt( xsi**2 + eta**3 ) + xsi
    term2 = np.sqrt( xsi**2 + eta**3 ) - xsi 
    return eps_cst + (C*1e4/T0) / ( term1**(2./3.) + term2**(2./3.) - eta )

方案2:改用scipy.special.polylog(推荐)

若你的scipy版本≥0.19.0,scipy.special.polylog原生支持numpy数组,无需额外处理,直接替换即可:

import numpy as np
from scipy.special import polylog
from scipy.optimize import curve_fit

def Vendik(x, C, T0, eps_cst, Td, xsi):
    integral = (np.pi**2)/6. + (Td/x) * np.log(1-np.cosh(Td/x)+np.sinh(Td/x)) - polylog(2, np.exp(-Td/x))
    eta = ( Td/ (2*T0) ) * ( 0.5 + 2./(Td/x)**2 * integral) -1
    term1 = np.sqrt( xsi**2 + eta**3 ) + xsi
    term2 = np.sqrt( xsi**2 + eta**3 ) - xsi 
    return eps_cst + (C*1e4/T0) / ( term1**(2./3.) + term2**(2./3.) - eta )

验证

修改后重新执行拟合代码即可,两种方案均能解决数组输入的兼容问题,方案2性能更优(原生数组运算,无需循环处理单个元素)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 16:37:03