Python曲线与测量数据点的拟合

Python曲线与测量数据点的拟合,python,curve-fitting,data-analysis,measurement,Python,Curve Fitting,Data Analysis,Measurement,我已经测量了数据点,我想根据公式拟合来确定两个实体。但是我得到了一个错误: TypeError:输入类型不支持ufunc“按位异或”,并且无法根据强制转换规则“安全”将输入安全强制为任何支持的类型 由以下python代码生成(我使用版本3): 将numpy导入为np 将matplotlib.pyplot作为plt导入 从scipy.optimize导入曲线\u拟合 def func(T、fun、Tc): 返回乐趣*np.sqrt(np.cos(np.pi/2*(T/Tc)^2)) 扩展数据=(4

我已经测量了数据点,我想根据公式拟合来确定两个实体。但是我得到了一个错误:

TypeError:输入类型不支持ufunc“按位异或”,并且无法根据强制转换规则“安全”将输入安全强制为任何支持的类型

由以下python代码生成(我使用版本3):

将numpy导入为np
将matplotlib.pyplot作为plt导入
从scipy.optimize导入曲线\u拟合
def func(T、fun、Tc):
返回乐趣*np.sqrt(np.cos(np.pi/2*(T/Tc)^2))
扩展数据=(4.61,4.89,4.92,4.95,5.06,5.10,5.21,5.38,5.41,5.57,5.80,6.14,6.61,7.27,7.66,7.90,8.91,8.29,8.23,7.30,7.86,
8.30,8.89,8.99,9.24,9.35,9.50,8.77,8.27,8.37,7.72,7.57,7.99,8.13)#这些是温度值T
ydata=(2.85,2.84,2.83,2.825,2.82,2.81,2.80,2.765,2.76,2.74,2.695,2.62,2.50,2.265,2.105,1.975,1.23,1.75,1.81,2.26,
2.005、1.75、1.31、1.14、1.015、1.045、1.06、1.40、1.75、1.69、2.075、2.15、1.93、1.855)#这些是能量值函数
popt,pcov=曲线拟合(func,扩展数据,ydata)
popt#显示这些优化值
下面是上面的错误

我看到了一种方法,如果你有一个固定的公式,并添加一些噪音,但我已经测量了数据点(它们必须是离散的)

谢谢大家!!
Carsten

我认为您看到的错误很大一部分是您没有为拟合变量
fun
Tc
提供初始值。不幸的是,scipy的
curve_fit()
允许这样做,并默默地将值指定为1.0,这会鼓励不良做法,是一个非常糟糕的“特性”。不要用它

请允许我推荐lmfit(),它为曲线拟合提供了更高级别的接口,更易于使用,更好地避免不良行为,并且有许多有用的功能,这些功能在
curve\u fit()中不可用

使用lmfit,您的拟合问题看起来像(为了清晰起见,我更改了几个变量名):

将numpy导入为np
将matplotlib.pyplot作为plt导入
从lmfit导入模型
def功能(t、刻度、tc):
返回量表*np.sqrt(np.cos(np.pi/2*(t/tc)**2))
tdata=np.数组([4.61,4.89,4.92,4.95,5.06,5.10,5.21,5.38,5.41,5.57,5.80,6.14,6.61,7.27,7.66,7.90,8.91,8.29,8.23,7.30,7.86,
8.30,8.89,8.99,9.24,9.35,9.50,8.77,8.27,8.37,7.72,7.57,7.99,8.13])这些是温度值T
能量=np.阵列([2.85,2.84,2.83,2.825,2.82,2.81,2.80,2.765,2.76,2.74,2.695,2.62,2.50,2.265,2.105,1.975,1.23,1.75,1.81,2.26,
2.005,1.75,1.31,1.14,1.015,1.045,1.06,1.40,1.75,1.69,2.075,2.15,1.93,1.855])这些是能量值函数
F模型=模型(func)
参数=F模型制造参数(比例=5,tc=10)
结果=fmodel.fit(能量、参数、t=tdata)
打印(result.fit_report())
plt.绘图(tdata、能量、'o',标签='data')
plt.plot(tdata,result.best_fit,“+”,label='fit')
plt.legend()
plt.show()
它将打印一份

[[Model]]
    Model(func)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 24
    # data points      = 34
    # variables        = 2
    chi-square         = 0.34988407
    reduced chi-square = 0.01093388
    Akaike info crit   = -151.601474
    Bayesian info crit = -148.548753
[[Variables]]
    scale:  2.87776739 +/- 0.02737439 (0.95%) (init = 5)
    tc:     9.68051725 +/- 0.03597889 (0.37%) (init = 10)
[[Correlations]] (unreported correlations are < 0.100)
    C(scale, tc) = -0.506
[[Model]]
模型(func)
[[Fit统计数据]]
#拟合方法=最小二乘法
#函数evals=24
#数据点=34
#变量=2
卡方检验=0.34988407
缩减卡方=0.01093388
Akaike信息临界值=-151.601474
贝叶斯信息临界值=-148.548753
[[变量]]
标度:2.87776739+/-0.02737439(0.95%)(初始值=5)
tc:9.68051725+/-0.03597889(0.37%)(初始值=10)
[[相关性]](未报告的相关性<0.100)
C(标度,tc)=-0.506
并生成一个类似于


电源操作员是
**
不是
^
^
表示“按位异或”@DavidG这是一个很好的捕获,做得很好。当我使用**,在popt:C:\Users\B\Anaconda3\lib\site packages\ipykernel\u main\ py.py:2:RuntimeWarning:ipykernel import kernelapp as app的sqrt中遇到无效值,之后在同一单元格中遇到无效值:RuntimeError:Optimal parameters not found:function调用次数已达到maxfev=600。这是另一种情况问题您需要问另一个问题(答案可能是您需要使用参数
p0=
)对
曲线拟合提供初始猜测),因此我不应该编辑该问题,而是让它保留并问一个新问题?(我是stackoverflow的新手)你们是如何得到scale=5(T=0K时超导体的带隙)和tc=10(超导体的临界温度——铌)的?您只是尝试了一些值并测试了结果是什么?(实际上,这些值来自物理估算值?)与文献(近似值)相比,物理值是正确的,我可以在安装“lmfit”后复制它。我不知道python社区中通常是如何看待这一点的,但是安装新的软件包总是有可能在某个地方出错,不是吗因此,我将标记为正确。仍然非常欢迎没有新软件包的答案(或对喜欢其他软件包的人有不同的答案)-非常感谢Newvielle先生的帮助。为了猜测初始值,我绘制了数据并看到:a)最大能量(y)值~2.5,b)最大t(x)值~10。这些都是更好的猜测(!),但我用这些来猜测
量表
可能在1到10之间(所以5),而
tc
可能在1到100之间(所以10)。可视化数据非常有用!使用正确的起始值,您应该可以使用
曲线拟合
leastsq
获得相同的结果。默认情况下,lmfit使用
scipy.optimize.leastsq()。所有软件都有出错的风险。在这种情况下,曲线拟合被证明比lmfit差;)。
import numpy as np
import matplotlib.pyplot as plt
from lmfit import Model

def func(t, scale, tc):
    return scale*np.sqrt(np.cos(np.pi/2*(t/tc)**2))

tdata = np.array([4.61, 4.89, 4.92, 4.95, 5.06, 5.10, 5.21, 5.38, 5.41, 5.57, 5.80, 6.14, 6.61, 7.27, 7.66, 7.90, 8.91, 8.29, 8.23, 7.30, 7.86,
                  8.30, 8.89, 8.99, 9.24, 9.35, 9.50, 8.77, 8.27, 8.37, 7.72, 7.57, 7.99, 8.13]) # these are temperature values <-> T

energy = np.array([2.85, 2.84, 2.83, 2.825, 2.82, 2.81, 2.80, 2.765, 2.76, 2.74, 2.695, 2.62, 2.50, 2.265, 2.105, 1.975, 1.23, 1.75, 1.81, 2.26,
                   2.005, 1.75, 1.31, 1.14, 1.015, 1.045, 1.06, 1.40, 1.75, 1.69, 2.075, 2.15, 1.93, 1.855]) # these are energy values <-> func

fmodel = Model(func)

params = fmodel.make_params(scale=5, tc=10)

result = fmodel.fit(energy, params, t=tdata)
print(result.fit_report())

plt.plot(tdata, energy, 'o', label='data')
plt.plot(tdata, result.best_fit, '+', label='fit')

plt.legend()
plt.show()
[[Model]]
    Model(func)
[[Fit Statistics]]
    # fitting method   = leastsq
    # function evals   = 24
    # data points      = 34
    # variables        = 2
    chi-square         = 0.34988407
    reduced chi-square = 0.01093388
    Akaike info crit   = -151.601474
    Bayesian info crit = -148.548753
[[Variables]]
    scale:  2.87776739 +/- 0.02737439 (0.95%) (init = 5)
    tc:     9.68051725 +/- 0.03597889 (0.37%) (init = 10)
[[Correlations]] (unreported correlations are < 0.100)
    C(scale, tc) = -0.506