Python 从numpy数组中有效地采样以相同数目终止的连续整数序列?

Python 从numpy数组中有效地采样以相同数目终止的连续整数序列?,python,numpy,random,sampling,markov-chains,Python,Numpy,Random,Sampling,Markov Chains,假设我有以下numpy数组: Space = np.arange(7) 问题:如何从空间生成一组N个样本,以便: 每个样本仅由递增或递减的连续数字组成 采样是通过替换完成的,因此样本不必单调递增或递减 每个样本以6或0结尾,并且 样本的长度没有限制(但是,一旦选择了6或0,每个样本就会终止) 本质上,我是通过numpy采样创建一个markov奖励过程(可能有一个更有效的数据包,但我不确定它会是什么)。例如,如果N=3,一个可能的采样集看起来像这样 Sample = [[1,0],[4, 3,

假设我有以下numpy数组:

Space = np.arange(7) 
问题:如何从空间生成一组N个样本,以便:

  • 每个样本仅由递增或递减的连续数字组成
  • 采样是通过替换完成的,因此样本不必单调递增或递减
  • 每个样本以6或0结尾,并且
  • 样本的长度没有限制(但是,一旦选择了6或0,每个样本就会终止)
  • 本质上,我是通过numpy采样创建一个markov奖励过程(可能有一个更有效的数据包,但我不确定它会是什么)。例如,如果N=3,一个可能的采样集看起来像这样

    Sample = [[1,0],[4, 3, 4, 5, 6],[4, 3, 2, 1, 2, 1, 0]]
    
    我可以用一些不太优雅的东西来做到这一点:

    N = len(Space)
    Set = []
    for i in range(3):
        X = np.random.randint(N)
        if (X == 0) | (X==6):
            Set.append(X)
        else:
            Sample = []
            while (X !=0) & (X != 6):
                Next = np.array([X-1, X+1])
                X = np.random.choice(Next)
                Sample.append(X)
            Set.append(Sample)
    return(Set)
    

    但我想知道,对于这种类型的采样,哪种方法更有效/更具蟒蛇风格,也许没有这么多循环?或者,是否有更好的python库来实现这类功能?谢谢。

    Numpy在这里似乎帮不了什么忙,我只想使用标准的
    随机
    模块。主要原因是,像此算法那样处理单个值时,
    random
    速度更快,而且似乎不需要引入额外的依赖项,除非需要

    from random import randint, choice
    
    def bounded_path(lo, hi):
        # r covers the interior space
        r = range(lo+1, hi)
        n = randint(lo, hi)
        result = [n]
        while n in r:
            n += choice((-1, 1))
            result.append(n)
        return result
    
    似乎为我做了正确的事情,例如,对上述10次评估,我得到:

    [0]
    [4, 3, 4, 3, 2, 1, 0]
    [5, 6]
    [2, 3, 4, 3, 4, 5, 4, 3, 4, 3, 2, 1, 0]
    [1, 0]
    [1, 0]
    [4, 3, 4, 3, 4, 3, 2, 3, 2, 1, 0]
    [3, 2, 3, 2, 1, 0]
    [6]
    [4, 5, 4, 3, 4, 3, 2, 1, 0]
    
    刚刚做了随机数生成的快速基准比较:

    def rng_np(X):
        for _ in range(10):
            X = np.random.choice(np.array([X-1,X+1]))
        return X
    
    def rng_py(X):
        for _ in range(10):
            X += choice((-1, +1))
        return X
    
    Numpy版本大约慢30倍。Numpy需要做很多额外的工作,每次迭代都要构建一个Python数组,转换成Numpy数组,在
    choice
    中切换以实现奇特的矢量化。Python知道香草版本中的
    (-1,+1)
    是常量,因此它只构建了一次(例如,可以查看内部的情况)


    你也许可以通过使用更大的数字块来达到某个目的,但我怀疑这会快得多。保持起点的一致性似乎很尴尬,但如果你真的很小心的话,你可能会做一些事情!Numpy在每次调用的矢量化值超过大约10个时开始收支平衡,当您有100个以上的值时,它会非常出色。

    我很困惑,因为您说过“每个样本只包含递增/递减的连续数字”,但在您的样本集中,样本并没有遵循该顺序。感谢您的反馈,样本增加/减少连续数,但如第2点所述。它们不必是单调的。这难道不意味着第二种说法与第一种说法相矛盾,因为你不能让样本只包含连续递增/递减的数字吗?我不这么认为。我可以用序列4,5,6。我也可以有2,1,0。序列1,2,3,4,3,2,1,0也不排除。所以每个样本都由整数组成。这些整数可以连续增加或减少,但样本(即整数字符串)不需要单调增加或减少。这样,唯一的要求是,您不需要两次背对背地包含同一个整数,这是真的吗?哇,我不会想到像这样接近它…谢谢你的明确回答和解释!我只是想知道,既然每个后续条目都依赖于前一个条目,那么这个条件元素是否排除了所有向量化的可能性?直觉上似乎是这样,但鉴于我在这方面不是很在行,我认为检查是谨慎的。@phntm添加了一些基准和解释,希望它们能有所帮助!