如何使用numpy.random.choice生成前缀相同、长度递增的随机序列
问题原因
你当前实现未达预期的核心原因是:numpy 旧版本 np.random.choice 在 replace=False 且传入概率参数时,内部采用批量加权无替换采样算法,而非逐次抽取样本,即使固定随机种子,不同采样长度的结果也无法保证前缀一致性。
方案1:预生成全量序列(适合n不大的场景,实现最简)
核心逻辑:固定种子后一次性生成全部n个无重复的加权随机序列,后续任意阶段需要多长就取前多少位,天然满足前缀一致、无重复的要求,仅需存储一个长度为n的数组即可。
import numpy as np n = 100 prob = np.random.choice(100, n) prob = prob / np.sum(prob) # 全局固定种子,预生成全量序列 np.random.seed(123) full_sequence = np.random.choice(n, size=n, replace=False, p=prob) # 不同运行阶段按需取前k位即可 for i in np.arange(10, 100, 10): selected = full_sequence[:i] print(f"{i}: {selected}")
方案2:迭代式逐次采样(适合n较大,无需预存全量序列)
如果你的n规模很大,预存全量序列占用内存过高,可实现逐次采样的生成器,每次调用返回下一个符合权重的无重复样本,按需取用即可,不需要提前生成全量序列,也无需强制存储已生成的历史序列。
import numpy as np def weighted_sample_generator(n, prob, seed=None): rng = np.random.default_rng(seed) remaining_indices = np.arange(n) remaining_prob = prob.copy() while len(remaining_indices) > 0: # 按当前剩余样本的概率权重抽取1个样本 selected_pos = rng.choice(len(remaining_indices), p=remaining_prob/remaining_prob.sum()) selected_val = remaining_indices[selected_pos] yield selected_val # 移除已抽取的样本和对应概率 remaining_indices = np.delete(remaining_indices, selected_pos) remaining_prob = np.delete(remaining_prob, selected_pos) # 全局初始化生成器,固定种子保证可复现 prob = np.random.choice(100, 100) prob = prob / np.sum(prob) gen = weighted_sample_generator(n=100, prob=prob, seed=123) # 不同运行阶段按需取数即可 # 阶段1:取10个样本 selected_10 = [next(gen) for _ in range(10)] print(f"10: {selected_10}") # 阶段2:取20个样本,前缀和前10个完全一致 selected_20 = selected_10 + [next(gen) for _ in range(10)] print(f"20: {selected_20}") # 阶段3:取30个样本,前缀和前20个完全一致 selected_30 = selected_20 + [next(gen) for _ in range(10)] print(f"30: {selected_30}")
内容的提问来源于stack exchange,提问作者naxatras
相关产品推荐
相关产品推荐

