我使用以下代码拟合了示例数据的一些分布:
import numpy as np
import pylab
import matplotlib.pyplot as plt
from scipy.stats import norm
samp = norm.rvs(loc=0,scale=1,size=150) # (example) sample values.
figprops = dict(figsize=(8., 7. / 1.618), dpi=128)
adjustprops = dict(left=0.1, bottom=0.1, right=0.97, top=0.93, wspace=0.2, hspace=0.2)
import pylab
fig = pylab.figure(**figprops)
fig.subplots_adjust(**adjustprops)
ax = fig.add_subplot(1, 1, 1)
ax.hist(samp,bins=10,density=True,alpha=0.6,color='grey', label='Data')
xmin, xmax = plt.xlim()
# Distributions.
import scipy.stats
dist_names = ['beta', 'norm','gumbel_l']
for dist_name in dist_names:
dist = getattr(scipy.stats, dist_name)
param = dist.fit(samp)
x = np.linspace(xmin, xmax, 100) #
ax.plot(x,dist(*param).pdf(x),linewidth=4,label=dist_name)
ax.legend(fontsize=14)
plt.savefig('example.png')
如何自动将图例中的分布名称从最适合(顶部)到最差适合排序?我在循环中生成了随机变量,每次迭代的最佳拟合结果可能不同。
最佳答案
那么,您可以使用 Kolmogorov-Smirnov (K-S) 检验来计算 p 值并按其排序
修改循环
for dist_name in dist_names:
dist = getattr(scipy.stats, dist_name)
param = dist.fit(samp)
x = np.linspace(xmin, xmax, 100) #
ax.plot(x,dist(*param).pdf(x),linewidth=4,label=dist_name)
ks = scipy.stats.kstest(samp, dist_name, args=param)
print((dist_name, ks))
你可以获得类似的输出
('beta', KstestResult(statistic=0.033975289251035434, pvalue=0.9951529119440156))
('norm', KstestResult(statistic=0.03164417055025992, pvalue=0.9982475331007705))
('gumbel_l', KstestResult(statistic=0.113229070386386, pvalue=0.039394595923043355))
这告诉你正常和测试版都相当不错,但gumbel应该是最后一个。基于 P 值或统计数据的排序应该很容易添加
您的结果可能会有所不同,并且取决于 RNG 的初始状态。
更新
关于 K-S 检验不适用于拟合优度估计,我强烈不同意。我认为没有科学理由不使用它,而且我自己也一直使用它。
通常,您有黑匣子生成随机数据,比如说一些网络延迟的测量
一般来说,它可以通过 Gamma 的混合来描述,并且您可以使用某种二次效用函数进行拟合并获取参数集
然后,您使用 K-S 或任何其他经验与理论分布方法来估计拟合程度。如果不使用K-S方法进行拟合,那么使用K-S方法是非常好的方法。
您基本上有一个黑盒生成数据,另一个黑盒拟合数据,并且想知道数据的拟合程度。然后 K-S 就会完成这项工作。
并声明“它通常用作正态性测试,以查看数据是否呈正态分布。”以我的拙见,完全关闭了。 K-S是关于CDF-vs-CDF最大差异,它不关心常态,它更通用
关于scipy - 评估分布拟合的优度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61276051/