我正在寻找一种优雅而有效的方式来表示和存储由显式采样构建的任意概率分布。
预计分配具有以下属性:
[-4000; 4000]
a
,b
,|a - b| < 40
通常的表示 - 直方图阵列 - 是不受欢迎的,主要是因为量化/分辨率和空间之间的权衡。我想必须有一种表示方法,根据当地的“复杂性”自适应地改变bin大小。
空间是值得关注的,因为更高级别的网格状数据结构将包含数千个单元,每个单元包含至少一个这样的概率表示。需要轻松序列化磁盘或网络传输,但效率不是优先考虑的事项。
任何帮助都将不胜感激。
答案 0 :(得分: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;
};
现在,存储部分:
通常的表示 - 直方图数组 - 主要是不受欢迎的 因为量化/分辨率和空间之间的权衡。一世 想象一下必须有一种自适应的表示方法 根据当地的“复杂性”改变垃圾箱大小。
传统方法是wavelets。您可以通过调用integrate
来生成系数,您可以将其序列化。如果它们产生的积分估计的方差很高,你就会抛出系数。
然后,要反序列化,可以生成Distribution
对象,其integrate
方法执行与小波的集成。可以使用您最喜欢的正交方法进行积分。我在这里故意模糊不清,因为实际的实现取决于你选择的小波族(平滑,紧凑支持,正交与否等)。无论如何,你需要深入了解文章。
这里的要点是,你通常只需要非常少的小波来表示具有少量特征的平滑函数(比如几个峰,并且通常形状为其他形状),不像更多“常规”有限元(直方图是一种特殊的有限元)元素表示)。小波表示适应变换的特征,无论其位置或大小如何。此外,您还可以决定要保留多少个系数,从而控制压缩率。
另外,0.001数字是一个非常高的数字:我怀疑你只需要一些系数
权衡取决于您使用的小波类:非常平滑的分布很可能用平滑小波很好地表示,但紧凑支持的小波可能更容易集成,等等。实验。请注意,这里不需要“小波变换”包:只有小波函数和正交例程的显式表示(尝试使用Gauss-XXX程序进行重建,或者高阶处理)。
我倾向于在傅立叶域中定义的小波(如Lemarie小波),因为它们在傅里叶空间中的值和导数为零已知,这允许您强制执行分布的约束:概率度量必须整合到一,你可能事先知道预期的价值或方差。
此外,您可能希望将变量更改为仅处理函数,例如。在[0,1]上。这段时间里有关于小波的大量文献。
答案 1 :(得分:1)
这个怎么样:
我假设我们从相当于直方图的数据开始,即带有与之关联的样本数的间隔列表。
现在让我们通过一个简单的直方图开始构建一个近似值,其中一个桶包含所有样本。
对于近似中的所有桶,考虑将它在中间分成两个桶,但实际上只拆分桶将在近似中产生最佳改进。
重复直到达到所需的近似值或获得最大可接受的桶数。
所以你需要的是一种识别要分割的最佳桶的方法。我想说新桶的最大偏差与原始桶的一半相比可能有效。
你还需要一些标准才能停下来。
我认为这实际上与1D中的八叉树很相似。你可能会在那里寻找有效的实现。
对于实际存储您可能的近似值,只需将一个阵列与存储桶边界存储在一起,另一个存储每个存储桶的内容。或者一个两倍大小的数组,具有交替的桶边界和内容值。
答案 2 :(得分:1)
我强烈建议您查看all of the distribution models available in SciPy。他们最大程度地解决了这个问题,而我提出的任何试图解决分辨率粒度问题的规范算法都将是他们至少切向考虑的问题。
如前所述here,多重数据的八叉树似乎是您所需的数据结构的正确表示。您的目标是在不同固定粒度级别的数据集中存储扰动,而不是包含受限于死记硬背箱的数据的扁平直方图。这与用于JPEG compression的算法最相似,还希望在某种程度的粒度和复杂度下从分布中提取样本。
为了创建分类算法或 dichotomizer 来填充数据结构,我强烈建议您查看像JPEG 2000这样的分解算法,以确定其形状和复杂性。数据中的扰动。其他方法(例如,ID3和C4.5)也可能是合适的,但我觉得简单的矢量化分解可能适用于您的目的。
并且,对于它的价值,如果你在空间内找到更适用的算法,我将非常感兴趣。我直接与对数据中的多尺度关系感兴趣的研究人员合作,所以如果你发现更有效的事情,请告诉我们!
答案 3 :(得分:0)
存储n个分位数。他们将自适应地围绕模式进行聚类。
令n为2的幂,则密度(和累积概率)查找可以通过将分位数作为中位数的二叉树和递归的“子中位数”存储来限制为O(log(n))。 / p>