【问题标题】:Generating numbers from normal distribution in Python在 Python 中从正态分布生成数字
【发布时间】:2015-10-22 05:43:45
【问题描述】:

我正在尝试通过使用 Box–Muller 变换对 Marsaglia 极坐标方法来测试从正态分布生成数字的速度。据说 Marsaglia 极坐标法比 Box-Muller 变换更快,因为它不需要计算 sin 和 cos。但是,当我在 Python 中编写代码时,情况并非如此。有人可以验证这一点或向我解释为什么会这样吗?

def marsaglia_polar():
    while True:
        x = (random.random() * 2) - 1
        y = (random.random() * 2) - 1
        s = x * x + y * y
        if s < 1:
            t = math.sqrt((-2) * math.log(s)/s)
            return x * t, y * t

def box_muller():
    u1 = random.random()
    u2 = random.random()

    t = math.sqrt((-2) * math.log(u1))
    v = 2 * math.pi * u2

    return t * math.cos(v), t * math.sin(v)

【问题讨论】:

  • 没有看到你的代码!?
  • 我们可以,如果您向我们展示您的代码
  • 所以我看到 box_muller 也赢了 10% 到 20%;可能拒绝采样足以使三角函数黯然失色。话虽这么说,如果你足够在意快速完成这种差异对你来说很重要,那么你一开始就不应该在纯 Python 中进行。
  • 好吧,公平地说,我在不到一秒的时间内用任何一种方法生成了一百万个随机数。但是,是的,box_muller 赢了 10-15%。似乎大约 25% 的 marsaglia_polar 运行生成了至少一个 s &gt;= 1,这似乎足以输掉比赛。
  • 您应该在获得结果时展示结果。我怀疑你会因为应该更快而失分——如果你这样做了,我对你的教授非常失望。衡量事物的全部意义在于找出实际上是什么

标签: python normal-distribution


【解决方案1】:

为了“好玩”,我在 go 里写了。 box_muller 函数在那里也更快。而且比python版本快10倍左右。

package main

import (
    "fmt"
    "math"
    "math/rand"
    "time"
)

func main() {
    rand.Seed(time.Now().UnixNano())
    now := time.Now()
    for i := 0; i < 1000000; i++ {
        marsaglia_polar()
    }
    fmt.Println("marsaglia_polar duration = ", time.Since(now))
    now = time.Now()
    for i := 0; i < 1000000; i++ {
        box_muller()
    }
    fmt.Println("box_muller duration      = ", time.Since(now))
}

func marsaglia_polar() (float64, float64) {
    for {
        x := random() * 2 - 1;
        y := random() * 2 - 1;
        s := x * x + y * y;
        if s < 1 {
            t := math.Sqrt((-2) * math.Log(s)/s);
            return x * t, y * t
        }
    }
}

func box_muller() (float64, float64) {
    u1 := random()
    u2 := random()
    t := math.Sqrt((-2) * math.Log(u1))
    v := 2 * math.Pi * u2
    return t * math.Cos(v), t * math.Sin(v)
}

func random() float64 {
    return rand.Float64()
}

输出:

marsaglia_polar duration =  104.308126ms
box_muller duration      =  88.365933ms

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-18
    • 2020-08-26
    • 1970-01-01
    • 2016-07-07
    • 1970-01-01
    • 2020-06-18
    • 1970-01-01
    • 2014-03-07
    相关资源
    最近更新 更多