问题:如何选择插值点,使每个插值段中任意点的最大误差保持在指定范围内?
目标是使用逆变换采样根据Zipf定律形成随机分布。我在这里找到了Zipf归一化因子的一个很好的近似值:
https://arxiv.org/abs/1511.01480("截断的Zeta分布的近似和Zipf的定律" Maurizio Naldi)
我现在正在做的是创建CDF值与排名的样条曲线,并尝试设置一个误差范围,使得没有排名的内插值超过其值的某个百分比(相对误差)。如果我有太多样条点,那会浪费内存。如果我的分数太少,则会增加误差。我试图找到样条点的最佳位置,以平衡这两个。
我当前的方法(失败)是遍历所有排名并查看连续排名之间PDF值的差异。这种差异是一阶导数的代理。我跟踪差值的MIN和MAX值,当它们与CDF的比例相差太大时,我假设曲线弯曲得太多,我添加了一个新的插值点并开始跟踪差异。该算法产生的插值点太少,因为误差比我预期的要快。
我有另一个想法:保持两个指针,一个在增长段的末端,一个在中点,前进一半的速度快。当中点误差变得太大时,添加一个新的插值点。但是,我不确定最差的错误是否必定在范围的中间。
我可以存储所有等级的CDF值(使用大量内存 - 我当前的应用程序最高等级为50万)。然后,我可以详尽地测试建议段的每个插值,并在错误变得太大时停止。我可以超调并进行二分查找以找到最佳的段长度 - 更快,但仍需要大量内存。我希望单通道或双通道在线算法具有适度的内存开销。
顺便说一下,对于每个样条线段,我尝试了以下插值函数:
线性 - 效果不佳。
二次方 - 更好,但仍然很差。
双曲线 - 对段的作用是Quadratic的两倍,但仍然不够好。 (如果我找到一种更好的方法来选择插值点,这可能就足够了。)
注意:双曲线的效果比预期好,因为高斯分布与大多数其他分布一样产生CDF的S曲线,Zipf PDF在开始时有峰值,所以它的CDF看起来像带有渐近线的双曲线之一。
更新
我采纳了我的一个想法。随着第二个指针的增长,我跟踪样条线段的中点,当中点的误差变得太大时,我结束该段并开始另一个。正如预期的那样,中点不是误差最大的地方,所以我将理想误差除以7,如果中点误差超过了我开始新的段。
以上是不够的。我发现由于最后一段保证在CDF = 1结束,最后一段实际到达渐近线。我对双曲线的拟合公式并不期望在等级达到无穷大之前达到渐近线,因此这会引入误差。因此,对于CDF = 1附近的最后几个段,我回退到使用抛物线拟合。
上述方法可以产生良好的CDF误差结果,但有时会导致往返计算结果不佳。如果我要求给定等级的CDF,则在反向查找中使用该CDF以找到等级,结果等级并不总是与原始等级匹配。我还在研究如何纠正这种往返错误。
答案 0 :(得分:0)
我解决了糟糕的往返协议问题。 CDF函数的等级在1处具有水平渐近线。反函数在N处具有垂直渐近线。我有错误的插值函数!
我发现延长段直到中点误差太大是一个很好的解决方案,与将每个段拟合到双曲线(除了最后一个段(或几个段))一致,我使用拉格朗日二次插值多项式拟合二次曲线。
对于N = 10000,我需要大约200个插值点来保持误差非常低。但如果我只是使用Zipf发行版进行测试,那么就足够了。