基于Numpy从非对称误差分布中抽取样本
用Numpy生成非高斯不对称误差分布的样本
针对你提到的Log10[param] = 9.33 +0.21 -0.01这种对数空间的不对称误差,推荐两种纯Numpy实现的抽样方法,直接匹配你的误差结构:
方法一:缩放正态分布(简单直观,适配1σ误差场景)
如果你的上下误差是类似1σ置信区间的定义,这种方法最快:直接对标准正态分布的正负半轴分别缩放不同倍数,生成对数空间的不对称样本,再转换回原始参数。
代码示例:
import numpy as np # 对数空间的参数配置 mu_log = 9.33 err_down_log = 0.01 # 向下误差 err_up_log = 0.21 # 向上误差 n_samples = 10000 # 要生成的样本量 # 生成标准正态样本 z = np.random.normal(0, 1, size=n_samples) # 对正负半轴分别缩放,得到对数空间样本 log_samples = mu_log + np.where(z < 0, z * err_down_log, z * err_up_log) # 转换回原始参数空间(10的幂) param_samples = 10 ** log_samples
原理:标准正态分布的16%分位数对应-1σ,84%分位数对应+1σ。通过分别缩放正负半轴,让对数空间样本的16%分位数刚好是9.33-0.01,84%分位数刚好是9.33+0.21,完美匹配你给出的误差范围。
方法二:Beta分布映射(灵活适配任意不对称分布)
如果你的误差对应的是更复杂的置信区间(比如95%置信度),可以用Beta分布来生成任意形状的不对称样本,再映射到对数空间的误差区间。
代码示例:
import numpy as np mu_log = 9.33 err_down_log = 0.01 err_up_log = 0.21 n_samples = 10000 # 确定对数空间的上下边界 L_log = mu_log - err_down_log U_log = mu_log + err_up_log # 调整Beta分布的形状参数,让分布众数落在中心值mu_log # 这里根据误差比例计算:中心值在区间内的占比 = 0.01/(0.01+0.21) ≈ 0.0455 alpha = 2 beta = 22 # 由Beta分布众数公式推导:(alpha-1)/(alpha+beta-2) = 0.0455 # 生成Beta样本并映射到对数空间区间 beta_samples = np.random.beta(alpha, beta, size=n_samples) log_samples = L_log + (U_log - L_log) * beta_samples # 转换回原始参数空间 param_samples = 10 ** log_samples
原理:Beta分布在[0,1]区间内的形状由alpha和beta控制——alpha越小、beta越大,分布越偏向左侧(对应大部分样本集中在中心值附近,少数向上偏移)。你可以调整alpha和beta的数值,让样本的分位数完全匹配你的置信区间要求。
验证样本合理性
生成样本后,你可以通过以下代码快速验证对数空间的样本是否符合误差要求:
# 查看对数空间样本的16%、50%、84%分位数 print(np.percentile(log_samples, [16, 50, 84]))
对于方法一,输出应该接近[9.32, 9.33, 9.54],完美匹配给定的误差范围。
内容的提问来源于stack exchange,提问作者arnbobo
相关产品推荐
相关产品推荐

