1

Python で対数正規分布の乱数を生成しようとしています (後の MC シミュレーション用)。パラメーターが少し大きいと、結果がかなり矛盾することがわかりました。

以下では、Normals から (そして Exp を使用して) 一連の LogNormals を、LogNormals から直接生成しています。結果として得られる平均は許容できますが、分散はかなり不正確です。これは、mu = 4,5、... についても当てはまります。

以下のコードを数回再実行すると、まったく異なる結果が返されます。

コード:

import numpy as np
mu = 10;
tmp1 = np.random.normal(loc=-mu, scale=np.sqrt(mu*2),size=1e7)
tmp1 = np.exp(tmp1)
print tmp1.mean(), tmp1.var()
tmp2 = np.random.lognormal(mean=-mu, sigma=np.sqrt(mu*2), size=1e7)
print tmp2.mean(), tmp2.var()
print 'True Mean:', np.exp(0), 'True Var:',(np.exp(mu*2)-1)

これを修正する方法についてアドバイスはありますか?Wakari.ioでもこれを試したので、結果はそこでも一貫しています

更新: ウィキペディアから「真の」平均と分散の式を取得しました: https://en.wikipedia.org/wiki/Log-normal_distribution

結果のスナップショット: 1)

0.798301881219 57161.0894726
1.32976988569 2651578.69947
True Mean: 1.0 True Var: 485165194.41

2)

1.20346203176 315782.004309
0.967106664211 408888.403175
True Mean: 1.0 True Var: 485165194.41

3) n=1e8 乱数の最後のもの

1.17719369919 2821978.59163
0.913827160458 338931.343819
True Mean: 1.0 True Var: 485165194.41
4

2 に答える 2

6

サンプル サイズが大きい場合でも、これらのパラメーターを使用すると、推定分散は実行ごとに大きく変化します。これが、裾が太い対数正規分布の性質です。np.exp(np.random.normal(...)).var()を数回実行してみてください。と同様の値の変動が見られnp.random.lognormal(...).var()ます。

いずれにせよ、np.random.lognormal()として実装されているだけですnp.exp(np.random.normal())(まあ、C の同等物)。

于 2013-10-22T18:23:34.780 に答える
1

サンプルを作成したばかりなので、ウィキペディアの表記 (最初のセクション、mu と sigma) とあなたが示した例を使用します。

from numpy import log, exp, sqrt
import numpy as np
mu = -10
scale = sqrt(2*10)   # scale is sigma, not variance
tmp1 = np.random.normal(loc=mu, scale=scale, size=1e8)
# Just checking
print tmp1.mean(), tmp1.std()
# 10.0011028634 4.47048010775, perfectly accurate
tmp1_exp = exp(tmp1)    # Not sensible to use the same name for two samples
# WIKIPEDIA NOTATION!
m = tmp1_exp.mean()     # until proven wrong, this is a meassure of the mean
v = tmp1_exp.var()  # again, until proven wrong, this is sigma**2
#Now, according to wikipedia
print "This: ", log(m**2/sqrt(v+m**2)), "should be similar to", mu
# I get This:  13.9983309499 should be similar to 10
print "And this:", sqrt(log(1+v/m**2)), "should be similar to", scale
# I get And this: 3.39421327037 should be similar to 4.472135955

したがって、値が完全でなくても、完全に間違っているとは言えません。

于 2013-10-22T18:25:21.107 に答える