我有一个关于使用scipy例程(如curve_fit)拟合阶跃函数的问题。我很难将其矢量化,例如:
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
xobs=np.linspace(0,10,100)
yl=np.random.rand(50); yr=np.random.rand(50)+100
yobs=np.concatenate((yl,yr),axis=0)
def model(x,rf,T1,T2):
#1: x=np.vectorize(x)
if x<rf:
ret= T1
else:
ret= T2
return ret
#2: model=np.vectorize(model)
popt, pcov = curve_fit(model, xobs, yobs, [40.,0.,100.])
它说
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
如果我添加#1或#2,它会运行,但并不真正适合数据:
OptimizeWarning: Covariance of the parameters could not be estimated category=OptimizeWarning)
[ 40. 50.51182064 50.51182064] [[ inf inf inf]
[ inf inf inf]
[ inf inf inf]]
有人知道怎么修吗?THX
3条答案
按热度按时间r1zhe5dt1#
我是这么做的我保留了
xobs
和yobs
:现在,必须生成Heaviside函数。为了给予这个函数的概述,考虑Heaviside函数的半最大约定:
在Python中,这相当于:
def f(x): return 0.5 * (np.sign(x) + 1)
样地为:
现在,绘制
xobs
和yobs
得到:请注意,比较这两个图,第二个图移动了5个单位,最大值从1.0增加到100。我推断第二个图的函数可以表示如下:
在Python中:
(0.5 * (np.sign(x-5) + 1) * 100 = 50 * (np.sign(x-5) + 1)
组合这些图可以得到(其中
Fit
表示上述拟合函数)情节证实了我的猜测是正确的。现在,假设你不知道这个正确的拟合函数是如何产生的,那么就创建了一个广义拟合函数:
def f(x,a,b,c): return a * (np.sign(x-b) + c)
,其中理论上,a = 50
,b = 5
和c = 1
。进行估算:
popt,pcov=curve_fit(f,xobs,yobs,bounds=([49,4.75,0],[50,5,2]))
。现在,
bounds = ([lower bound of each parameter (a,b,c)],[upper bound of each parameter])
。从技术上讲,这意味着49 <a
< 50,4.75 <b
< 5,0 <c
< 2。以下是我对
popt
和pcov
的搜索结果:pcov
表示popt的估计协方差。对角线提供参数估计值Source(https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.optimize.curve_fit.html)的方差。结果表明,参数估计值
pcov
与理论值接近.基本上,广义Heaviside函数可以表示为:
a * (np.sign(x-b) + c)
下面是生成参数估计值和相应协方差的代码:
最后,请注意
popt
和pcov
的估计值不同。pythonscipy
ql3eal8s2#
这个问题很老了,但如果它对其他人有用的话:Heaviside函数在步长处不可微,这导致了最小化的问题。在这种情况下,我拟合一个逻辑函数,如下所示。
在我的情况下,拟合一个单侧函数总是失败。
slmsl1lt3#
对于噪声和更复杂的数据,您也可以使用误差函数来拟合步长: