问题描述
我正在将合成数据拟合到 scipy 中的各种分布,但是,我观察到了一些意想不到的结果。我的数据包含负数,当我在固定位置和比例时将此数据拟合到具有非负支持的分布时,我没有收到错误。我的代码如下:
import scipy.stats as st
import numpy as np
import pandas as pd
np.random.seed(7)
test_data = pd.Series(0.5 + 0.1*np.sin(np.linspace(0,3*np.pi,100)) + 0.5*np.random.normal(0,1,size=100))
print(np.min(test_data))
哪个返回:
-0.5900934692403015
确认我产生了负面观察。当我拟合具有非包含非负支持的 scipy lognorm 时,我得到了违反数据边界的错误的预期结果:
st.lognorm.fit(test_data,floc=0,fscale=1)
---------------------------------------------------------------------------
FitDataError Traceback (most recent call last)
<ipython-input-13-fbeaae8f3c2e> in <module>
----> 1 st.lognorm.fit(test_data,fscale=1)
~\Miniconda3\lib\site-packages\scipy\stats\_continuous_distns.py in fit(self,data,*args,**kwds)
5087 data = data - floc
5088 if np.any(data <= 0):
-> 5089 raise FitDataError("lognorm",lower=floc,upper=np.inf)
5090 lndata = np.log(data)
5091
FitDataError: Invalid values in `data`. Maximum likelihood estimation with 'lognorm' requires that 0.0 < x < inf for each x in `data`.
但是,通过以下分布,我能够拟合数据,尽管所有这些分布都具有非负数据边界(如其 scipy 文档所定义)和固定位置和比例。
st.burr.fit(test_data,fscale=1)
st.expon.fit(test_data)
st.chi2.fit(test_data,fscale=1)
st.invgauss.fit(test_data,fscale=1)
st.invgamma.fit(test_data,fscale=1)
哪个产量:
(4.435119987970436,0.32475585134451646,1)
(-0.5900934692403015,1.1171187649605647)
(1.349414062500001,1)
(0.6815429687499996,1)
(2.301074218750003,1)
此外,没有任何形状参数的分布指数能够执行,这令人惊讶。如果有人能解释这些分布如何能够适应数据,尽管他们的支持范围已被违反,我将不胜感激。
我正在运行 numpy 1.19.2 和 scipy 1.5.2
谢谢!
解决方法
那些 fit
没有抛出任何错误的事实并不意味着它们非常适合或可以描述您的数据。
我正在使用 scipy==1.6.1
。
您可以查看绘图结果
x = np.linspace(test_data.min(),test_data.max(),100)
毛刺:没有错误,bu无法描述数据
burr_pars = sps.burr.fit(test_data,floc=0,fscale=1)
y = sps.burr(*burr_pars).pdf(x)
plt.plot(x,y)
plt.hist(test_data,alpha=.5,density=True);
Expon:没有错误,但非常不合适
expon_pars = sps.expon.fit(test_data)
y = sps.expon(*expon_pars).pdf(x)
plt.plot(x,density=True);
Chi2:没有错误,但拟合很差,无法描述数据
chi2_pars = sps.chi2.fit(test_data,fscale=1)
y = sps.chi2(*chi2_pars).pdf(x)
plt.plot(x,density=True);
Invgauss:错误
invgauss_pars = sps.invgauss.fit(test_data,fscale=1)
FitDataError: Invalid values in `data`. Maximum likelihood estimation with 'invgauss' requires that 0 < (x - loc)/scale < inf for each x in `data`.
如果您不设置 loc 和 scale,则最适合 x>=0,但鉴于其 PDF 的公式,没有理由为 x
invgauss_pars = sps.invgauss.fit(test_data)
y = sps.invgauss(*invgauss_pars).pdf(x)
plt.plot(x,density=True);
Invgamma:警告,不合适,无法描述 x
invagamm_pars = sps.invgamma.fit(test_data,fscale=1)
y = sps.invgauss(*invagamm_pars).pdf(x)
plt.plot(x,density=True);
RuntimeWarning: invalid value encountered in double_scalars
Lhat = muhat - Shat*mu
编辑
从 https://github.com/scipy/scipy/blob/v1.6.3/scipy/stats/_continuous_distns.py 中您可以看到 FitDataError
仅由 beta
、expon
调用(但如果 floc is None
则 floc = data_min
)、{{ 1}}、gamma
(但仅限于 invgauss
)、np.any(data - floc < 0)
、lognorm
、pareto
、rayleigh
。
对于其他发行版,uniform
未实现。