是否有算法来估计值集的中值,模式,偏度和/或峰度,但这不需要立即将所有值存储在内存中?
我想计算基本统计数据:
计算任何这些的基本公式是小学算术,我知道它们。还有许多统计库可以实现它们。
我的问题是我正在处理的集合中的大量(数十亿)值:在Python中工作,我不能只使用数十亿个元素创建列表或哈希。即使我用C语言编写,十亿元素数组也不太实用。
数据未排序。它是由其他过程随机,即时生成的。每组的大小变化很大,预先不知道大小。
我已经弄清楚如何很好地处理均值和方差,以任何顺序迭代集合中的每个值。 (实际上,在我的情况下,我按照它们生成的顺序来看它们。)这是我正在使用的算法,礼貌http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm:
这种“在线”算法存在缺陷(例如,精度问题,因为sum_of_squares快速增长大于整数范围或浮点精度),但它基本上给了我所需要的东西,而不必在每个集合中存储每个值。 / p>
但我不知道是否存在类似的技术来估计额外的统计数据(中位数,模式,偏度,峰度)。只要处理N值所需的内存远小于O(N),我就可以使用有偏差的估算器,甚至可以在一定程度上影响精度的方法。
如果图书馆具有“在线”计算这些操作中的一个或多个的功能,那么将我指向现有的统计库也会有所帮助。
答案 0 :(得分:53)
我使用这些增量/递归均值和中值估计值,它们都使用常量存储:
mean += eta * (sample - mean)
median += eta * sgn(sample - median)
其中 eta 是一个小的学习率参数(例如0.001), sgn ()是signum函数,它返回{-1,0,1}中的一个。 (如果数据是非平稳的并且您想跟踪随时间的变化,则使用常量 eta ;否则,对于固定源,您可以使用类似 eta = 1 / n的内容对于平均估计量,其中n是到目前为止看到的样本数...不幸的是,这似乎不适用于中位数估计量。)
这种类型的增量平均估计似乎可以在所有地方使用,例如在无监督的神经网络学习规则中,尽管有其优点(对异常值的鲁棒性),但中位数似乎不太常见。似乎在许多应用中,中位数版本可以用作平均估计量的替代。
我很想看到类似形式的增量模式估算器......
<强>更新强>
我刚刚修改了增量中值估计量来估计任意分位数。通常,分位数函数(http://en.wikipedia.org/wiki/Quantile_function)告诉您将数据分成两个分数的值:p和1-p。以下内容逐步估算此值:
quantile += eta * (sgn(sample - quantile) + 2.0 * p - 1.0)
值p应在[0,1]范围内。这实际上将 sgn ()函数的对称输出{-1,0,1}向一侧倾斜,将数据样本划分为两个不等大小的二进制位(分数p和1-p)数据分别小于/大于分位数估计值。请注意,对于p = 0.5,这会降低到中值估计值。
答案 1 :(得分:51)
偏斜和Kurtosis
对于Skewness和Kurtosis的在线算法(沿着方差线),请参阅同一个wiki页面here中用于更高时刻统计的并行算法。
<强>中值强>
没有分类数据,中位数很难。如果你知道,你有多少数据点,理论上你只需要进行部分排序,例如:使用selection algorithm。然而,这对数十亿的价值观没有多大帮助。我建议使用频率计数,请参阅下一节。
有频率计数的中位数和模式
如果是整数,我会指望 frequencies,可能会切断超出某个值的最高值和最低值,我确信它不再相关。对于浮点数(或者整数太多),我可能会创建存储桶/间隔,然后使用与整数相同的方法。 (近似)模式和中值计算比根据频率表变得容易。
正态分布随机变量
如果它是正态分布的,我会使用总体样本mean,variance,skewness和kurtosis作为小子集的最大似然估计。用于计算这些的(在线)算法,你现在已经。例如。读入数十万或数百万个数据点,直到您的估计误差变得足够小。只需确保从您的集合中随机选择(例如,您不会通过选择前100'000值来引入偏差)。同样的方法也可用于估计正常情况下的模式和中位数(因为样本均值是一个估计量)。
进一步评论
以上所有算法都可以并行运行(包括许多排序和选择算法,例如QuickSort和QuickSelect),如果这有帮助的话。
我一直假设(除了关于正态分布的部分)我们讨论样本矩,中位数和模式,而不是给定已知分布的理论矩的估计。
一般来说,只要所有观察都是相同随机变量(具有相同分布)和时刻的实现,给定数据量,对数据进行采样(即仅查看子集)应该非常成功,这种分布实际上存在,模式和中位数。最后一个警告并非无害。例如,Cauchy Distribution的均值(和所有更高的时刻)不存在。在这种情况下,“小”子集的样本均值可能与整个样本的样本均值大量偏离。
答案 2 :(得分:9)
我在一个名为P-Square Algorithm for Dynamic Calculation of Quantiles and Histograms without Storing Observations的简洁Python模块中实现了LiveStats。它应该非常有效地解决你的问题。除了模式之外,该库支持您提到的每个统计信息。我还没有找到一个令人满意的模式估计解决方案。
答案 3 :(得分:7)
我无法想到模式和中位数的任何在线方法,这似乎需要立即考虑整个列表。但是,与方差和均值相似的方法很可能也适用于偏度和峰度......
答案 4 :(得分:3)
该问题中引用的维基百科文章包含了在线计算偏度和峰度的公式。
对于模式 - 我相信 - 没有办法在网上这样做。为什么?假设输入的所有值除了与前一个值重复的最后一个值之外是不同的。在这种情况下,您必须记住输入中已经看到的所有值,以检测最后一个值是否与所看到的值重复并使其成为最常见的值。
对于中位数,它几乎是相同的 - 直到最后一个输入,如果所有输入值都不同,你不知道哪个值将成为中位数,因为它可能在当前中位数之前或之后。如果您知道输入的长度,您可以找到中位数而不将所有值存储在内存中,但您仍然需要存储其中的许多值(我猜大约一半),因为错误的输入序列可能会在下半场可能从上半场中位数做出任何价值。
(请注意,我仅提到精确计算。)
答案 5 :(得分:2)
如果你有数十亿的数据点,那么你不太可能需要确切的答案,而不是关闭答案。通常,如果您有数十亿个数据点,那么生成它们的基础过程可能会遵循某种统计平稳性/遍历性/混合属性。您是否期望分布合理连续也可能无关紧要。
在这些情况下,存在分位数的在线,低内存,估计的算法(中位数是0.5分位数的特殊情况),以及模式,如果你不这样做需要确切的答案。这是一个活跃的统计领域。
分位数估算示例:http://www.computer.org/portal/web/csdl/doi/10.1109/WSC.2006.323014
模式估算示例:Bickel DR。连续数据模式和偏度的稳健估计。计算统计和数据分析。 2002; 39:153-163。 doi:10.1016 / S0167-9473(01)00057-3。
这些是计算统计的活跃字段。你进入的领域没有任何单一的最精确算法,但是它们的多样性(统计估计,实际上),它们具有不同的属性,假设和性能。这是实验数学。关于这个问题可能有数百到数千篇论文。
最后一个问题是你是否真的需要偏斜和峰度,或者更可能是一些其他参数在表征概率分布时可能更可靠(假设你有概率分布!)。你期待高斯吗?
您是否有办法清理/预处理数据以使其主要为高斯数据? (例如,金融交易金额在取对数后通常有些高斯)。您是否期望有限的标准偏差?你期待肥尾吗?您在尾巴或散装中关注的数量是多少?
答案 6 :(得分:2)
每个人都在说你不能以在线方式进行这种模式,但事实并非如此。这是一个article描述了一个算法,它可以解决耶鲁大学Michael E. Fischer和Steven L. Salzberg在1982年发明的这个问题。来自文章:
多数查找算法将其中一个寄存器用于临时 从流中存储单个项目;这个项目是当前的 多数元素的候选人。第二个寄存器是一个计数器 初始化为0.对于流的每个元素,我们询问算法 执行以下程序。如果计数器读数为0,请安装 当前流元素作为新的多数候选者(取代任何 可能已存在于寄存器中的其他元素)。然后,如果 当前元素匹配多数候选者,递增计数器; 否则,递减计数器。在循环的这一点,如果 到目前为止看到的流的一部分有一个多数元素,那个元素是 在候选者寄存器中,并且计数器保持大于的值 0.如果没有多数元素怎么办?没有第二次通过数据 - 这在流环境中是不可能的 - 算法不能总是给出一个明确的答案 环境。它只是承诺正确识别大多数人 元素,如果有的话。
它也可以扩展为找到具有更多内存的前N个,但这应该解决它的模式。
答案 7 :(得分:1)
最终,如果您没有关于分布的先验参数知识,我认为您必须存储所有值。
除非你正在处理某种病态,否则补救措施(Rousseuw和Bassett 1990)可能对你的目的而言足够好。
非常简单,它涉及计算批次中位数的中位数。
答案 8 :(得分:0)
中位数和模式。但是,因为中位数和模式无论如何都比“定量”更“描述”,你可以估计它们,例如通过对数据集进行抽样。
如果从长远来看数据是正态分布的,那么你可以用你的均值估算中位数。
您还可以使用以下技术估算中位数:为数据流中的每个(例如1,000,000个条目)建立中位数估计M [i],以便M [0]是前100万个条目的中位数,M [ 1]第二百万个条目的中位数等。然后使用M [0] ... M [k]的中值作为中值估计量。这当然节省了空间,您可以通过“调整”参数1,000,000来控制您想要使用多少空间。这也可以递归推广。
答案 9 :(得分:0)
好的老兄试试这些:
for c ++:
double skew(double* v, unsigned long n){
double sigma = pow(svar(v, n), 0.5);
double mu = avg(v, n);
double* t;
t = new double[n];
for(unsigned long i = 0; i < n; ++i){
t[i] = pow((v[i] - mu)/sigma, 3);
}
double ret = avg(t, n);
delete [] t;
return ret;
}
double kurt(double* v, double n){
double sigma = pow(svar(v, n), 0.5);
double mu = avg(v, n);
double* t;
t = new double[n];
for(unsigned long i = 0; i < n; ++i){
t[i] = pow( ((v[i] - mu[i]) / sigma) , 4) - 3;
}
double ret = avg(t, n);
delete [] t;
return ret;
}
你说你已经可以计算样本方差(svar)和平均值(平均值) 你指出那些你的功能。
另外,看看Pearson的近似值。在这么大的数据集上它会非常相似。 3(平均值 - 中位数)/标准差 你的中位数为max - min / 2
对于浮点模式没有任何意义。人们通常会把它们放在一个非常大的箱子里(比如1/100 *(最大 - 最小))。
答案 10 :(得分:0)
答案 11 :(得分:-1)
我倾向于使用桶,这可能是自适应的。铲斗尺寸应该是您需要的精度。然后,当每个数据点进入时,将一个数据点添加到相关存储桶的计数中。 这些应该通过计算每个桶作为其计数加权值来为您提供中位数和峰度的简单近似值。
一个问题可能是数十亿次操作后浮点的分辨率损失,即添加一个不再改变值!为了解决这个问题,如果最大铲斗尺寸超过某个限制,您可以从所有计数中取出大量数据。
答案 12 :(得分:-1)
dynamic