numpy.random.lognormal生成指定均值标准差对数正态分布参数设置
numpy.random.lognormal 目标算术均值/标准差的参数换算指南
核心误区说明
numpy.random.lognormal 接收的两个位置参数 mean、sigma,不是原始数据尺度的均值和标准差,而是「原始数据取自然对数后服从的正态分布」的均值和标准差。此前报错/结果不符合预期的两个典型原因:
- 直接传入原始尺度的均值13600、标准差7900:相当于对数尺度的均值高达1.36e4,取指数还原后数值远超64位浮点数上限,自然会大量出现
inf - 直接对原始均值、标准差取对数传入:没有做矩匹配换算,还原后的原始数据均值、标准差和目标值完全不匹配,结果必然偏离预期
正确换算公式
设原始尺度(即收入值)的目标算术均值为 $\mu_{arith}$,目标标准差为 $\sigma_{arith}$,对数尺度的两个参数记为 $\mu_{log}$、$\sigma_{log}$,换算逻辑如下:
- 先计算对数尺度的标准差 $\sigma_{log}$:
$$\sigma_{log} = \sqrt{\ln\left( \frac{\sigma_{arith}2}{\mu_{arith}2} + 1 \right)}$$ - 再计算对数尺度的均值 $\mu_{log}$:
$$\mu_{log} = \ln(\mu_{arith}) - \frac{\sigma_{log}^2}{2}$$
代入给出的数值($\mu_{arith}=13600$,$\sigma_{arith}=7900$)计算可得:
- $\sigma_{log} \approx 0.539$
- $\mu_{log} \approx 9.37$
可复现代码示例
import numpy as np # 输入目标:原始收入尺度的算术均值、标准差 target_mean = 13600 target_std = 7900 # 参数换算 sigma_log = np.sqrt(np.log( (target_std ** 2) / (target_mean ** 2) + 1 )) mu_log = np.log(target_mean) - (sigma_log ** 2) / 2 # 生成数据集,固定随机种子保证复现 np.random.seed(42) income_data = np.random.lognormal(mean=mu_log, sigma=sigma_log, size=100000) # 校验结果 print(f"生成数据算术均值:{income_data.mean():.0f}") # 输出约13600 print(f"生成数据标准差:{income_data.std():.0f}") # 输出约7900
补充说明
对数正态分布本身是强右偏分布,生成的收入数据中位数会低于算术均值(本例中位数约11700),高收入尾部会存在少量极高值,完全符合真实家庭收入的分布特征,不属于参数错误。
内容的提问来源于stack exchange,提问作者Or Rubinstein
相关产品推荐
相关产品推荐

