如何从自定义梯形概率密度函数生成样本以拟合梯形直方图?
从梯形PDF生成样本的方法
要从自定义的梯形PDF生成符合分布的样本,最直接的方法是逆变换采样法——先推导PDF对应的累积分布函数(CDF),再通过CDF的逆函数,将均匀分布的随机数转换为目标分布的样本。
步骤1:推导梯形PDF的CDF与逆CDF
已知你的梯形PDF参数为a(左起点)、b(左平顶起点)、c(右平顶终点)、d(右终点),先计算关键常数:
- 归一化常数
const = 2 / (d + c - a - b) - 总区间长度相关的
S = d + c - a - b - CDF在
b点的值u1 = (b - a) / S - CDF在
c点的值u2 = 1 - (d - c) / S
针对均匀分布随机数u ∈ [0,1),逆CDF的分情况计算逻辑:
- 当
0 ≤ u < u1:x = a + sqrt(u * (b - a) * S) - 当
u1 ≤ u < u2:x = b + (u - u1) / const - 当
u2 ≤ u < 1:x = d - sqrt( (1 - u) * (d - c) * S )
步骤2:实现逆CDF并生成样本
用numpy实现向量化的逆CDF函数,批量生成样本:
import numpy as np import matplotlib.pyplot as plt # 你定义的梯形PDF def trapezoidal_pdf(x, a, b, c, d): const = (2 / (d + c - a - b)) if a <= x < b: return const * (x - a) / (b - a) elif b <= x < c: return const elif c <= x < d: return const * (d - x) / (d - c) else: return 0.0 # 向量化的梯形PDF(方便画图) vec_trapezoidal_pdf = np.vectorize(trapezoidal_pdf) # 实现逆CDF函数 def trapezoidal_icdf(u, a, b, c, d): S = d + c - a - b u1 = (b - a) / S u2 = 1 - (d - c) / S const = 2 / S # 分情况计算,用numpy的where处理向量化 x = np.where( u < u1, a + np.sqrt(u * (b - a) * S), np.where( u < u2, b + (u - u1) / const, d - np.sqrt( (1 - u) * (d - c) * S ) ) ) return x # 生成样本 a, b, c, d = 1, 2, 4, 5 # 示例参数 num_samples = 100000 u = np.random.uniform(0, 1, num_samples) samples = trapezoidal_icdf(u, a, b, c, d) # 画图验证:直方图 + PDF曲线 plt.figure(figsize=(10,6)) # 画直方图,密度归一化 plt.hist(samples, bins=100, density=True, alpha=0.6, label='样本直方图') # 画PDF曲线 x_range = np.linspace(a-0.5, d+0.5, 1000) pdf_values = vec_trapezoidal_pdf(x_range, a, b, c, d) plt.plot(x_range, pdf_values, 'r', linewidth=2, label='梯形PDF') plt.xlabel('x') plt.ylabel('概率密度') plt.legend() plt.title('梯形分布样本直方图与PDF对比') plt.show()
说明
- 逆变换采样的核心是利用“任何分布的CDF都是[0,1]上的均匀分布”这一性质,通过反推得到目标样本。
- 用numpy的向量化操作处理批量样本,比循环高效得多,适合生成大量样本。
- 运行代码后,直方图会和你定义的梯形PDF完全匹配,验证样本的正确性。
内容的提问来源于stack exchange,提问作者Fazlur Rahman
相关产品推荐
相关产品推荐

