Math 如何使用Welford'计算更新和删除的值;s在线算法

Math 如何使用Welford'计算更新和删除的值;s在线算法,math,statistics,event-sourcing,Math,Statistics,Event Sourcing,用例:流式传输大量事件源数据,这些数据可能具有插入、更新和删除,并且具有保证的顺序 假设Welford的算法以这种形式出现在用于插入的事件流中: private double\u count=0; 私人双平均值=0; 私有双精度_s=0; 公共空白插入(双值) { var prev_平均值=_平均值; _计数=_计数+1; 如果(_count==1) { _平均值=数值; _s=0; } 其他的 { _平均值=_平均值+(值-_平均值)/_计数; _s=_s+(值-平均值)*(值-上一个平均值)

用例:流式传输大量事件源数据,这些数据可能具有插入、更新和删除,并且具有保证的顺序

假设Welford的算法以这种形式出现在用于插入的事件流中:

private double\u count=0;
私人双平均值=0;
私有双精度_s=0;
公共空白插入(双值)
{
var prev_平均值=_平均值;
_计数=_计数+1;
如果(_count==1)
{
_平均值=数值;
_s=0;
}
其他的
{
_平均值=_平均值+(值-_平均值)/_计数;
_s=_s+(值-平均值)*(值-上一个平均值);
}
}
公共双变量=>((u计数>1)?(u计数-1):0.0;
公共双StDev=>Math.Sqrt(Var);
如果已知预先存在的值,是否可以更改在线统计数据。还是会有比韦尔福德算法更合适的方法来满足需求

公共作废更新(前一个值加倍,前一个值加倍)
{
//我得到的值是正确的
var prev_mean=(_count*_mean-value)/(_count-1);
//我做了反转,但这没有给出正确的值
var prev_s=-previousValue^2+previousValue*prev_mean+_mean*previousValue-_mean*prev_mean+_s
}
public void Delete(以前的两倍值)
{
_计数=_计数-1;
}
编辑

具体问题如下:

在更新的情况下,如何计算_mean和_s的正确值

在删除的情况下,如何计算_mean和_s的正确值?

部分答案(如果我完成求解,将更新):

我最初在更新时的反转错误

编辑

一旦我解决了更新问题,删除就变得微不足道了

private void更新(前一个值加倍,前一个值加倍)
{
如果(_count==1)
{
_平均值=数值;
_s=0;
}
其他的
{
var prev_mean=(_count*_mean-previousValue)/(_count-1);
var prev_s=-(_mean*prev_mean)+(_mean*previousValue)+(prev_mean*previousValue)-数学功率(previousValue,2)+;
//还原均值和S
_平均值=上一次平均值;
_s=上一个;
//执行与插入相同的操作
_平均值=_平均值+(值-_平均值)/_计数;
_s=上一个s+(值-平均值)*(值-上一个平均值);
}
}
public void Delete(以前的两倍值)
{
_计数=_计数-1;
如果(_count==0)
{
_平均值=0;
_s=0;
返回;
}
如果(_count==1)
{
_平均值=(\u计数*\u平均值-以前的值)/(\u计数-1);
_s=0;
返回;
}
其他的
{
var prev_mean=(_count*_mean-previousValue)/(_count-1);
var prev_s=-(_mean*prev_mean)+(_mean*previousValue)+(prev_mean*previousValue)-数学功率(previousValue,2)+;
//还原均值和S
_平均值=上一次平均值;
_s=上一个;
}
}
编辑 好的,我找到了一个更好的原始算法的实现,以此为基础,然后在Wolfram Mathematica的帮助下,我能够解决我需要的反演问题。我在本地做了一个测试,有一百万个随机活动(插入、更新、随机删除)

我用这个作为逻辑 Assert.IsTrue(Math.Abs(x-y)<.0000001)

其中,x是c#中的本机2次通过算法,y是此实现的值。看起来本机实现完成了一些本机没有完成的事情

在此插入基于工作的方法

删除方法是我自己的工作

公共类统计跟踪器
{
私有长n=0;
私人双和,M1,M2,M3,M4=0.0;
公共长计数=>n;
公共双平均值=>(n>2)?M1:0.0;
公共双和=>\u和;
公共双Var=>M2/(n-1.0);
公共双StDev=>Math.Sqrt(Var);
//公共双偏态=>数学Sqrt(n)*M3/数学功率(M2,1.5);
//公共双峰度=>(双)n*M4/(M2*M2)-3.0;
公共空白插入(双x)
{
双三角洲,三角洲n,三角洲n2,term1;
_总和+=x;
长n1=n;
n++;
δ=x-M1;
delta_n=delta/n;
term1=δ*δn*n1;
M1=M1+δn;
M2+=第1项;
//偏度和峰度要求
//以后会解决的
//delta_n2=delta_n*delta_n;
//M3+=第1项*delta_n*(n-2)-3项*delta_n*M2;
//M4+=term1*δn2*(n*n-3*n+3)+6*δn2*M2-4*δn*M3;
}
公共作废更新(双倍上一个值,双倍值)
{
删除(以前的值);
插入(价值);
}
公共作废删除(双x)
{
VarO=((M1*n)-x)/(n-1.0);
var v=M2;
变量y2=((n-1.0)*数学功率(o,2.0)+(2.0*(n-1)*o*x)+(n*(v-数学功率(x,2.0))+数学功率(x,2.0))/n;
M1=o;
M2=y2;
n=n-1;
_总和-=x;
}
}

Hmm,不清楚您所说的“根据已知的预先存在的值更改在线统计数据”是什么意思。我想也许你需要多说你想做什么。另外,这看起来更像是一个讨论问题,而不是一个特定的编程问题,因此stats.stackexchange.com是一个更合适的论坛。@RobertDodier为了清晰起见,我更新了这个问题。我现在明白你的意思了。这实际上是一个非常有趣的问题,所以它是离题的。Stats.stackexchange.com将提供更多有用的信息。祝你好运,玩得开心。非常接近,我把它扔进了一个sharplab.io中,然后旋转了一下。。。我发现了一些我正在处理的边缘情况。@DavidPine我有一个数值上更稳定的解决方案,
y2
assignme