【问题标题】:python seed() not keeping same sequencepython种子()不保持相同的序列
【发布时间】:2014-05-28 18:36:46
【问题描述】:

我正在使用 random.seed() 来尝试保持 random.sample() 与我从列表中采样更多值相同,并且在某些时候数字会改变.....我认为那个seed() 函数的目的是保持数字不变。

这是我进行的一项测试,以证明它不会保持相同的数字。

import random

a=range(0,100)
random.seed(1)
a = random.sample(a,10)
print a

然后将样本更改得更高,序列会改变(至少对我来说他们总是这样做):

a = random.sample(a,40)
print a

我是一个新手,所以也许这是一个简单的解决方法,但我将不胜感激。 谢谢!

【问题讨论】:

  • 您能否提供一个示例输出(来自 print a),说明您得到了什么以及您期望什么?你的问题有点含糊(数字变了?),但听起来这个功能就像我期望的那样工作。
  • 值得注意的是,随机样本的子序列本身也是随机样本。因此,您可能应该先抓取 40 元素的样本,然后用切片制作 10 元素的样本。
  • @PaulSeeb 是的,抱歉有点含糊。我应该多解释一下我的最终目标,即以随机顺序从 0 个样本到完整的 100 个样本,不重复。随着我的样本数量增加,序列会在某些时候发生变化。当我用 10 做样本时,我的序列从 [13,84,76,25...] 开始,而 40 的序列给我 [13,83,74,24...] 似乎有些数字保持不变,在某些时候发生的其他变化对我来说似乎很奇怪。

标签: python random sequence seed


【解决方案1】:

你只需要重新播种:

a = list(range(100))
random.seed(1)  # seed first time
random.sample(a, 10)
>> [17, 72, 97, 8, 32, 15, 63, 57, 60, 83]
random.seed(1)  # seed second time with same value
random.sample(a, 40)
>> [17, 72, 97, 8, 32, 15, 63, 57, 60, 83, 48, 26, 12, 62, 3, 49, 55, 77, 0, 92, 34, 29, 75, 13, 40, 85, 2, 74, 69, 1, 89, 27, 54, 98, 28, 56, 93, 35, 14, 22]

但是在您的情况下,您使用的是生成器,而不是列表,因此在第一次采样后 a 会缩小(从 100 到 90),并且您将丢失采样的元素,所以它赢了不行。因此,只需在每次采样之前使用列表和种子即可。

【讨论】:

    【解决方案2】:

    您假设random.sample 的实现如下:

    def samples(lst, k):
        n = len(lst)
        indices = []
        while len(indices) < k:
            index = random.randrange(n)
            if index not in indices:
                indices.append(index)
        return [lst[i] for i in indices]
    

    这给出了:

    >>> random.seed(1)
    >>> samples(list(range(20)), 5)
    [4, 18, 2, 8, 3]
    >>> random.seed(1)
    >>> samples(list(range(20)), 10)
    [4, 18, 2, 8, 3, 15, 14, 12, 6, 0]
    

    但是,random.sample 的实际实现方式并非如此; seed 确实如你所想,但 sample 不行!

    【讨论】:

      【解决方案3】:

      如果您要从生成器中抽取独立样本,会发生什么正是您所期望的:

      In [1]: import random
      
      In [2]: random.seed(1)
      
      In [3]: [random.randint(0, 99) for _ in range(10)]
      Out[3]: [13, 84, 76, 25, 49, 44, 65, 78, 9, 2]
      
      In [4]: random.seed(1)
      
      In [5]: [random.randint(0, 99) for _ in range(40)]
      Out[5]: [13, 84, 76, 25, 49, 44, 65, 78, 9, 2, 83, 43 ...]
      

      如您所见,前十个数字确实相同。

      事实上,random.sample() 正在绘制样本没有替换,这阻碍了这一点。要了解这些算法的工作原理,请参阅Reservoir Sampling。从本质上讲,较晚个样本可以将较早个样本从结果集中推出。

      另一种方法可能是打乱索引列表,然后采用 10 或 40 个第一个元素:

      In [1]: import random
      
      In [2]: a = range(0,100)
      
      In [3]: random.shuffle(a)
      
      In [4]: a[:10]
      Out[4]: [48, 27, 28, 4, 67, 76, 98, 68, 35, 80]
      
      In [5]: a[:40]
      Out[5]: [48, 27, 28, 4, 67, 76, 98, 68, 35, 80, ...]
      

      【讨论】:

      • 谢谢,我使用了您的第二个选项,效果很好,尽管它很糟糕,random.sample 不会一直计数而无需切换。你的第一个选项也很好,只是它重复了。再次感谢您的帮助!
      • random.sample 不使用水库采样。它会进行部分随机抽样或拒绝抽样,具体取决于样本大小与总体大小的比较。
      【解决方案4】:

      似乎random.sample 只有当种子 样本大小保持不变时才具有确定性。换句话说,即使您重置种子,生成具有不同长度的样本也不是“相同”的随机操作,并且与生成具有相同种子的较小样本相比,可能会给出不同的初始子序列。换句话说,内部会生成相同的随机数,但sample 使用它们推导随机序列的方式会有所不同,具体取决于您要求的样本有多大。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-22
        • 2012-11-02
        • 1970-01-01
        • 2019-02-14
        • 1970-01-01
        • 1970-01-01
        • 2020-04-21
        • 2020-02-02
        相关资源
        最近更新 更多