首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何从numpy数组中确定概率分布函数?

如何从numpy数组中确定概率分布函数?
EN

Stack Overflow用户
提问于 2014-04-24 01:53:19
回答 2查看 17.2K关注 0票数 23

我到处寻找,令我惊讶的是,这个问题似乎还没有得到回答。

我有一个包含10000个测量值的Numpy数组。我用Matplotlib绘制了一个直方图,通过肉眼观察,这些值似乎是正态分布的:

然而,我想要验证这一点。我发现了一个在scipy.stats.mstats.normaltest下实现的正态性测试,但结果并非如此。我得到以下输出:

代码语言:javascript
复制
(masked_array(data = [1472.8855375088663],
         mask = [False],
   fill_value = 1e+20)
, masked_array(data = [ 0.],
         mask = False,
   fill_value = 1e+20)

)

这意味着数据集呈正态分布的概率为0。我重新运行了这些实验,并再次测试了它们,获得了相同的结果,在“最佳”情况下,p值为3.0e-290。

我已经用下面的代码测试了这个函数,它似乎做了我想要做的事情:

代码语言:javascript
复制
import numpy
import scipy.stats as stats

mu, sigma = 0, 0.1
s = numpy.random.normal(mu, sigma, 10000)

print stats.normaltest(s)

(1.0491016699730547, 0.59182113002186942)

如果我正确理解和使用了这个函数,它意味着这些值不是正态分布的。(老实说,我不知道为什么输出会有差异,即更少的细节。)

我非常确定这是一个正态分布(尽管我的统计学知识很基础),但我不知道另一种选择是什么。我如何检查所讨论的概率分布函数是什么?

编辑:

我的包含10000个值的Numpy数组是这样生成的(我知道这不是填充Numpy数组的最佳方法),然后运行normaltest测试:

代码语言:javascript
复制
values = numpy.empty(shape=10000, 1))
for i in range(0, 10000):
    values[i] = measurement(...) # The function returns a float

print normaltest(values)

EDIT 2:

我刚刚意识到,输出之间的差异是因为我无意中使用了两个不同的函数(scipy.stats.normaltest()和scipy.stats.mstats.normaltest()),但这并没有什么不同,因为无论使用哪个函数,输出的相关部分都是相同的。

EDIT 3:

将直方图与askewchan的建议进行拟合:

代码语言:javascript
复制
plt.plot(bin_edges, scipy.stats.norm.pdf(bin_edges, loc=values.mean(), scale=values.std()))

结果如下:

EDIT 4:

将直方图与用户user333700的建议进行拟合:

代码语言:javascript
复制
scipy.stats.t.fit(data)

结果如下:

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-24 02:32:09

假设您正确地使用了测试,我的猜测是您与正态分布的偏差,并且由于您的样本量非常大,即使是很小的偏差也会导致拒绝正态分布的零假设。

一种可能是通过使用loc=data.mean()scale=data.std()绘制具有大量柱状图和pdf的normed直方图来直观地检查数据。

有检验正态性的替代检验,当估计分布参数时,统计模型有Anderson-Darling和Lillifors (Kolmogorov-Smirnov)检验。

然而,考虑到大样本量,我预计结果不会有太大差异。

主要的问题是,您是否想测试您的样本是否“完全”来自正态分布,或者您是否只对您的样本是否来自一个非常接近正态分布的分布感兴趣,在实际使用方面, close

详述最后一点:

http://jpktd.blogspot.ca/2012/10/tost-statistically-significant.html http://www.graphpad.com/guides/prism/6/statistics/index.htm?testing_for_equivalence2.htm

随着样本大小的增加,假设检验获得了更多的能力,这意味着即使是对于越来越小的差异,该测试也能够拒绝相等的零假设。如果我们保持我们的重要性水平不变,那么最终我们将拒绝我们并不真正关心的微小差异。

另一种类型的假设检验是我们想要证明我们的样本接近给定点假设,例如两个样本具有几乎相同的均值。问题是我们必须定义我们的等价区域是什么。

在拟合优度测试的情况下,我们需要选择一个距离度量,并为样本和假设分布之间的距离度量定义一个阈值。我还没有找到任何直觉可以帮助选择这个距离阈值的解释。

stats.normaltest是基于偏斜和峰度与正态分布的偏差。

Anderson-Darling是基于cdf之间加权平方差的积分。

Kolmogorov-Smirnov是基于cdf之间的最大绝对差值。

入库数据的平方将基于二进制概率的平方和。

诸若此类。

我只尝试过对二进制或离散化数据进行等价性测试,其中我使用了一些参考案例中的阈值,这仍然是相当随意的。

在医学等效性测试中,有一些预定义的标准来指定何时两种治疗方法可以被认为是等效的,或者在单边版本中类似地被认为是较差的或较好的。

票数 5
EN

Stack Overflow用户

发布于 2020-05-02 00:47:20

测试来自测量的大样本是否符合给定的分布通常是棘手的,因为任何偏离分布的情况都会被测试识别为异常值,并使测试拒绝该分布。

这就是我通常使用QQ-Plot实现此目的的原因。这是一个图形工具,其中X轴绘制数据的分位数,Y轴绘制拟合分布的分位数。图形分析允许选择对特定研究重要的分布部分:中心分散、下尾部或上尾部。

为此,我使用了DrawQQplot函数。

代码语言:javascript
复制
import openturns as ot
import numpy as np
sample = ot.Sample(s, 1)
tested_distribution = ot.NormalFactory().build(sample)
QQ_plot = ot.VisualTest.DrawQQplot(sample, tested_distribution)

这将生成以下图形。

QQ图验证了点在测试线上的分布。在目前的情况下,拟合是很好的,尽管我们注意到数据的极端分位数不是很好(正如我们可能预期的那样,考虑到这些事件的低概率密度)。

只是为了看看经常会发生什么,我尝试了BetaFactory,这显然是一个错误的选择!

代码语言:javascript
复制
tested_distribution = ot.BetaFactory().build(sample)
QQ_plot = ot.VisualTest.DrawQQplot(sample, tested_distribution)

这会产生以下结果:

qq图现在很清楚:中心区域的拟合是可以接受的,但低于-0.2或大于0.2的分位数是不能接受的。请注意,Beta及其4个参数足够灵活,可以很好地拟合0.2,0.2区间内的数据。

如果样本量很大,我宁愿使用KernelSmoothing而不是直方图。这更准确,即更接近真实的、未知的PDF (就阿米西里误差而言,内核平滑可以达到1/n^{4/5},而不是直方图的1/n^{2/3} ),并且是连续分布(您的分布似乎是连续的)。如果样本真的很大,则可以激活入库,从而降低CPU成本。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23251759

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档