编程语言
首页 > 编程语言> > 如何使用逆CDF在Python中随机抽样对数正态数据并指定目标百分位数?

如何使用逆CDF在Python中随机抽样对数正态数据并指定目标百分位数?

作者:互联网

我正在尝试从Python的对数正态分布生成随机样本,该应用程序用于模拟网络流量.我想生成这样的样本:

>模态采样结果为320(〜10 ^ 2.5)
> 80%的样本位于100到1000(10 ^ 2到10 ^ 3)的范围内

我的策略是使用逆CDF(或我相信的Smirnov变换):

>将PDF用于以2.5为中心的正态分布,以计算10 ^ x的PDF,其中x〜N(2.5,sigma).
>计算上述分布的CDF.
>沿0到1的间隔生成随机的统一数据.
>使用逆CDF将随机统一数据转换为所需范围.

问题是,当我最后计算第10个百分位数和第90个百分位数时,我得到的数字完全错误.

这是我的代码:

%matplotlib inline

import matplotlib
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats
from scipy.stats import norm

# find value of mu and sigma so that 80% of data lies within range 2 to 3
mu=2.505
sigma = 1/2.505
norm.ppf(0.1, loc=mu,scale=sigma),norm.ppf(0.9, loc=mu,scale=sigma)
# output: (1.9934025, 3.01659743)

# Generate normal distribution PDF
x = np.arange(16,128000, 16) # linearly spaced here, with extra range so that CDF is correctly scaled
x_log = np.log10(x)
mu=2.505
sigma = 1/2.505
y = norm.pdf(x_log,loc=mu,scale=sigma)
fig, ax = plt.subplots()
ax.plot(x_log, y, 'r-', lw=5, alpha=0.6, label='norm pdf')

x2 = (10**x_log) # x2 should be linearly spaced, so that cumsum works (later)
fig, ax = plt.subplots()
ax.plot(x2, y, 'r-', lw=5, alpha=0.6, label='norm pdf')
ax.set_xlim(0,2000)

# Calculate CDF
y_CDF = np.cumsum(y) / np.cumsum(y).max()
fig, ax = plt.subplots()
ax.plot(x2, y_CDF, 'r-', lw=2, alpha=0.6, label='norm pdf')
ax.set_xlim(0,8000)

# Generate random uniform data
input = np.random.uniform(size=10000)

# Use CDF as lookup table
traffic = x2[np.abs(np.subtract.outer(y_CDF, input)).argmin(0)]

# Discard highs and lows
traffic = traffic[(traffic >= 32) & (traffic <= 8000)]

# Check percentiles
np.percentile(traffic,10),np.percentile(traffic,90)

产生输出:

(223.99999999999997, 2480.0000000000009)

…而不是我想看到的(100,1000).任何建议表示赞赏!

解决方法:

首先,我不确定将PDF用于以2.5为中心的正态分布.毕竟,对数正态约等于底e对数(又称自然对数),这意味着320 = 102.5 = e5.77.

第二,我将以不同的方式来解决问题.您需要m和s才能从Log-Normal进行采样.

如果您看一下上面的Wiki文章,您会发现它是两参数分布.而您恰好有两个条件:

Mode = exp(m - s*s) = 320
80% samples in [100,1000] => CDF(1000,m,s) - CDF(100,m,s) = 0.8

CDF通过错误函数表示(这是任何库中常见的函数)

因此,两个非线性方程针对两个参数.解决它们,找到m和s并将其放入任何标准的对数正态采样

标签:probability-density,statistics,random,cdf,python
来源: https://codeday.me/bug/20191026/1934205.html