如何使用NumPy生成正态分布随机数
概率分布描述了事件或实验所有可能结果的可能性。正态分布是最有用的概率分布之一,因为它可以很好地模拟许多自然现象。
正态分布在其峰值周围是对称的。由于这种对称性,分布的均值通常用μ表示,并位于该峰值处。标准差σ描述了分布的扩散程度。
如果一些样本服从正态分布,则随机抽取一个样本接近均值的概率很高。实际上,大约68%的所有样本都在距离平均值一个标准差之内。
图中曲线下的面积解释为概率测量。绿色区域代表所有小于平均数一个标准偏差的样本,占曲线下面积的68%。
我们都知道在Matlab中可以使用randn函数创建正态分布的随机数。
在Python中,可以使用NumPy从正态分布中创建随机数样本。
numpy生成随机数
NumPy包含一个完整的子包numpy.random,专门用于处理随机数。由于历史原因,该软件包包括许多函数。
通常应该通过实例化默认随机数生成器(RNG)来开始:
import numpy as np
rng = np.random.default_rng()
RNG可以从许多不同的分布中生成随机数。
要从正态分布中抽样,可以使用.normal()函数:
虽然上图这些数字看起来是随机的,但很难确认这些数字是否从给定分布中抽取的。
因此,可以一次生成大量随机数:
numbers = rng.normal(size=10000)
numbers.mean()
numbers.std()
绘制正态分布图像
这里尝试生成直方图表示上一节生成的10000个随机数
import matplotlib.pyplot as plt
plt.hist(numbers)
plt.show
直方图的纵轴表示不同区间的样本数量。
直方图的形状显示了与正态分布相关联的特征,它是对称的,具有一个明确定义的峰值,并向两侧逐渐变窄。
通过增加区间数量,可以得到更加平滑的图像
plt.hist(numbers,bins=500)
plt.show
这些是概率密度函数,可以使用它们来绘制理论概率分布,并与之前生成的随机数分布进行对比,可以看到生成的随机数符合正态分布
import scipy.stats
bins = 500
bin_width = (numbers.max() - numbers.min()) / bins
hist_area = len(numbers) * bin_width
x = np.linspace(numbers.min(), numbers.max(), 101)
plt.plot(x, scipy.stats.norm.pdf(x) * hist_area)
plt.hist(numbers,bins=500)
plt.show()
控制随机数生成器
自然界很多事物都服从正态分布,例如身高、体重、鞋码。
在像计算机这样的确定性系统中创建随机数并不容易。大多数随机数生成器不能产生真正的随机性,而是通过一种确定性和可重复的过程生成数字,使得这些数字看起来是随机的。
通常情况下,一个随机数生成器——或者更准确地说,伪随机数生成器(PRNG)——是从已知种子开始,并从中生成一个伪随机数。这样一个发生器的优点之一就在于可以再现那些伪造出来的数字:
如果使用特定的种子创建随机数生成器,则可以通过使用相同的种子稍后重新创建相同的随机数。在此示例中,对.normal()的第二次调用生成与第一次调用相同的数字。另一方面,如果您使用不同的种子初始化生成器,则会获得不同的随机数。
历史上,在NumPy中处理随机数时没有使用显式随机数生成器。而是直接调用诸如np.random.normal()之类的函数。但是,NumPy 1.17引入了显式随机数生成器,并鼓励尽可能多地使用这种新方法来处理随机数。
用中心极限定理逐步接近正常分布
正态分布在统计学和概率论中扮演着重要角色。它出现在许多实际例子和许多理论结果中。中心极限定理可以解释一些根本原因。
该结果表明,重复实验的平均值将近似于正态分布。这个成立的一个重要条件是实验具有相同的分布,尽管它们不需要是正态分布。
举个掷骰子的例子。普通骰子有六个面,在单次掷骰子时,每种结果——1、2、3、4、5或6都是等可能发生的。因此这些投掷是均匀分布的,然而,反复投掷骰子得到的平均数仍会接近正态分布。
可以使用NumPy来证明这一点。首先生成随机骰子投掷:
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(seed=2310)
rng.integers(low=1, high=6, endpoint=True, size=1)
使用 .integers() 并指定要在 1 到 6 的范围内(包括边界)抽样整数。接下来可以使用 size 来模拟重复掷骰子的分布。首先将掷骰子的次数重复两次,为了获得代表性分布,进行10000次这样的重复投掷,使用 .mean() 来计算两次掷骰子的平均值,然后绘制直方图来查看分布:
rolls = rng.integers(low=1, high=6, endpoint=True, size=(10_000, 2))
plt.hist(rolls.mean(axis=1), bins=21)
plt.show()
分布接近对称且有明显的峰值,该分布并不均匀,每个结果出现的可能性也不相等。
如果你增加重复的次数,那么你会发现分布会越来越接近正态分布。
这说明了中心极限定理:重复实验产生正态性。因为许多自然过程包括累加效应,它们通常会符合正态分布。
—— end ——
文章来源:基算仿真