为何相同种子下random.sample(k=100)结果不在k=800样本中?
回答
这是Python的random.sample内部算法切换导致的问题,核心是不同的种群规模和采样数量组合会触发不同的采样逻辑,相同种子下消耗的随机数序列不一样,最终导致样本不匹配。
算法切换逻辑
random.sample会根据k(采样数)和n(种群大小)的关系自动选择高效算法:
- 当
k远小于n:使用增量洗牌算法,类似Fisher-Yates洗牌的前k步,直接生成前k个随机排列的元素。 - 当
k接近n(k > n - k):使用反向采样,随机选择n-k个元素排除,剩下的作为样本。 - 当
k介于两者之间:使用随机索引去重算法,不断生成随机索引直到凑够k个不重复的,过程中可能因重复索引消耗更多随机数。
对应你的案例
n=1000:k=800触发反向采样,k=100触发增量洗牌。反向采样生成的前100个元素刚好和增量洗牌结果一致,所以样本完全匹配。n=2000:k=100触发增量洗牌,k=800触发索引去重算法。两种算法使用随机数的逻辑不同,即使种子相同,生成的样本顺序也不一样,所以对应位置匹配度低。n=5000:k=100和k=800都触发增量洗牌,相同种子下前100个元素完全一致,结果匹配。
解决方案
最可靠的方式是先采样大样本,再切片取小样本,代码示例:
import random for n in 1000, 2000, 5000: print(end=f'{n=}: ') for i in range(10): random.seed(i) y = random.sample(range(n), 800) x = y[:100] print(sum(i==j for i,j in zip(x,y[:100])), end=' ') print()
这样能保证x完全是y的子集,且顺序一致,完全符合预期。
至于不同目录的结果差异,本质是不同目录的文件数量(即n)不同,触发了不同的采样算法,和排序无关。
内容的提问来源于stack exchange,提问作者John Karkas
相关产品推荐
相关产品推荐

