评估分布拟合的优度
Evaluate the goodness of a distributional fits
我使用以下代码为示例数据拟合了一些分布:
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) 检验来计算,f.e,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 检验对拟合优度估计的不适用性,我强烈反对。我没有看到不使用它的科学理由,我自己一直在使用它。
通常,您有黑匣子生成随机数据,比方说网络延迟的一些测量值
一般来说,它可以用 Gammas 的混合来描述,你可以使用某种二次效用函数进行拟合并取回参数集
然后您使用 K-S 或任何其他经验与理论分布方法来估计拟合的好坏程度。如果不使用K-S方法拟合,那么使用K-S是非常好的方法。
您基本上有一个黑盒生成数据,另一个黑盒拟合数据,并且想知道拟合数据的拟合程度。然后K-S就可以完成工作了。
并且声明 "it is commonly used as a test for normality to see if your data is normally distributed." 是完全错误的,以我的拙见。 K-S是关于CDF-vs-CDF最大差异的,它不关心正态性,它更通用
我使用以下代码为示例数据拟合了一些分布:
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) 检验来计算,f.e,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 检验对拟合优度估计的不适用性,我强烈反对。我没有看到不使用它的科学理由,我自己一直在使用它。
通常,您有黑匣子生成随机数据,比方说网络延迟的一些测量值
一般来说,它可以用 Gammas 的混合来描述,你可以使用某种二次效用函数进行拟合并取回参数集
然后您使用 K-S 或任何其他经验与理论分布方法来估计拟合的好坏程度。如果不使用K-S方法拟合,那么使用K-S是非常好的方法。
您基本上有一个黑盒生成数据,另一个黑盒拟合数据,并且想知道拟合数据的拟合程度。然后K-S就可以完成工作了。
并且声明 "it is commonly used as a test for normality to see if your data is normally distributed." 是完全错误的,以我的拙见。 K-S是关于CDF-vs-CDF最大差异的,它不关心正态性,它更通用