【问题标题】:Log normal distribution对数正态分布
【发布时间】:2019-01-11 20:09:31
【问题描述】:

我有一个关于对数正态分布的问题。我想创建和集合具有从 10 到 10**5 的“质量”通常分布的对象。我认为这将是一个对数正态分布,所以我开始尝试在 python 中这样做:

mu, sigma = 3., 1. # mean and standard deviation
s = np.random.lognormal(mu, sigma, 1000)
count, bins, ignored = plt.hist(s, 1000, density=True, align='mid')
x = np.linspace(min(bins), max(bins), 1000)
pdf = (np.exp(-(np.log(x) - mu)**2 / (2 * sigma**2)) / (x * sigma * np.sqrt(2 * np.pi)))
plt.plot(x, pdf, linewidth=2, color='r')
plt.xscale('log')
plt.show()

如 numpy 的示例所示,但更改 mu 和 sigma 并查看图表,我无法确定是否将 m 和 v(按照下面链接的 wikipedia 文章)设置为 10**5 和 1000说给了我想要的东西

我查看了https://en.wikipedia.org/wiki/Log-normal_distribution 以弄清楚如何计算 mu 和 sigma,但也许我做错了其他事情。这是解决这个问题的正确方法吗?

我阅读了以前关于对数正态分布的问题/答案,但我认为他们问的不是同一件事。如果此类问题已得到解答,请提前致歉。

mu, sigma = 3., 1. 示例中给出的是什么,这很好用,但是当我将 mu 和 sigma 更改为以下值时:

m=10**3.5 #where I want the distribution to be centered
v=10000   #the "spread" that I want 
f=1.+(v/m2)
mu=np.log(m/np.sqrt(f))
sigma=np.sqrt(np.log(f))

我没有得到我期望的结果。这是一个以 10**3.5 为中心的分布,标准为 10000。

尝试建议的方法:

mu=np.log(3000)
sigma=np.log(10)
s = np.random.lognormal(mu, sigma, 1000)
count, bins, ignored = plt.hist(s, 500, density=True, align='mid')
x = np.linspace(min(bins), max(bins), 1000)
pdf = (np.exp(-(np.log(x) - mu)**2 / (2 * sigma**2)) / (x * sigma * np.sqrt(2 * np.pi)))
plt.semilogx(x, pdf, linewidth=2, color='r')

这似乎也不起作用,除非我误解了直方图 histogram

【问题讨论】:

  • 您的问题缺乏明确的问题陈述?你到底想要什么? wiki 给出了 m,v 和 mu, sigma 之间的关系。您在问题中提到了 m, v 的值,但您的代码中没有任何地方使用它们。请具体明确。为什么选择 mu=3 和 sigma=1?
  • 谢谢,我更新了问题。 3 和 1 只是 np.random.lognormal() 文档中示例中的值

标签: python statistics


【解决方案1】:

我认为您在解释分布参数时遇到了困难。

np.random.lognormal 的文档在这里: https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.lognormal.html

特别是,平均值不是mu10**mu,而是exp(mu),因此您的分布的平均值为e**3 ≈ 20

您似乎希望平均值约为 1000,因此将 mu 和 sigma 设置为

mu, sigma  = np.log(1000), np.log(10)`

将生成您期望的分布。

【讨论】:

  • 谢谢,是的,我认为不理解变量绝对是我遇到的问题。我尝试按照您的建议进行操作,但直方图的情节似乎仍然不正确
【解决方案2】:

如果你知道你想要 1000 个对数正态分布的值(即 log(x) 给你正态分布),并且你希望你的数据范围从 10 到 10^5,那么你必须这样做一些计算来获得 mu 和 sigma。但是您必须插入np.random.lognormal 的值是底层相关正态分布的平均值和标准差,不是对数正态分布。您可以从您看到的 Wikipedia 页面上给出的均值和方差公式得出这些。

# Parameters
xmax = 10**5
xmin = 10
n = 1000

# Get original mean and variance
# mu: We want normal distribution, so just take the average of the extremes.
# sigma: use the z = (x - mu)/sigma formula and approximation that 
#        the extremes are a deviation of z=3 away.
mu = (xmax + xmin)/2.0
sigma = (xmax - mu)/3.0
m = mu
v = sigma**2

# Get the mean and standard deviation of the underlying normal distribution
norm_mu = np.log(m**2 / np.sqrt(v + m**2))
norm_sigma = np.sqrt((v / m**2)+1)

# Generate random data and an overlying smooth curve
# (This is the same as your code, except I replaced the parameters
# in the 'pdf =' formula.)
s = np.random.lognormal(norm_mu, norm_sigma, n)
count, bins, ignored = plt.hist(s, n, density=True, align='mid')
x = np.linspace(min(bins), max(bins), n)
pdf = (np.exp(-(np.log(x) - norm_mu)**2 / (2 * norm_sigma**2)) / (x * norm_sigma * np.sqrt(2 * np.pi)))
plt.plot(x, pdf, linewidth=2, color='r')
plt.xscale('log')
plt.show()

这就是我得到的。请注意,x 轴上的缩放比例呈指数上升,而不是线性上升。这是你要找的东西吗?

【讨论】:

  • 谢谢你,这就是我想要的,除了移动,使其以 103 或 103.5 为中心。但是,在您的示例中更改 mu 似乎会破坏它,我不明白。另外我认为在计算 norm_mu 时你有一个 m**2 而不是 m。再次感谢
猜你喜欢
  • 2021-10-06
  • 2017-11-15
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
  • 2023-03-13
  • 2014-12-11
  • 1970-01-01
相关资源
最近更新 更多