我想评估/测试我的数据与特定分布的拟合程度如何。
关于这个问题有几个提问,我被告知可以使用 scipy.stats.kstest
或 scipy.stats.ks_2samp
。这似乎很简单,只需提供:(A) 数据;(2) 分布;和 (3) 拟合参数。唯一的问题是我的结果没有任何意义?我想测试我的数据的“拟合度”以及它与不同分布的拟合,但从 kstest
的输出来看,我不知道是否可以做到这一点?
“[SciPy] 包含 K-S”
使用 Scipy 的 stats.kstest 模块进行拟合度测试 提到
“第一个值是测试统计量,第二个值是 p 值。如果 p 值小于 95(对于 5% 的显著性水平),这意味着你不能拒绝两个样本分布相同的零假设。”
这只是展示如何拟合:拟合分布,拟合度,p 值。使用 Scipy(Python)可以做到吗?
np.random.seed(2)# 从均值为 -50 和标准差为 1 的正态分布中抽样x = np.random.normal(loc=-50, scale=1, size=100)x#array([-50.41675785, -50.05626683, -52.1361961 , -48.35972919,# -51.79343559, -50.84174737, -49.49711858, -51.24528809,# -51.05795222, -50.90900761, -49.44854596, -47.70779199,# ...# -50.46200535, -49.64911151, -49.61813377, -49.43372456,# -49.79579202, -48.59330376, -51.7379595 , -48.95917605,# -49.61952803, -50.21713527, -48.8264685 , -52.34360319])# 尝试对 Gamma 分布进行拟合distribution = "gamma"distr = getattr(stats, distribution)params = distr.fit(x)stats.kstest(x,distribution,args=params)KstestResult(statistic=0.078494356486987549, pvalue=0.55408436218441004)
p 值为 pvalue=0.55408436218441004
表示 normal
和 gamma
抽样来自相同的分布吗?
我以为 Gamma 分布必须包含正值?https://en.wikipedia.org/wiki/Gamma_distribution
现在对正态分布进行测试:
# 尝试对正态分布进行拟合distribution = "norm"distr = getattr(stats, distribution)params = distr.fit(x)stats.kstest(x,distribution,args=params)KstestResult(statistic=0.070447707170256002, pvalue=0.70801104133244541)
根据这个,如果我选择最低的 p 值,那么 我会得出我的数据来自 gamma
分布的结论,尽管它们都是负值?
np.random.seed(0)distr = getattr(stats, "norm")x = distr.rvs(loc=0, scale=1, size=50)params = distr.fit(x)stats.kstest(x,"norm",args=params, N=1000)KstestResult(statistic=0.058435890774587329, pvalue=0.99558592119926814)
这意味着在 5% 的显著性水平下,我可以拒绝分布相同的零假设。所以我得出它们不同的结论,但它们显然不是这样的? 我是否错误地解释了这一点?如果我将其改为单尾测试,是否会使得值越大,它们越有可能来自相同的分布?
回答:
因此,KT 测试的零假设是分布相同。因此,p 值越低,你拒绝零假设的统计证据就越强,并得出分布不同的结论。该测试只能让你谈论分布不同的信心,而不是相同的,因为该测试旨在找到 alpha,即第一类错误的概率。
另外,我非常确定 KT 测试只有在你事先有完全指定的分布时才有效。在这里,你只是在一些数据上 拟合 一个 Gamma 分布,当然,测试产生高 p 值(即你不能拒绝分布相同的零假设)并不奇怪。
快速看一下,你拟合的 Gamma 分布的 pdf(蓝色)与你抽样的正态分布的 pdf(绿色)对比:
In [13]: paramsd = dict(zip(('shape','loc','scale'),params))In [14]: a = paramsd['shape']In [15]: del paramsd['shape']In [16]: paramsdOut[16]: {'loc': -71.588039241913037, 'scale': 0.051114096301755507}In [17]: X = np.linspace(-55, -45, 100)In [18]: plt.plot(X, stats.gamma.pdf(X,a,**paramsd))Out[18]: [<matplotlib.lines.Line2D at 0x7ff820f21d68>]
显然这些分布差异不大。实际上,测试比较的是经验累积分布函数(ECDF)与你候选分布的累积分布函数(CDF)(再次强调,你是从拟合数据到该分布中得出的),测试统计量是最大差异。借用这里的 ECDF 实现 来自这里,我们可以看到任何这样的最大差异都会很小,测试显然不会拒绝零假设:
In [32]: def ecdf(x): .....: xs = np.sort(x) .....: ys = np.arange(1, len(xs)+1)/float(len(xs)) .....: return xs, ys .....: In [33]: plt.plot(X, stats.gamma.cdf(X,a,**paramsd))Out[33]: [<matplotlib.lines.Line2D at 0x7ff805223a20>]In [34]: plt.plot(*ecdf(x))Out[34]: [<matplotlib.lines.Line2D at 0x7ff80524c208>]