Python 计算流中的标准偏差

Python 计算流中的标准偏差,python,math,Python,Math,使用Python,假设我正在运行已知数量的项目I,并且能够计算处理每个t所需的时间,以及处理t所花费的运行总时间和到目前为止处理的项目数c。我目前正在计算动态平均值A=T/c,但这可能会因为单个项目的处理时间过长(几秒钟而不是几毫秒)而发生偏差 我想显示一个连续的标准偏差。如何在不记录每个t的情况下做到这一点?如中所述,记录以下三个总数就足够了: s0 = sum(1 for x in samples) s1 = sum(x for x in samples) s2 = sum(x*x for

使用Python,假设我正在运行已知数量的项目
I
,并且能够计算处理每个
t
所需的时间,以及处理
t
所花费的运行总时间和到目前为止处理的项目数
c
。我目前正在计算动态平均值
A=T/c
,但这可能会因为单个项目的处理时间过长(几秒钟而不是几毫秒)而发生偏差

我想显示一个连续的标准偏差。如何在不记录每个
t
的情况下做到这一点?

如中所述,记录以下三个总数就足够了:

s0 = sum(1 for x in samples)
s1 = sum(x for x in samples)
s2 = sum(x*x for x in samples)
当新值到达时,这些总和很容易更新。标准偏差可计算为:

std_dev = math.sqrt((s0 * s2 - s1 * s1)/(s0 * (s0 - 1)))
请注意,如果您的样本是浮点数,并且与样本的平均值相比,标准偏差很小,那么这种计算标准偏差的方法在数值上可能是病态的。如果你希望得到这种类型的样本,你应该求助于Welford的方法(见公认的答案)。

我使用的方法,它可以提供更准确的结果。此链接指向。这里有一段总结了为什么它是首选方法:

这种更好的计算方差的方法可以追溯到B.p.Welford 1962年的一篇论文,发表在Donald Knuth的《计算机编程艺术》,第2卷,第232页,第3版。虽然这种解决方案已经被人们知道了几十年,但了解它的人还不够多。大多数人可能不知道计算样本方差可能很困难,直到他们第一次计算标准偏差时,才发现取负数的平方根是个例外

基于:

使用每一条新数据更新差异:

N = 100
data = np.random.random(N)
ov = OnlineVariance(ddof=0)
for d in data:
    ov.include(d)
std = ov.std
print(std)
对照numpy计算的标准偏差检查我们的结果:

assert np.allclose(std, data.std())

请看这里:您可能还想看看不能将
s0
更简单地计算为
length(samples)
,将
s1
计算为
sum(samples)
?@Benjamin:当然。但是OP不想跟踪
样本
。我选择这种语法是为了明确在每次迭代中要添加什么(以及它的对称性)。@Benjamin:Sven以编程方式显示,标准偏差定义为数据的第零、第一和第二时刻的函数。对于一个样本,(s0*(s0-1))==0,当然,这个算法虽然简单,但比Welford的算法更容易受到数字溢出的影响。阅读John Cook的概述,我没有提到如何合并加权值。对于@SvenMarnach的帖子中的方法,wikipedia()提到对s0、s1和s2使用加权值将产生正确的结果。这似乎是有可能的,但你知道韦尔福德的方法是否也是如此吗?我对加权法也很好奇。给定的解决方案似乎给出了数据流整个历史的方差。对于某些流媒体域,我可以看到,将值加权以表示最近数据点的方差,并使较旧的样本消失是多么有用。对于默认ddof,一个在第一轮崩溃,然后n=1,方差被零除。解决方法是将方差作为属性,这样就不会在线计算方差。
assert np.allclose(std, data.std())