序列泊松噪声实现的可复现性:未修改像素噪声一致方案咨询
解决方案
你遇到的问题本质是numpy内置泊松采样针对不同λ值采用了差异化的高效采样算法,随机数消耗量不固定,导致同种子的两个RNG处理完不同λ的像素后状态错位,后续相同λ的像素采样结果不一致。有两种成熟的解决思路,按需选择即可:
思路1:仅重算修改像素(最高效,推荐)
你的场景是仅修改了极少部分像素,完全可以复用第一遍的采样结果,只对修改过的像素单独做第二次采样,未修改的像素直接沿用第一次的结果,天然保证噪声完全一致。
代码示例:
import numpy from numpy.random import default_rng import copy import pylab # 生成原始数组和修改后数组 a0 = numpy.random.randint(low=0, high=1e6, size=10000).astype('float') a = numpy.random.randint(low=0, high=30, size=10000).astype('float') b = copy.copy(a) modify_mask = a0>9.9e5 b[modify_mask] += 1e6 # 第一次对全数组a采样 gen = default_rng(seed=1234) resa = gen.poisson(a) # 第二次仅对修改的像素采样b的值,未修改部分直接复用resa resb = resa.copy() resb[modify_mask] = gen.poisson(b[modify_mask]) # 此时未修改位置resa和resb完全相等,差值仅出现在修改位置 pylab.imshow(resa.reshape((100,100))-resb.reshape((100,100)), vmin=-10,vmax=10)
思路2:固定随机数消耗的全量泊松采样
如果你的场景必须分别对全量a和全量b做独立采样,不能复用第一次结果,可以采用泊松逆变换采样,该算法每个像素仅消耗1个均匀随机数,不管λ值多大,随机数消耗量完全固定,同种子的RNG采样相同位置的结果完全一致。
逆变换采样逻辑:对每个像素,先生成1个[0,1)区间的均匀随机数u,找到最小的非负整数k使得泊松累积分布函数P(X≤k|λ)≥u,k就是该位置的泊松采样结果。
代码示例:
import numpy from numpy.random import default_rng from scipy.stats import poisson def fixed_cost_poisson(rng, lam_array): # 每个像素生成1个均匀随机数,固定消耗1次随机数 u = rng.uniform(0, 1, size=lam_array.shape) # 用ppf(百分位点函数,即逆CDF)直接得到采样结果 return poisson.ppf(u, lam_array).astype(numpy.int64) # 测试 gen1 = default_rng(seed=1234) gen2 = default_rng(seed=1234) resa = fixed_cost_poisson(gen1, a) resb = fixed_cost_poisson(gen2, b) # 未修改位置resa和resb完全相等
如果λ的最大值很大(比如超过1e4),可以提前预计算CDF查找表优化速度,避免每次调用scipy的ppf带来的性能开销。
内容的提问来源于stack exchange,提问作者Akira Doe
相关产品推荐
相关产品推荐

