如何在指定范围内稳定生成对数正态与幂律分布样本?
稳定生成指定范围的对数正态与幂律分布样本
一、对数正态分布样本生成
问题分析
你的核心思路是对的,但代码存在两处关键问题:
- 未调用
np.exp会导致语法错误; - 未固定随机种子,导致样本生成结果不稳定;
- 样本很少接近500的本质原因:如果
mu和sigma是从1-500的数据集拟合而来,原对数正态分布的上尾本来就极窄,500对应的对数正态概率密度极低,因此采样中出现接近500的样本概率自然不高。
修正后的稳定生成代码
import numpy as np from scipy.stats import truncnorm def generate_lognormal(xmin, xmax, mu, sigma, n, random_state=42): # 计算标准化后的截断正态分布上下界 a = (np.log(xmin) - mu) / sigma b = (np.log(xmax) - mu) / sigma # 固定随机种子保证生成结果稳定 norm_samples = truncnorm.rvs(a, b, loc=0, scale=1, size=n, random_state=random_state) # 转换为对数正态分布样本 lognorm_samples = np.exp(mu + sigma * norm_samples) return lognorm_samples
提升上尾样本占比的可选方案
如果需要更多接近500的样本,且不要求严格匹配原数据集的分布,可以调整参数:增大mu会让整体分布右移,增大sigma会让分布更分散,从而提升上尾样本的占比。若需严格贴合原数据集拟合结果,只能通过增加样本量来提升出现接近500样本的概率。
二、幂律分布样本生成
powerlaw模块默认生成无界幂律样本,因此会超出500上限。可以通过截断幂律的逆变换采样生成指定范围的样本,同时保证稳定性。
实现代码
import numpy as np def generate_truncated_powerlaw(xmin, xmax, alpha, n, random_state=42): np.random.seed(random_state) # 计算截断幂律CDF的归一化分母 cdf_denominator = 1 - (xmin / xmax) ** (alpha - 1) # 生成0-1均匀分布样本 u = np.random.uniform(0, 1, size=n) # 逆变换得到截断幂律样本,严格限制在[xmin, xmax]范围内 samples = xmin / (1 - u * cdf_denominator) ** (1 / (alpha - 1)) return samples
说明
alpha为幂律分布的拟合指数(对应powerlaw拟合结果中的powerlaw.alpha);- 固定
random_state参数可确保每次生成的样本完全一致; - 该方法严格约束样本落在指定区间内,不会出现超出上限的情况。
内容的提问来源于stack exchange,提问作者Julian_P
相关产品推荐
相关产品推荐

