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

Geo*_*sov 13 c++ probability data-structures

我正在寻找一种优雅而有效的方式来表示和存储由显式采样构造的任意概率分布.

该分布预计具有以下属性:

  • 样本是浮点值,但原则上可以认为分辨率低至.001
  • 从间隔中抽取样本 [-4000; 4000]
  • 然而,对于任何两个样本a,b,|a - b| < 40
  • 90%的时间,它会有一个尖锐的峰值或几个尖锐的峰值彼此接近
  • 10%的时间,它将有一个峰值,高度不均匀,宽度为0.5到5.

通常的表示 - 直方图阵列 - 是不希望的,主要是因为量化/分辨率和空间之间的权衡.我想必须有一种表示方法,根据本地"复杂性"自适应地改变bin大小.

空间是值得关注的,因为更高级别的网格状数据结构将包含数千个单元,每个单元包含至少一个这样的概率表示.需要轻松序列化磁盘或网络传输,但效率不是优先考虑的事项.

任何帮助,将不胜感激.

Ale*_* C. 5

有趣的问题.这是一个建议,根据您在数学上倾向的程度,这可能很难实现.

请注意,我交换空间的速度,因为我建议的计算可能相当繁重(但这是针对实际数据进行测试).

首先,使用功能方法.概率分布是概率测量:

struct Distribution
{
    virtual ~Distribution() {};
    virtual double integrate(std::function<double(double)>) = 0;
};
Run Code Online (Sandbox Code Playgroud)

这样,您就可以从您生成的样本中抽象出来,因为您不想存储它们.说服自己,你可以通过"整合"方法做很多事情.

当然,使用显式样本,您可以执行类似的操作

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;
};
Run Code Online (Sandbox Code Playgroud)

现在,存储部分:

通常的表示 - 直方图阵列 - 是不希望的,主要是因为量化/分辨率和空间之间的权衡.我想必须有一种表示方法,根据本地"复杂性"自适应地改变bin大小.

传统的方法是小波.您可以通过调用生成系数integrate,您可以将其序列化.如果它们产生的积分估计的方差很高,则抛出系数.

然后,要反序列化,您将生成一个Distribution对象,其integrate方法执行与wavelet的集成.可以使用您最喜欢的正交方法进行积分.我在这里故意模糊不清,因为实际的实现取决于你选择的小波族(平滑,紧凑支持,正交与否等).无论如何,您需要深入了解文章.

这里的要点是,您通常只需要很少的小波来表示具有少量特征的平滑函数(比如几个峰,并且通常形状为其他形状),这与更多"常规"有限元不同(直方图是一种特殊的有限元表示) .小波表示适应变换的特征,无论其位置或大小如何.此外,您还可以决定要保留多少系数,从而控制压缩比.

此外,0.001数字是一个非常高的数字:我怀疑你只需要一些系数

权衡取决于您使用的小波类:非常平滑的分布很可能用平滑小波很好地表示,但紧凑支持的小波可能更容易集成,等等.实验.请注意,这里不需要"小波变换"包:只有小波函数和正交例程的显式表示(尝试Gauss-XXX程序用于重建,或者高阶命令).

我倾向于在傅立叶域中定义的小波(如Lemarie小波),因为它们在傅里叶空间中的值和导数为零已知,这允许您强制执行分布上的约束:概率度量必须与一个集成,并且您可能事先知道预期的价值或差异.

此外,您可能希望将变量更改为仅处理函数,例如.在[0,1]上.在这个区间有一个关于小波的大量文献.