寻求关于概率分布数据表示的建议

16

我正在寻找一种优雅且高效的方式来表示和存储由显式抽样构建的任意概率分布。

该分布应具有以下特性:

  • 样本是浮点数,但原则上可以认为其分辨率高达0.001
  • 样本取自区间[-4000; 4000]
  • 然而,对于任何两个样本ab|a - b| < 40
  • 90%的时间内,它将具有一个或几个靠近彼此的尖锋
  • 10%的时间内,它将具有一个不平坦的高原峰,宽度为0.5到5。

通常的表示方法——直方图数组——并不理想,主要是因为量化/分辨率和空间之间的权衡。我想象中必须有一种表示方法,根据局部“复杂性”自适应地变化bin大小。

空间是一个问题,因为更高级别的类似网格的数据结构将包含成千上万个单元格,每个单元格至少包含一个这样的概率表示。易于磁盘或网络传输的序列化是可取的,但效率不是优先考虑的因素。

任何帮助都将不胜感激。


那么,可以接受多少精度损失呢?如果不想存储原始数据点,则信息损失(几乎?)是不可避免的。 - Konrad Rudolph
1
冒昧地说,我无法直接回答这个问题。在最坏的情况下,我可以将数据量化到0.01,尽管0.001更好。理想情况下,我希望有一种自适应解决方案,根据局部密度最大化精度。也就是说,如果我的95%数据集中在中位数的1个单位内,我希望该区域具有最高的精度,但剩余的5%可能不太精确。 - George Skoptsov
我并不是统计学家或数学家,所以如果我说的话没有意义,请原谅。但是,使用像FLAC这样的算法压缩内存数据是否有可能解决那种问题呢?因为音频波形与你的数据有些相似。我也在想是否可能使用某种插值形式...... - SirDarius
你是否考虑将数据量化为类似于八叉树(但是在一维空间中),其中详细程度/分裂增加的地方具有更多的细节/振幅?http://en.wikipedia.org/wiki/Octree - Akanksh
绝对最优的概率分布压缩方法被称为算术编码(有人说它等同于范围编码)。然而,它受到专利限制。一个天真的17位增量编码器可以将浮点数的存储大小减少约53%。一个模拟数据集的自适应增量编码器会做得更好,也许可以达到约70%。线性预测+ rice-golomb 编码(如 FLAC)也应该适合您的需求。 - std''OrgnlDave
显示剩余5条评论
4个回答

5
有趣的问题。这里有一个建议,根据您在数学方面的倾向程度,可能很难实现。
请注意,我为了速度而交换了空间,因为我建议的东西很可能在计算上非常繁重(但需要根据实际数据进行测试)。
首先,使用一种功能方法。概率分布是一个概率测度:
struct Distribution
{
    virtual ~Distribution() {};
    virtual double integrate(std::function<double(double)>) = 0;
};

这样,你可以抽象出你生成的样本,因为你不想储存它们。相信自己可以用“整合”方法做任何事情。
当然,对于明确的样本,你可以做如下操作:
struct SampledDistribution
{
    double integrate(std::function<double(double)> f)
    {
        double acc = 0;
        for (double x: samples) acc += f(samples);
        return acc / samples.size();
    }

    std::deque<double> samples;
};

现在,存储部分:
传统的表示方法——直方图数组——不太理想,主要是因为量化/分辨率和空间之间的权衡。我想必定有一种表示方法,可以根据本地“复杂性”自适应地改变箱子大小。
传统的方法是小波。您可以通过调用integrate来生成系数,并将其序列化。如果积分估计器产生的方差很高,则可以丢弃系数。
然后,要进行反序列化,您需要生成一个Distribution对象,其integrate方法针对小波执行积分。可以使用您喜欢的数值积分方法进行积分。我在这里故意保持模糊,因为实际实现取决于您选择的小波族(平滑、紧支撑、正交或非正交等)。无论如何,您都需要深入研究文献以获取详细信息。
这里的重点是,通常只需要很少的小波来表示具有少量特征(比如几个峰值和其他规则形状)的平滑函数,不像更“常规”的有限元素(直方图是一种有限元素表示)。小波表示自适应于变换对象的特征,无论它们的位置或大小如何。此外,您可以决定保留多少系数,从而控制压缩比率。
另外,0.001的数字相当高:我怀疑您只需要少量系数。
权衡在于使用哪种小波类别:非常平滑的分布可能会用平滑小波很好地表示,但紧支持小波可能更容易集成等。实验。注意,您不需要“小波变换”包:只需要小波函数的显式表示和积分程序(尝试Gauss-XXX过程进行重建,或者使用某些高阶方法)。
我倾向于使用在傅里叶域中定义的小波(例如Lemarie小波),因为它们在傅里叶空间中的值和导数为零是已知的,这使您可以强制执行对分布的约束:概率测度必须集成为1,并且您可能事先知道期望值或方差。
此外,您可能希望将变量更改为仅处理函数,例如在[0,1]上。有大量关于区间小波的文献。

+1,好答案。而且,因为你(正确地)将波动理论带入讨论中,我想我会在这里留下它。 :) - MrGomez
@MrGomez:说得好。在傅里叶空间中定义小波在这里有优势。让我来详细解释一下。 - Alexandre C.
@AlexandreC。我最喜欢你的答案。如果您知道现有实现的更多详细信息和指针,那将是很好的。无论如何,由于赏金即将到期,我将授予您该奖励。 - George Skoptsov

2

我强烈建议您查看SciPy中提供的所有分布模型。它们与这个问题密切相关,而且任何我想出来的旨在解决分辨率粒度问题的特定算法都是他们至少间接考虑过的。

正如此处所提到的,对于多重分辨率数据,八叉树似乎是您所需的正确数据结构表示。您的目标不是包含数据限制在固定区间内的平坦直方图,而是在不同级别的固定粒度下存储扰动数据集。这最类似于JPEG压缩所使用的算法,但还希望从某个粒度和复杂度水平的分布中提取样本。

如果要创建一个分类算法或二分器来填充数据结构,我强烈建议查看像JPEG 2000这样的分解算法,以确定数据中扰动的形状和复杂性。其他方法(例如ID3C4.5)也可能适用,但我认为简单的向量化分解可能适合您的目的。

另外,如果您在该领域找到更适用的算法,我会非常感兴趣。我直接与对数据中多尺度关系感兴趣的研究人员合作,因此如果您发现更有效的算法,请务必告诉我们!


1

存储n个分位数。它们将自适应地聚集在众数周围。

假设n是2的幂次方,则可以通过递归地将分位数存储为中位数和“子中位数”的二叉树,将密度(和累积概率)查找限制为O(log(n))。


1

这样怎么样:

我假设我们从等价于直方图的数据开始,即一个区间列表,其中包含与之关联的样本数。

现在让我们通过从一个包含所有样本的简单直方图开始来构建它的近似值。

对于近似中的所有桶,请考虑将其分成两个桶的中间部分,但只实际分割将产生最佳改进的桶。

重复此过程,直到达到所需的近似值或获得可接受的最大桶数为止。

因此,您需要一种识别最佳拆分桶的方法。我认为新桶与原始桶的一半相比的最大偏差可能有效。

您还需要一些标准来确定何时停止。

我认为这实际上与1D Octree非常相似。您可以在那里寻找高效的实现。

要实际存储近似值,您可以仅使用一个数组存储桶边界和另一个数组存储每个桶的内容。或者使用大小为两倍的一个数组,其中交替存储桶边界和内容值。


我试图避免存储显式值。否则,这些桶会包含显式值;否则我怎么能将它们分开呢?或者您是否有不同的表示方法?我认为在这里一个均值和标准差的元组是行不通的;桶中样本的分布不会是高斯的。 - George Skoptsov
你需要从显式的值开始,然后根据这些值构建一个近似值。这就是我在回答中试图勾画出的内容。 - Jens Schauder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接