2012-03-31 54 views
1

我正在寫一個小函數來使用Box-Muller方法從正態分佈生成值,但我得到的是負值。使用Box-Muller方法從正態分佈生成值

這裏是我的源代碼

import random 

def generate_normal(mu, sigma): 
    u = random.random() 
    v = random.random() 

    z1 = sqrt(-2 * log(u)) * sin(2 * pi * v) 
    z2 = sqrt(-2 * log(u)) * cos(2 * pi * v) 

    x1 = mu + z1 * sigma 
    x2 = mu + z2 * sigma 

    return x2 

啥子我缺少什麼?我在x1x2中都收到負值。例如:

mu: 400 
sigma: 150 
u: 7.27333176449e-05 
v: 0.642384573173 
z1: -3.40497345242 
x1: -110.746017863 

和:

x2: -9.79324023117 

回答

6

單元normal distribution集中在零,並用小尾雙面出正負無窮大。 99.7% of your values將在三個標準偏差內,另外0.3%不會。

enter image description here

在這個例子中,具有400的平均和150的標準偏差,您的值的99.7%將落入在平均值的三個標準偏差 - 區間[-50,850],其包括負數字。所以期待負數。

至於其他0.3%的值,請記住這是您的數字的3/1000 - 根本不常見。

如果您想要有限支持的「鐘形曲線」分佈,請嘗試使用beta distribution

最後,除非這是一項學術活動,否則不需要將自己的等價物滾動到numpy.random.normal()

+0

太好了。我不知道我是如何錯過它的。我只是把注意力集中在這個問題上,而我完全忘記了那個**非常着名的N(0,1)':)'圖形。非常感謝! – 2012-03-31 00:38:13

+0

我們都有我們的小失誤。 ;)這就是說,你沒有使用'numpy.random.normal()'的原因? – 2012-03-31 00:42:29

+0

OP不一定使用NumPy,但標準庫提供這個爲'random.gauss'(更快但不是線程安全)或'random.normalvariate'。這就是說,IIRC給定的方法很容易出現數值不穩定性(最好在單位平方中選擇隨機座標,如果它們在單位平方之外,則拒絕它們,而不是選擇加權隨機半徑和隨機角度),扔掉一半的有效結果('x1'與'x2'一樣隨機,並且獨立;最好記住這個值並且每隔一段時間返回一次,或者在循環中使用一個生成器和'yield'兩個值)。 – 2012-03-31 01:10:53

0

當隨機生成的值非常接近零時,Box-Muller變換存在穩定性問題。我建議用gaussinan分佈替換random.random(),並用你的均值和標準差來影響。