加速循环以用另一个数组中最接近的值填充数组

加布里埃尔

我有一段代码需要优化,因为我必须运行数千次。

它的作用是在给定数组的子列表中为随机浮点数找到最接近的浮点数,并将相应的浮点数(即具有相同索引)存储在该数组的另一个子表中。重复该过程,直到存储的浮点数的总和达到某个限制。

这是MWE为了使其更清楚:

import numpy as np

# Define array with two sub-lists.
a = [np.random.uniform(0., 100., 10000), np.random.random(10000)]

# Initialize empty final list.
b = []

# Run until the condition is met.
while (sum(b) < 10000):

    # Draw random [0,1) value.
    u = np.random.random()
    # Find closest value in sub-list a[1].
    idx = np.argmin(np.abs(u - a[1]))
    # Store value located in sub-list a[0].
    b.append(a[0][idx])

该代码相当简单,但是我还没有找到一种加速它的方法。我试图使我前段时间提出的类似问题中给出的出色(且非常快)的答案无济于事。

ali_m

好的,这是一个稍微偏左的建议。据我了解,您只是尝试从中的元素进行统一采样,a[0]直到列表总数超过某个限制为止。

尽管在内存方面会花费更多,但我认为您可能会发现,从头a[0]开始生成大量随机样本,然后求和,并首先发现超出限制的位置会更快。

例如:

import numpy as np

# array of reference float values, equivalent to a[0]
refs = np.random.uniform(0, 100, 10000)

def fast_samp_1(refs, lim=10000, blocksize=10000):

    # sample uniformally from refs
    samp = np.random.choice(refs, size=blocksize, replace=True)
    samp_sum = np.cumsum(samp)

    # find where the cumsum first exceeds your limit
    last = np.searchsorted(samp_sum, lim, side='right')
    return samp[:last + 1]

    # # if it's ok to be just under lim rather than just over then this might
    # # be quicker
    # return samp[samp_sum <= lim]

当然,如果blocksize元素样本的总和为<lim,那么将无法为您提供总和> = lim的样本。您可以检查是否存在这种情况,并在必要时循环添加到样本中。

def fast_samp_2(refs, lim=10000, blocksize=10000):

    samp = np.random.choice(refs, size=blocksize, replace=True)
    samp_sum = np.cumsum(samp)

    # is the sum of our current block of samples >= lim?
    while samp_sum[-1] < lim:

        # if not, we'll sample another block and try again until it is
        newsamp = np.random.choice(refs, size=blocksize, replace=True)
        samp = np.hstack((samp, newsamp))
        samp_sum = np.hstack((samp_sum, np.cumsum(newsamp) +  samp_sum[-1]))

    last = np.searchsorted(samp_sum, lim, side='right')
    return samp[:last + 1]

请注意,连接数组的速度相当慢,因此,最好使其blocksize足够大以合理地确保单个块的总和> =到您的限制而不会太大。

更新资料

我对您的原始功能做了一些调整,以使其语法与我的更加相似。

def orig_samp(refs, lim=10000):

    # Initialize empty final list.
    b = []

    a1 = np.random.random(10000)

    # Run until the condition is met.
    while (sum(b) < lim):

        # Draw random [0,1) value.
        u = np.random.random()
        # Find closest value in sub-list a[1].
        idx = np.argmin(np.abs(u - a1))
        # Store value located in sub-list a[0].
        b.append(refs[idx])

    return b

这是一些基准数据。

%timeit orig_samp(refs, lim=10000)
# 100 loops, best of 3: 11 ms per loop

%timeit fast_samp_2(refs, lim=10000, blocksize=1000)
# 10000 loops, best of 3: 62.9 µs per loop

这快了三个数量级。您可以通过减小块大小来提高性能-您基本上希望它比要取出的数组的长度舒适地更大。在这种情况下,您知道输出的平均长度约为200个元素,因为0到100之间的所有实数的平均值为50,并且10000/50 = 200。

更新2

获得加权样本而不是均匀样本很容易-您可以将p=参数传递np.random.choice

def weighted_fast_samp(refs, weights=None, lim=10000, blocksize=10000):

    samp = np.random.choice(refs, size=blocksize, replace=True, p=weights)
    samp_sum = np.cumsum(samp)

    # is the sum of our current block of samples >= lim?
    while samp_sum[-1] < lim:

        # if not, we'll sample another block and try again until it is
        newsamp = np.random.choice(refs, size=blocksize, replace=True, 
                                   p=weights)
        samp = np.hstack((samp, newsamp))
        samp_sum = np.hstack((samp_sum, np.cumsum(newsamp) +  samp_sum[-1]))

    last = np.searchsorted(samp_sum, lim, side='right')
    return samp[:last + 1]

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在另一个数组的特定列中查找数组中最接近的元素

来自分类Dev

在另一个数组中查找所有数组中最接近的float

来自分类Dev

用另一个数组项填充数组字段

来自分类Dev

向量化为另一个数组中的每个元素在数组中找到最接近的值

来自分类Dev

向量化为另一个数组中的每个元素在数组中找到最接近的值

来自分类Dev

PHP - 内置函数用另一个数组中的特定元素填充数组

来自分类Dev

如何用另一个数组的内容填充数组的列?

来自分类Dev

angularjs 从另一个数组填充数组

来自分类Dev

用Java循环一个数组与另一个数组

来自分类Dev

用另一个数据框的值填充数据框列

来自分类Dev

Numpy用另一个数组的值总结一个数组

来自分类Dev

过滤数组并返回包含最接近字符串的对象,该对象在一个对象内的数组内,另一个数组内

来自分类Dev

Javascript / AngularJs-如何用另一个数组中的对象填充数组?

来自分类常见问题

用另一个数组填充对象数组将返回内存地址

来自分类Dev

用升序将另一个数组的项填充到数组中(Javascript)

来自分类Dev

用一个数组填充另一个数组内的表* ngFor

来自分类Dev

从 .csv 中获取最接近另一个数据帧中的值的值

来自分类Dev

如何在大型排序数组中高效找到最接近另一个值X的值

来自分类Dev

用另一个数组的相同索引的值替换一个数组中的值?

来自分类Dev

删除另一个数组的数组值

来自分类Dev

在PHP中使用for循环将数组值存储在另一个数组中

来自分类Dev

循环遍历数组并将值存储在另一个数组中

来自分类Dev

用另一个数组中的值替换numpy数组的切片

来自分类Dev

用php中的另一个数组替换数组的值

来自分类Dev

将值匹配到R中另一个列表中最接近的较大值

来自分类Dev

ReactJS钩子用另一个数组更新一个数组

来自分类Dev

AngularJs用另一个数组过滤一个数组

来自分类Dev

查找数组中而不是另一个数组中最小元素的索引(Matlab)

来自分类Dev

从另一个数组的值派生一个数组

Related 相关文章

  1. 1

    在另一个数组的特定列中查找数组中最接近的元素

  2. 2

    在另一个数组中查找所有数组中最接近的float

  3. 3

    用另一个数组项填充数组字段

  4. 4

    向量化为另一个数组中的每个元素在数组中找到最接近的值

  5. 5

    向量化为另一个数组中的每个元素在数组中找到最接近的值

  6. 6

    PHP - 内置函数用另一个数组中的特定元素填充数组

  7. 7

    如何用另一个数组的内容填充数组的列?

  8. 8

    angularjs 从另一个数组填充数组

  9. 9

    用Java循环一个数组与另一个数组

  10. 10

    用另一个数据框的值填充数据框列

  11. 11

    Numpy用另一个数组的值总结一个数组

  12. 12

    过滤数组并返回包含最接近字符串的对象,该对象在一个对象内的数组内,另一个数组内

  13. 13

    Javascript / AngularJs-如何用另一个数组中的对象填充数组?

  14. 14

    用另一个数组填充对象数组将返回内存地址

  15. 15

    用升序将另一个数组的项填充到数组中(Javascript)

  16. 16

    用一个数组填充另一个数组内的表* ngFor

  17. 17

    从 .csv 中获取最接近另一个数据帧中的值的值

  18. 18

    如何在大型排序数组中高效找到最接近另一个值X的值

  19. 19

    用另一个数组的相同索引的值替换一个数组中的值?

  20. 20

    删除另一个数组的数组值

  21. 21

    在PHP中使用for循环将数组值存储在另一个数组中

  22. 22

    循环遍历数组并将值存储在另一个数组中

  23. 23

    用另一个数组中的值替换numpy数组的切片

  24. 24

    用php中的另一个数组替换数组的值

  25. 25

    将值匹配到R中另一个列表中最接近的较大值

  26. 26

    ReactJS钩子用另一个数组更新一个数组

  27. 27

    AngularJs用另一个数组过滤一个数组

  28. 28

    查找数组中而不是另一个数组中最小元素的索引(Matlab)

  29. 29

    从另一个数组的值派生一个数组

热门标签

归档