机器学习数学基础 - Box-Muller

619 阅读2分钟

什么是Box-Muller变换?

Box-Muller变换是一种数学方法,可以从0到1的均匀分布中生成标准正态分布(也就是平均值为0,标准差为1的正态分布)的数据。

Box-Muller变换的基本思想是首先生成两个独立且分布均匀的随机变量,然后通过一定的数学变换,将这两个随机变量转换成两个独立的标准正态分布的随机变量。

这样做的好处是,生成均匀分布的随机变量比较容易且直观,然后通过Box-Muller变换,我们可以得到我们需要的正态分布的随机变量。

具体的变换步骤:

假设U1和U2是两个独立的、在(0,1)上均匀分布的随机数,则可通过如下公式生成两个独立的、服从标准正态分布的随机数:

Z0 = sqrt(-2.0 * log(U1)) * cos(2*pi*U2)

Z1 = sqrt(-2.0 * log(U1)) * sin(2*pi*U2)

在这里,log是自然对数,sqrt是平方根,cos是余弦函数,sin是正弦函数,pi是圆周率,这都是数学里常用的函数和常量。使用这两个公式,就可以从U1和U2生成我们需要的正态分布的随机数Z0和Z1。

Box-Muller变换前后比较

使用pycharm运行以下python代码

import numpy as np
import matplotlib.pyplot as plt
import time

class RandNum:
    def __init__(self):
        self.seed = int(time.time())

    def uniform(self, num):
        np.random.seed(self.seed)
        self.seed += 1
        return np.random.uniform(0, 1, num)

    def normal(self, num):
        u1 = self.uniform(num)
        u2 = self.uniform(num)
        z0 = np.sqrt(-2 * np.log(u1)) * np.sin(2.0 * np.pi * u2)
        z1 = np.sqrt(-2 * np.log(u1)) * np.cos(2.0 * np.pi * u2)
        return u1, u2, z0, z1

# 主程序
if __name__ == "__main__":
    randnum = RandNum()
    u1, u2, z0, z1 = randnum.normal(10000)

    plt.figure(figsize=(10, 10))

    # 绘制u1的直方图
    plt.subplot(221)
    plt.hist(u1, bins=30, density=True, alpha=0.5, color='steelblue', edgecolor='none')
    plt.title("Histogram of u1")

    # 绘制u2的直方图
    plt.subplot(222)
    plt.hist(u2, bins=30, density=True, alpha=0.5, color='green', edgecolor='none')
    plt.title("Histogram of u2")

    # 绘制z0的直方图
    plt.subplot(223)
    plt.hist(z0, bins=30, density=True, alpha=0.5, color='red', edgecolor='none')
    plt.title("Histogram of z0")

    # 绘制z1的直方图
    plt.subplot(224)
    plt.hist(z1, bins=30, density=True, alpha=0.5, color='yellow', edgecolor='none')
    plt.title("Histogram of z1")

    plt.show()

图像示例

image.png