python - 采样直方图,使样本的总和均匀

标签 python numpy statistics sampling

我有一个项目列表,我想从中随机抽取一个子集,但每个项目都与 D 个 bin 上的直方图配对,我想以总和直方图近似均匀的方式对项目进行抽样。

因此它应该像下面的示例函数一样工作:

>>> import numpy
>>> #The histograms from which to sample (each having 5 bins):
>>> data = numpy.random.randint(100, size=(10000,5))
>>> #The function which I'm trying to program:
>>> samples = sample(data,500)
>>> samples.shape
(500,5)
>>> summed_histogram = samples.sum(axis=0)
>>> #Each bin should have approximately equal value
>>> summed_histogram / float(summed_histogram.sum())
array([ 0.2,  0.2,  0.2,  0.2,  0.2])

求和直方图的绝对值并不重要,也不需要完全均匀,只需要近似均匀即可。另外,我不在乎返回的样本量是否不完全是指定的样本量。采样应无放回。

最佳答案

要扩展@Ilmari Karonen 的解决方案,您要做的是计算每个直方图的权重,然后根据这些权重进行采样。在我看来,鉴于您的目标,最有效的方法是使用 linear program

令 D_ij 为第 i 个项目的直方图中第 j 个 bin 的权重。然后,如果每个项目都用权重 w_i 加权,则“求和直方图”将具有权重和(项目中的 i)w_i D_ij。获得“近似均匀”分布的一种方法是最小化 bin 之间的最大差异,因此我们将解决以下 LP:

minimize z
subject to (for all j, k) 
    z >= (sum i in items) w_i D_ij - (sum i in items) w_i D_ik
    z >= (sum i in items) w_i D_ik - (sum i in items) w_i D_ij

上面基本上是说 z >= 所有加权 bin 对的差异的绝对值。要求解此 LP,您将需要一个单独的包,因为 numpy 不包含 LP 求解器。使用 cplex 的解决方案请参见 this gist,使用 cvxpy 的解决方案请参见 this gist。请注意,您需要像这些解决方案一样对权重设置一些约束(例如,每个权重大于或等于 0)。可以在此处找到 GLPK(GNU 线性编程工具包)的其他 python 绑定(bind):http://en.wikibooks.org/wiki/GLPK/Python

最后,您只需从权重为 w_i 的直方图 i 中采样。这可以通过使用 cumsumsearchsorted 调整轮盘选择来完成,正如@Ilmari Karonen 所建议的,参见 this gist

如果您希望生成的加权分布“尽可能均匀”,我会解决与权重类似的问题,但会最大化 bin 的加权总和中的加权熵。尽管您可以使用任意数量的非线性求解器(例如 BFGS 或基于梯度的方法),但此问题似乎是非线性的。这可能比 LP 方法慢一点,但这取决于您的应用程序需要什么。如果您有大量直方图,LP 方法会非常接近非线性方法,因为它很容易达到均匀分布。

当使用 LP 解决方案时,一堆直方图权重可能会绑定(bind)到 0,因为约束的数量很少,但这不会成为非平凡数量的 bin 的问题,因为约束的数量是 O (n^2).

具有 50 个直方图和 10 个 bin 的示例权重:

[0.006123642775837011, 0.08591660144140816, 0.0, 0.0, 0.0, 0.0, 0.03407525280610657, 0.0, 0.0, 0.0, 0.07092537493489116, 0.0, 0.0, 0.023926802333318554, 0.0, 0.03941537854267549, 0.0, 0.0, 0.0, 0.0, 0.10937063438351756, 0.08715770469631079, 0.0, 0.05841899435928017, 0.016328676622408153, 0.002218517959171183, 0.0, 0.0, 0.0, 0.08186919626269101, 0.03173286609277701, 0.08737065271898292, 0.0, 0.0, 0.041505225727435785, 0.05033635148761689, 0.0, 0.09172214842175723, 0.027548495513552738, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0259929997624099, 0.0, 0.0, 0.028044483157851748, 0.0, 0.0, 0.0]

有 50 个直方图,每个直方图有 50 个 bin,现在零值很少:

[0.0219136051655165, 0.0, 0.028325808078797768, 0.0, 0.040889043180965624, 0.04372501089775975, 0.0, 0.031032870504105477, 0.020745831040881676, 0.04794861828714149, 0.0, 0.03763592540998652, 0.0029093177405377577, 0.0034239051136138398, 0.0, 0.03079554151573207, 0.0, 0.04676278554085836, 0.0461258666541918, 9.639105313353352e-05, 0.0, 0.013649362063473166, 0.059168272186891635, 0.06703936360466661, 0.0, 0.0, 0.03175895249795131, 0.0, 0.0, 0.04376133487616099, 0.02406633433758186, 0.009724226721798858, 0.05058252335384487, 0.0, 0.0393763638188805, 0.05287112817101315, 0.0, 0.0, 0.06365320629437914, 0.0, 0.024978299494456246, 0.023531082497830605, 0.033406648550332804, 0.012693750980220679, 0.00274892002684083, 0.0, 0.0, 0.0, 0.0, 0.04465971034045478, 4.888224154453002]

关于python - 采样直方图,使样本的总和均匀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14791918/

相关文章:

python - 在 App Engine 应用程序中放置缓存驱逐逻辑的最佳位置在哪里?

python - 从 Numpy ndarray 中提取给定行和列的最快方法是什么?

java - 生成 [0,x] 范围内的正态分布时间戳

python - Tweepy 截断状态

python - 在 alpine 中安装 python3 包时出错

python - 在 matplotlib + numpy 中布置几个图

python - 在python中将2D数组插入3D数组

python - 高斯滤波器后合并接近的对象

python - Hotelling 在 python 中的 T^2 分数

r - R中的线性插值