22.8. 分布¶ 在 SageMaker Studio Lab 中打开 Notebook
现在我们已经学习了如何在离散和连续的情况下处理概率,让我们来了解一些常见的分布。根据机器学习领域的不同,我们可能需要熟悉更多的分布,而对于深度学习的某些领域,我们可能完全不需要了解这些分布。但是,熟悉下面这个基本列表是有益的。让我们先导入一些常用的库。
%matplotlib inline
from math import erf, factorial
import torch
from IPython import display
from d2l import torch as d2l
torch.pi = torch.acos(torch.zeros(1)) * 2 # Define pi in torch
%matplotlib inline
from math import erf, factorial
import numpy as np
from IPython import display
from d2l import mxnet as d2l
%matplotlib inline
from math import erf, factorial
import tensorflow as tf
import tensorflow_probability as tfp
from IPython import display
from d2l import tensorflow as d2l
tf.pi = tf.acos(tf.zeros(1)) * 2 # Define pi in TensorFlow
22.8.1. 伯努利分布¶
这是我们通常遇到的最简单的随机变量。这个随机变量可以看作是抛硬币,结果为 \(1\) 的概率为 \(p\),结果为 \(0\) 的概率为 \(1-p\)。如果我们有一个服从该分布的随机变量 \(X\),我们会写作
其累积分布函数为
概率质量函数绘制如下。
p = 0.3
d2l.set_figsize()
d2l.plt.stem([0, 1], [1 - p, p], use_line_collection=True)
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.show()
p = 0.3
d2l.set_figsize()
d2l.plt.stem([0, 1], [1 - p, p], use_line_collection=True)
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.show()
p = 0.3
d2l.set_figsize()
d2l.plt.stem([0, 1], [1 - p, p], use_line_collection=True)
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.show()
现在,我们来绘制累积分布函数 (22.8.2)。
x = torch.arange(-1, 2, 0.01)
def F(x):
return 0 if x < 0 else 1 if x > 1 else 1 - p
d2l.plot(x, torch.tensor([F(y) for y in x]), 'x', 'c.d.f.')
x = np.arange(-1, 2, 0.01)
def F(x):
return 0 if x < 0 else 1 if x > 1 else 1 - p
d2l.plot(x, np.array([F(y) for y in x]), 'x', 'c.d.f.')
x = tf.range(-1, 2, 0.01)
def F(x):
return 0 if x < 0 else 1 if x > 1 else 1 - p
d2l.plot(x, tf.constant([F(y) for y in x]), 'x', 'c.d.f.')
如果 \(X \sim \textrm{Bernoulli}(p)\),那么
\(\mu_X = p\),
\(\sigma_X^2 = p(1-p)\).
我们可以从伯努利随机变量中采样一个任意形状的数组,如下所示。
1*(torch.rand(10, 10) < p)
tensor([[0, 1, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 0, 0, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 1, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
[1, 1, 0, 0, 1, 1, 1, 1, 1, 0],
[1, 0, 0, 0, 1, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[1, 0, 1, 1, 1, 1, 0, 1, 0, 0]])
1*(np.random.rand(10, 10) < p)
array([[0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0, 1],
[0, 1, 0, 0, 0, 0, 0, 1, 1, 0],
[1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 1, 0, 1, 1, 0, 0, 0, 0, 0],
[1, 0, 0, 1, 1, 0, 0, 0, 0, 1],
[1, 0, 1, 0, 0, 1, 1, 0, 0, 0]])
tf.cast(tf.random.uniform((10, 10)) < p, dtype=tf.float32)
<tf.Tensor: shape=(10, 10), dtype=float32, numpy=
array([[0., 0., 0., 0., 1., 1., 0., 1., 0., 0.],
[0., 0., 1., 0., 0., 1., 0., 0., 0., 0.],
[1., 0., 0., 1., 0., 1., 0., 0., 1., 0.],
[1., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 1., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 1., 1., 1.],
[0., 1., 1., 0., 0., 0., 0., 0., 0., 1.],
[0., 1., 0., 1., 0., 1., 1., 0., 1., 0.]], dtype=float32)>
22.8.2. 离散均匀分布¶
下一个常见的随机变量是离散均匀分布。在我们的讨论中,我们假设它在整数 \(\{1, 2, \ldots, n\}\) 上取值,但是任何其他值集都可以自由选择。在这种情况下,均匀这个词的含义是每个可能的值都是等可能的。每个值 \(i \in \{1, 2, 3, \ldots, n\}\) 的概率是 \(p_i = \frac{1}{n}\)。我们将一个服从该分布的随机变量 \(X\) 记作
其累积分布函数为
我们首先绘制概率质量函数。
n = 5
d2l.plt.stem([i+1 for i in range(n)], n*[1 / n], use_line_collection=True)
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.show()
n = 5
d2l.plt.stem([i+1 for i in range(n)], n*[1 / n], use_line_collection=True)
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.show()
n = 5
d2l.plt.stem([i+1 for i in range(n)], n*[1 / n], use_line_collection=True)
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.show()
现在,我们来绘制累积分布函数 (22.8.4)。
x = torch.arange(-1, 6, 0.01)
def F(x):
return 0 if x < 1 else 1 if x > n else torch.floor(x) / n
d2l.plot(x, torch.tensor([F(y) for y in x]), 'x', 'c.d.f.')
x = np.arange(-1, 6, 0.01)
def F(x):
return 0 if x < 1 else 1 if x > n else np.floor(x) / n
d2l.plot(x, np.array([F(y) for y in x]), 'x', 'c.d.f.')
x = tf.range(-1, 6, 0.01)
def F(x):
return 0 if x < 1 else 1 if x > n else tf.floor(x) / n
d2l.plot(x, [F(y) for y in x], 'x', 'c.d.f.')
如果 \(X \sim U(n)\),那么
\(\mu_X = \frac{1+n}{2}\),
\(\sigma_X^2 = \frac{n^2-1}{12}\).
我们可以从离散均匀随机变量中采样一个任意形状的数组,如下所示。
torch.randint(1, n, size=(10, 10))
tensor([[1, 4, 3, 2, 1, 1, 3, 1, 1, 4],
[4, 1, 1, 4, 4, 1, 4, 3, 2, 4],
[2, 4, 4, 1, 4, 2, 4, 3, 2, 1],
[1, 2, 3, 1, 1, 4, 2, 4, 1, 3],
[1, 2, 4, 1, 4, 3, 3, 2, 2, 1],
[1, 2, 2, 4, 1, 3, 2, 4, 2, 3],
[1, 2, 3, 4, 1, 3, 4, 1, 4, 3],
[3, 1, 1, 4, 4, 1, 3, 1, 1, 2],
[2, 2, 4, 3, 4, 2, 3, 4, 2, 4],
[1, 4, 3, 3, 2, 3, 3, 4, 1, 3]])
np.random.randint(1, n, size=(10, 10))
array([[3, 4, 2, 1, 2, 1, 4, 4, 1, 4],
[2, 3, 4, 2, 1, 4, 4, 2, 2, 4],
[3, 4, 3, 4, 4, 4, 2, 4, 2, 4],
[3, 4, 4, 4, 1, 3, 1, 2, 4, 1],
[2, 2, 4, 1, 2, 4, 4, 3, 1, 2],
[3, 4, 4, 3, 4, 1, 1, 1, 4, 2],
[2, 1, 2, 1, 2, 2, 4, 4, 2, 2],
[3, 4, 3, 3, 3, 3, 3, 4, 4, 1],
[2, 1, 4, 2, 4, 2, 1, 2, 3, 1],
[3, 4, 1, 2, 2, 4, 4, 4, 4, 3]])
tf.random.uniform((10, 10), 1, n, dtype=tf.int32)
<tf.Tensor: shape=(10, 10), dtype=int32, numpy=
array([[2, 4, 1, 2, 3, 2, 4, 4, 1, 4],
[1, 1, 2, 2, 1, 3, 4, 1, 1, 2],
[2, 1, 4, 3, 1, 4, 1, 1, 2, 2],
[2, 1, 3, 1, 4, 2, 2, 3, 3, 4],
[2, 3, 2, 1, 2, 4, 3, 3, 2, 2],
[3, 3, 3, 3, 1, 3, 4, 3, 4, 1],
[2, 2, 3, 3, 2, 1, 1, 2, 2, 4],
[2, 2, 1, 1, 3, 4, 3, 1, 4, 2],
[3, 4, 2, 1, 4, 4, 1, 4, 2, 2],
[2, 3, 1, 2, 4, 1, 2, 1, 2, 2]], dtype=int32)>
22.8.3. 连续均匀分布¶
接下来,让我们讨论连续均匀分布。这个随机变量背后的思想是,如果我们增加离散均匀分布中的 \(n\),然后将其缩放到区间 \([a, b]\) 内,我们将接近一个连续随机变量,它以相同的概率在 \([a, b]\) 内选择一个任意值。我们将这个分布记作
其概率密度函数为
其累积分布函数为
我们首先绘制概率密度函数 (22.8.6)。
a, b = 1, 3
x = torch.arange(0, 4, 0.01)
p = (x > a).type(torch.float32)*(x < b).type(torch.float32)/(b-a)
d2l.plot(x, p, 'x', 'p.d.f.')
a, b = 1, 3
x = np.arange(0, 4, 0.01)
p = (x > a)*(x < b)/(b - a)
d2l.plot(x, p, 'x', 'p.d.f.')
a, b = 1, 3
x = tf.range(0, 4, 0.01)
p = tf.cast(x > a, tf.float32) * tf.cast(x < b, tf.float32) / (b - a)
d2l.plot(x, p, 'x', 'p.d.f.')
现在,我们来绘制累积分布函数 (22.8.7)。
def F(x):
return 0 if x < a else 1 if x > b else (x - a) / (b - a)
d2l.plot(x, torch.tensor([F(y) for y in x]), 'x', 'c.d.f.')
def F(x):
return 0 if x < a else 1 if x > b else (x - a) / (b - a)
d2l.plot(x, np.array([F(y) for y in x]), 'x', 'c.d.f.')
def F(x):
return 0 if x < a else 1 if x > b else (x - a) / (b - a)
d2l.plot(x, [F(y) for y in x], 'x', 'c.d.f.')
如果 \(X \sim U(a, b)\),那么
\(\mu_X = \frac{a+b}{2}\),
\(\sigma_X^2 = \frac{(b-a)^2}{12}\).
我们可以从均匀随机变量中采样一个任意形状的数组,如下所示。请注意,它默认从 \(U(0,1)\) 中采样,所以如果我们想要一个不同的范围,我们需要对它进行缩放。
(b - a) * torch.rand(10, 10) + a
tensor([[2.4857, 2.2461, 1.6809, 2.7434, 2.7072, 2.6190, 1.4883, 1.2517, 1.3454,
2.4754],
[1.0974, 1.5680, 1.8788, 2.8231, 2.1695, 2.6461, 1.4914, 1.4887, 1.3860,
1.9090],
[1.3746, 1.7773, 1.2412, 1.1950, 2.7281, 2.8356, 1.2266, 2.4724, 2.4641,
2.8991],
[2.4018, 2.6727, 1.0308, 1.1951, 1.9390, 1.6486, 2.8314, 1.1025, 1.3354,
1.0130],
[1.1281, 1.8000, 2.3788, 2.6580, 1.6750, 2.2081, 1.2705, 1.0757, 2.3311,
2.6557],
[2.9912, 1.2263, 1.8115, 1.5940, 1.9321, 1.6469, 2.2990, 2.1473, 1.8165,
1.2806],
[1.1672, 1.1536, 1.9649, 2.1655, 1.7170, 1.0284, 1.3305, 2.1904, 1.4036,
2.1958],
[2.5891, 2.5840, 2.2679, 2.0687, 2.9249, 1.6741, 1.2238, 2.4463, 2.2235,
2.7038],
[1.8697, 2.4965, 1.5785, 2.7890, 2.3319, 2.1434, 2.3333, 1.0286, 1.9245,
1.7640],
[1.2504, 1.7558, 1.4322, 1.5226, 1.3380, 1.1388, 1.8707, 2.2330, 2.3818,
2.2087]])
(b - a) * np.random.rand(10, 10) + a
array([[2.38360201, 1.42301059, 1.30828215, 2.23648218, 2.36792603,
1.91291633, 2.86068987, 1.82011582, 2.04179583, 1.60297964],
[2.16824638, 1.57385641, 1.66921053, 1.43114352, 2.25602411,
2.87490344, 2.40876076, 1.7617666 , 2.02837681, 1.95209339],
[2.10921523, 2.19732773, 1.59625198, 1.61302107, 1.27852537,
2.37811459, 2.29000406, 1.03847199, 1.56422557, 2.50686118],
[1.7817774 , 1.62100143, 2.27307703, 2.05133929, 2.05104624,
2.96610051, 2.89734953, 1.21910903, 2.9754619 , 2.48726223],
[2.56736775, 1.839721 , 2.95232472, 1.12483235, 2.5400353 ,
2.29622885, 2.28849311, 2.52556794, 1.11539063, 1.49332251],
[1.87762881, 2.0559545 , 1.62359339, 1.90967816, 2.98212587,
1.21525452, 2.68658767, 2.54676585, 1.1852055 , 2.45969756],
[2.07266639, 2.95876653, 2.00955484, 1.55029107, 1.50520493,
1.88796762, 1.92171128, 2.02120858, 1.56685236, 2.6619405 ],
[1.11606361, 1.40236782, 1.0776729 , 1.41579594, 2.87791721,
1.28461063, 1.91013181, 1.59194299, 2.97532135, 2.85899927],
[2.06719995, 1.70292102, 2.4059567 , 1.61806169, 1.81718481,
2.92306811, 2.31158504, 1.05026323, 1.57910039, 1.83457301],
[1.85492878, 1.84662898, 1.41416257, 1.05939756, 1.23999994,
2.11843352, 2.93857488, 1.05851556, 1.69802914, 2.87658077]])
(b - a) * tf.random.uniform((10, 10)) + a
<tf.Tensor: shape=(10, 10), dtype=float32, numpy=
array([[2.8664184, 2.438953 , 2.183648 , 2.6834862, 2.5966637, 1.1439416,
2.608807 , 1.0293896, 2.3320234, 1.8846245],
[1.080436 , 1.3330972, 2.3824317, 1.6961837, 2.3930948, 2.5123057,
2.1429653, 1.4829049, 2.1934493, 2.2013004],
[1.0424838, 2.796021 , 2.7420611, 1.4439683, 1.0762017, 2.6044428,
2.288131 , 2.7516022, 1.878279 , 1.0029557],
[2.6579297, 2.4939828, 2.953441 , 2.1348112, 1.7846551, 2.8381727,
1.4484763, 2.6948266, 1.966721 , 2.1762617],
[1.6473658, 2.3157299, 1.5706291, 2.6134923, 2.5549824, 1.2292521,
1.2990353, 1.1018548, 2.3749387, 2.814359 ],
[1.3394063, 1.7971177, 1.6891305, 2.0523329, 1.7005038, 2.4614336,
2.6337047, 2.2743304, 2.2163136, 1.7015438],
[1.9442399, 2.6003797, 2.0429137, 2.23415 , 2.2446375, 1.4651737,
2.4320726, 1.5983024, 1.5828397, 1.197459 ],
[1.8227904, 2.2702656, 1.9956629, 1.6375196, 1.4135013, 1.7102294,
2.4104555, 2.0014505, 1.4420359, 2.340128 ],
[1.5781457, 2.5949705, 2.9382844, 1.0134435, 2.4329488, 1.2575395,
1.6634142, 1.7678592, 2.8386252, 1.0254025],
[1.6798866, 2.7402108, 1.1072655, 2.0986164, 1.3502924, 2.2395515,
2.4990425, 1.8304801, 2.674482 , 2.3498237]], dtype=float32)>
22.8.4. 二项分布¶
让我们把事情弄得复杂一点,研究一下二项随机变量。这个随机变量源于进行一系列 \(n\) 次独立实验,每次实验成功的概率为 \(p\),我们想知道我们期望看到多少次成功。
让我们用数学的方式来表达。每个实验都是一个独立的随机变量 \(X_i\),我们用 \(1\) 来编码成功,用 \(0\) 来编码失败。由于每个实验都是一次独立的抛硬币,成功的概率为 \(p\),我们可以说 \(X_i \sim \textrm{Bernoulli}(p)\)。那么,二项随机变量是
在这种情况下,我们会写作
为了得到累积分布函数,我们需要注意到,恰好获得 \(k\) 次成功的情况有 \(\binom{n}{k} = \frac{n!}{k!(n-k)!}\) 种,每种情况发生的概率是 \(p^k(1-p)^{n-k}\)。因此累积分布函数是
我们首先绘制概率质量函数。
n, p = 10, 0.2
# Compute binomial coefficient
def binom(n, k):
comb = 1
for i in range(min(k, n - k)):
comb = comb * (n - i) // (i + 1)
return comb
pmf = torch.tensor([p**i * (1-p)**(n - i) * binom(n, i) for i in range(n + 1)])
d2l.plt.stem([i for i in range(n + 1)], pmf, use_line_collection=True)
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.show()
n, p = 10, 0.2
# Compute binomial coefficient
def binom(n, k):
comb = 1
for i in range(min(k, n - k)):
comb = comb * (n - i) // (i + 1)
return comb
pmf = np.array([p**i * (1-p)**(n - i) * binom(n, i) for i in range(n + 1)])
d2l.plt.stem([i for i in range(n + 1)], pmf, use_line_collection=True)
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.show()
n, p = 10, 0.2
# Compute binomial coefficient
def binom(n, k):
comb = 1
for i in range(min(k, n - k)):
comb = comb * (n - i) // (i + 1)
return comb
pmf = tf.constant([p**i * (1-p)**(n - i) * binom(n, i) for i in range(n + 1)])
d2l.plt.stem([i for i in range(n + 1)], pmf, use_line_collection=True)
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.show()
现在,我们来绘制累积分布函数 (22.8.10)。
x = torch.arange(-1, 11, 0.01)
cmf = torch.cumsum(pmf, dim=0)
def F(x):
return 0 if x < 0 else 1 if x > n else cmf[int(x)]
d2l.plot(x, torch.tensor([F(y) for y in x.tolist()]), 'x', 'c.d.f.')
x = np.arange(-1, 11, 0.01)
cmf = np.cumsum(pmf)
def F(x):
return 0 if x < 0 else 1 if x > n else cmf[int(x)]
d2l.plot(x, np.array([F(y) for y in x.tolist()]), 'x', 'c.d.f.')
x = tf.range(-1, 11, 0.01)
cmf = tf.cumsum(pmf)
def F(x):
return 0 if x < 0 else 1 if x > n else cmf[int(x)]
d2l.plot(x, [F(y) for y in x.numpy().tolist()], 'x', 'c.d.f.')
如果 \(X \sim \textrm{Binomial}(n, p)\),那么
\(\mu_X = np\),
\(\sigma_X^2 = np(1-p)\).
这来自于对 \(n\) 个伯努利随机变量之和的期望值的线性性,以及独立随机变量之和的方差是方差之和这一事实。这可以如下采样。
m = torch.distributions.binomial.Binomial(n, p)
m.sample(sample_shape=(10, 10))
tensor([[6., 3., 4., 3., 3., 1., 3., 3., 3., 3.],
[3., 1., 2., 2., 3., 2., 1., 3., 1., 4.],
[6., 1., 0., 3., 0., 3., 1., 0., 1., 1.],
[1., 2., 3., 1., 2., 2., 2., 2., 3., 2.],
[2., 2., 5., 4., 1., 3., 4., 3., 2., 0.],
[2., 0., 2., 2., 3., 1., 1., 4., 3., 1.],
[1., 1., 3., 2., 4., 2., 2., 2., 1., 0.],
[0., 3., 2., 1., 1., 3., 2., 1., 1., 3.],
[2., 3., 2., 3., 4., 3., 1., 2., 1., 2.],
[1., 2., 1., 1., 3., 2., 4., 3., 3., 2.]])
np.random.binomial(n, p, size=(10, 10))
array([[2, 1, 1, 2, 0, 3, 3, 1, 3, 4],
[0, 2, 0, 2, 2, 1, 2, 1, 1, 2],
[2, 2, 1, 1, 1, 2, 2, 3, 2, 3],
[3, 2, 3, 2, 3, 2, 1, 1, 4, 1],
[2, 2, 1, 2, 0, 2, 2, 1, 1, 2],
[1, 1, 1, 0, 2, 0, 3, 3, 1, 0],
[3, 3, 0, 3, 2, 2, 0, 1, 4, 4],
[0, 1, 0, 1, 2, 5, 1, 3, 1, 0],
[0, 3, 2, 4, 2, 1, 3, 3, 3, 3],
[4, 3, 3, 2, 3, 2, 1, 3, 0, 1]])
m = tfp.distributions.Binomial(n, p)
m.sample(sample_shape=(10, 10))
WARNING:tensorflow:From /home/ci/.local/lib/python3.10/site-packages/tensorflow_probability/python/internal/batched_rejection_sampler.py:102: calling while_loop_v2 (from tensorflow.python.ops.control_flow_ops) with back_prop=False is deprecated and will be removed in a future version.
Instructions for updating:
back_prop=False is deprecated. Consider using tf.stop_gradient instead.
Instead of:
results = tf.while_loop(c, b, vars, back_prop=False)
Use:
results = tf.nest.map_structure(tf.stop_gradient, tf.while_loop(c, b, vars))
<tf.Tensor: shape=(10, 10), dtype=float32, numpy=
array([[6., 9., 9., 9., 8., 4., 6., 7., 5., 7.],
[7., 7., 6., 7., 4., 4., 6., 6., 7., 7.],
[6., 3., 5., 9., 7., 7., 6., 6., 5., 7.],
[4., 6., 5., 2., 5., 6., 8., 8., 4., 7.],
[5., 3., 6., 6., 8., 5., 4., 5., 7., 7.],
[5., 3., 6., 3., 4., 5., 4., 1., 7., 5.],
[6., 6., 6., 5., 4., 6., 7., 8., 5., 3.],
[5., 8., 6., 9., 4., 5., 3., 7., 5., 7.],
[5., 2., 5., 6., 6., 8., 8., 4., 4., 6.],
[6., 7., 3., 5., 4., 5., 3., 4., 6., 7.]], dtype=float32)>
22.8.5. 泊松分布¶
现在让我们做一个思想实验。我们站在一个公交车站,想知道在接下来的一分钟内会有多少辆公交车到达。让我们从考虑 \(X^{(1)} \sim \textrm{Bernoulli}(p)\) 开始,这仅仅是一辆公交车在一分钟窗口内到达的概率。对于远离市中心的公交车站,这可能是一个相当好的近似。我们可能永远不会在一分钟内看到超过一辆公交车。
然而,如果我们身处繁忙地区,两辆公交车到达是可能甚至很可能的。我们可以通过将我们的随机变量分成两部分来建模,即前半分钟和后半分钟。在这种情况下,我们可以写作
其中 \(X^{(2)}\) 是总和,而 \(X^{(2)}_i \sim \textrm{Bernoulli}(p/2)\)。那么总分布是 \(X^{(2)} \sim \textrm{Binomial}(2, p/2)\)。
为什么要止步于此?让我们继续把那一分钟分成 \(n\) 部分。根据上面的相同推理,我们看到
考虑这些随机变量。根据上一节,我们知道 (22.8.12) 的均值为 \(\mu_{X^{(n)}} = n(p/n) = p\),方差为 \(\sigma_{X^{(n)}}^2 = n(p/n)(1-(p/n)) = p(1-p/n)\)。如果我们取 \(n \rightarrow \infty\),我们可以看到这些数字稳定到 \(\mu_{X^{(\infty)}} = p\) 和方差 \(\sigma_{X^{(\infty)}}^2 = p\)。这表明在这个无限细分的极限中,我们可能可以定义某个随机变量。
这应该不会太令人惊讶,因为在现实世界中,我们只需要数公交车的到达数量,但很高兴看到我们的数学模型是定义良好的。这种讨论可以被形式化为稀有事件定律。
仔细遵循这个推理,我们可以得到以下模型。我们会说 \(X \sim \textrm{Poisson}(\lambda)\),如果它是一个随机变量,取值为 \(\{0,1,2, \ldots\}\),概率为
值 \(\lambda > 0\) 被称为率(或形状参数),表示我们期望在一个单位时间内平均到达的数量。
我们可以将这个概率质量函数求和得到累积分布函数。
我们首先绘制概率质量函数 (22.8.13)。
lam = 5.0
xs = [i for i in range(20)]
pmf = torch.tensor([torch.exp(torch.tensor(-lam)) * lam**k
/ factorial(k) for k in xs])
d2l.plt.stem(xs, pmf, use_line_collection=True)
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.show()
lam = 5.0
xs = [i for i in range(20)]
pmf = np.array([np.exp(-lam) * lam**k / factorial(k) for k in xs])
d2l.plt.stem(xs, pmf, use_line_collection=True)
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.show()
lam = 5.0
xs = [i for i in range(20)]
pmf = tf.constant([tf.exp(tf.constant(-lam)).numpy() * lam**k
/ factorial(k) for k in xs])
d2l.plt.stem(xs, pmf, use_line_collection=True)
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.show()
现在,我们来绘制累积分布函数 (22.8.14)。
x = torch.arange(-1, 21, 0.01)
cmf = torch.cumsum(pmf, dim=0)
def F(x):
return 0 if x < 0 else 1 if x > n else cmf[int(x)]
d2l.plot(x, torch.tensor([F(y) for y in x.tolist()]), 'x', 'c.d.f.')
x = np.arange(-1, 21, 0.01)
cmf = np.cumsum(pmf)
def F(x):
return 0 if x < 0 else 1 if x > n else cmf[int(x)]
d2l.plot(x, np.array([F(y) for y in x.tolist()]), 'x', 'c.d.f.')
x = tf.range(-1, 21, 0.01)
cmf = tf.cumsum(pmf)
def F(x):
return 0 if x < 0 else 1 if x > n else cmf[int(x)]
d2l.plot(x, [F(y) for y in x.numpy().tolist()], 'x', 'c.d.f.')
正如我们上面所看到的,均值和方差特别简洁。如果 \(X \sim \textrm{Poisson}(\lambda)\),那么
\(\mu_X = \lambda\),
\(\sigma_X^2 = \lambda\).
这可以如下采样。
m = torch.distributions.poisson.Poisson(lam)
m.sample((10, 10))
tensor([[ 1., 4., 6., 8., 4., 4., 4., 7., 6., 4.],
[ 3., 6., 7., 7., 5., 7., 7., 3., 5., 4.],
[ 4., 1., 3., 3., 10., 5., 5., 3., 7., 5.],
[ 4., 3., 4., 10., 8., 6., 4., 6., 5., 5.],
[ 5., 11., 1., 5., 7., 5., 2., 4., 3., 5.],
[ 6., 6., 4., 4., 3., 1., 5., 8., 4., 5.],
[ 2., 9., 7., 2., 6., 5., 2., 8., 6., 10.],
[ 1., 4., 3., 7., 3., 1., 7., 5., 3., 6.],
[ 5., 4., 6., 4., 9., 8., 3., 3., 1., 8.],
[ 3., 12., 9., 13., 2., 14., 3., 2., 0., 3.]])
np.random.poisson(lam, size=(10, 10))
array([[ 5, 5, 4, 2, 13, 7, 8, 6, 6, 5],
[ 6, 3, 4, 5, 4, 2, 1, 3, 6, 3],
[ 6, 5, 3, 4, 4, 4, 2, 3, 2, 5],
[ 2, 8, 4, 7, 7, 7, 5, 6, 2, 6],
[ 3, 4, 3, 0, 7, 2, 6, 6, 7, 4],
[ 4, 1, 5, 0, 3, 3, 3, 6, 4, 3],
[ 4, 5, 4, 6, 4, 5, 3, 6, 9, 7],
[ 4, 2, 5, 3, 5, 5, 2, 6, 10, 5],
[ 5, 4, 5, 3, 6, 5, 2, 3, 6, 3],
[ 8, 7, 9, 6, 3, 7, 11, 7, 13, 2]])
m = tfp.distributions.Poisson(lam)
m.sample((10, 10))
<tf.Tensor: shape=(10, 10), dtype=float32, numpy=
array([[ 6., 5., 3., 5., 4., 6., 5., 8., 4., 4.],
[ 6., 4., 3., 7., 9., 4., 4., 4., 7., 6.],
[ 9., 4., 5., 3., 6., 4., 1., 5., 4., 7.],
[ 7., 3., 4., 7., 5., 2., 3., 1., 6., 4.],
[ 4., 6., 4., 10., 5., 4., 4., 6., 2., 0.],
[ 3., 4., 5., 2., 5., 2., 3., 4., 3., 7.],
[ 2., 7., 6., 5., 3., 7., 6., 7., 4., 3.],
[ 4., 6., 4., 7., 4., 5., 2., 4., 5., 4.],
[ 6., 6., 3., 6., 4., 7., 6., 5., 3., 5.],
[ 5., 7., 2., 5., 2., 9., 9., 2., 3., 4.]], dtype=float32)>
22.8.6. 高斯分布¶
现在让我们尝试一个不同但相关的实验。假设我们再次进行 \(n\) 次独立的 \(\textrm{Bernoulli}(p)\) 测量 \(X_i\)。这些测量值之和的分布是 \(X^{(n)} \sim \textrm{Binomial}(n, p)\)。与 \(n\) 增加而 \(p\) 减小不同,让我们固定 \(p\),然后让 \(n \rightarrow \infty\)。在这种情况下 \(\mu_{X^{(n)}} = np \rightarrow \infty\) 和 \(\sigma_{X^{(n)}}^2 = np(1-p) \rightarrow \infty\),所以没有理由认为这个极限会是良定的。
然而,并非所有希望都已破灭!让我们通过定义
可以看出,它的均值为零,方差为一,因此有理由相信它会收敛到某个极限分布。如果我们绘制出这些分布的样子,我们将会更加确信它会起作用。
p = 0.2
ns = [1, 10, 100, 1000]
d2l.plt.figure(figsize=(10, 3))
for i in range(4):
n = ns[i]
pmf = torch.tensor([p**i * (1-p)**(n-i) * binom(n, i)
for i in range(n + 1)])
d2l.plt.subplot(1, 4, i + 1)
d2l.plt.stem([(i - n*p)/torch.sqrt(torch.tensor(n*p*(1 - p)))
for i in range(n + 1)], pmf,
use_line_collection=True)
d2l.plt.xlim([-4, 4])
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.title("n = {}".format(n))
d2l.plt.show()
p = 0.2
ns = [1, 10, 100, 1000]
d2l.plt.figure(figsize=(10, 3))
for i in range(4):
n = ns[i]
pmf = np.array([p**i * (1-p)**(n-i) * binom(n, i) for i in range(n + 1)])
d2l.plt.subplot(1, 4, i + 1)
d2l.plt.stem([(i - n*p)/np.sqrt(n*p*(1 - p)) for i in range(n + 1)], pmf,
use_line_collection=True)
d2l.plt.xlim([-4, 4])
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.title("n = {}".format(n))
d2l.plt.show()
p = 0.2
ns = [1, 10, 100, 1000]
d2l.plt.figure(figsize=(10, 3))
for i in range(4):
n = ns[i]
pmf = tf.constant([p**i * (1-p)**(n-i) * binom(n, i)
for i in range(n + 1)])
d2l.plt.subplot(1, 4, i + 1)
d2l.plt.stem([(i - n*p)/tf.sqrt(tf.constant(n*p*(1 - p)))
for i in range(n + 1)], pmf,
use_line_collection=True)
d2l.plt.xlim([-4, 4])
d2l.plt.xlabel('x')
d2l.plt.ylabel('p.m.f.')
d2l.plt.title("n = {}".format(n))
d2l.plt.show()
需要注意的一点是:与泊松分布的情况相比,我们现在除以了标准差,这意味着我们将可能的结果压缩到越来越小的区域。这表明我们的极限将不再是离散的,而是连续的。
对所发生情况的推导超出了本文档的范围,但中心极限定理指出,当 \(n \rightarrow \infty\) 时,这将产生高斯分布(或有时称为正态分布)。更明确地说,对于任何 \(a, b\)
我们称一个随机变量是正态分布的,具有给定的均值 \(\mu\) 和方差 \(\sigma^2\),记作 \(X \sim \mathcal{N}(\mu, \sigma^2)\),如果 \(X\) 的密度为
我们首先绘制概率密度函数 (22.8.17)。
mu, sigma = 0, 1
x = torch.arange(-3, 3, 0.01)
p = 1 / torch.sqrt(2 * torch.pi * sigma**2) * torch.exp(
-(x - mu)**2 / (2 * sigma**2))
d2l.plot(x, p, 'x', 'p.d.f.')
mu, sigma = 0, 1
x = np.arange(-3, 3, 0.01)
p = 1 / np.sqrt(2 * np.pi * sigma**2) * np.exp(-(x - mu)**2 / (2 * sigma**2))
d2l.plot(x, p, 'x', 'p.d.f.')
mu, sigma = 0, 1
x = tf.range(-3, 3, 0.01)
p = 1 / tf.sqrt(2 * tf.pi * sigma**2) * tf.exp(
-(x - mu)**2 / (2 * sigma**2))
d2l.plot(x, p, 'x', 'p.d.f.')
现在,我们来绘制累积分布函数。超出了本附录的范围,但高斯累积分布函数没有以更初等的函数表示的封闭形式公式。我们将使用 erf
,它提供了一种数值计算这个积分的方法。
def phi(x):
return (1.0 + erf((x - mu) / (sigma * torch.sqrt(torch.tensor(2.))))) / 2.0
d2l.plot(x, torch.tensor([phi(y) for y in x.tolist()]), 'x', 'c.d.f.')
def phi(x):
return (1.0 + erf((x - mu) / (sigma * np.sqrt(2)))) / 2.0
d2l.plot(x, np.array([phi(y) for y in x.tolist()]), 'x', 'c.d.f.')
def phi(x):
return (1.0 + erf((x - mu) / (sigma * tf.sqrt(tf.constant(2.))))) / 2.0
d2l.plot(x, [phi(y) for y in x.numpy().tolist()], 'x', 'c.d.f.')
敏锐的读者会认出其中一些术语。确实,我们在 22.5节 中遇到过这个积分。我们确实需要那个计算来证明这个 \(p_X(x)\) 的总面积为1,因此是一个有效的密度。
我们选择使用抛硬币来简化计算,但这个选择并没有任何根本性的原因。事实上,如果我们取任何一组独立同分布的随机变量 \(X_i\),并构造
那么
将近似于高斯分布。要使其成立还需要额外的要求,最常见的是 \(E[X^4] < \infty\),但其原理是清晰的。
中心极限定理是高斯分布对概率、统计和机器学习至关重要的原因。每当我们可以说我们测量的东西是许多小的独立贡献之和时,我们就可以假设被测量的东西将接近高斯分布。
高斯分布还有许多其他迷人的性质,我们在此想讨论其中一个。高斯分布是所谓的最大熵分布。我们将在 22.11节 中更深入地讨论熵,但目前我们只需要知道它是随机性的一种度量。在严格的数学意义上,我们可以将高斯分布视为具有固定均值和方差的随机变量中最随机的选择。因此,如果我们知道我们的随机变量具有某个均值和方差,高斯分布在某种意义上是我们能做出的最保守的分布选择。
在本节结束时,让我们回顾一下,如果 \(X \sim \mathcal{N}(\mu, \sigma^2)\),那么
\(\mu_X = \mu\),
\(\sigma_X^2 = \sigma^2\).
我们可以从高斯(或标准正态)分布中采样,如下所示。
torch.normal(mu, sigma, size=(10, 10))
tensor([[ 1.3588, 0.0473, -1.5805, -0.0108, 0.4253, 0.7924, -0.6547, 0.7313,
-0.3038, 1.1935],
[ 0.0089, 0.8951, 1.0055, 0.0956, -1.1109, -0.6342, 1.6772, 1.0314,
0.3819, -1.7822],
[-0.0604, -1.0318, 0.9113, 1.3118, -1.8370, -0.9023, 1.0365, 0.9052,
-0.6411, -0.8949],
[-0.1713, -0.2347, 0.0767, -0.6375, -0.4612, -1.6875, -0.1570, 1.0591,
0.8377, 0.5097],
[ 0.2762, -0.6213, -0.3422, 0.9449, -0.7544, -0.2150, 1.0240, 1.0253,
-0.9182, 1.1536],
[ 0.0614, 0.2758, -0.3610, -1.0577, -0.5513, -0.9158, 0.7539, 0.9204,
-0.5908, 0.9113],
[ 1.6190, -0.9213, -0.7944, -2.2621, 0.5826, -1.8287, 1.4097, -0.5744,
-0.0668, 1.2074],
[-0.0624, 0.1928, 1.3002, 0.6756, 1.1590, 1.0144, 1.1840, -0.5010,
0.6026, -0.7722],
[-2.0148, 0.6958, 0.9940, 0.8477, 1.0957, -0.5253, 0.2353, -0.2663,
1.2275, 0.5993],
[ 0.4651, -0.8218, -0.5441, -2.0338, -0.6930, -0.0674, -0.4448, -0.8397,
0.0360, -0.7089]])
np.random.normal(mu, sigma, size=(10, 10))
array([[-0.11992579, 0.11242172, -0.35572603, 0.58136987, 0.12435943,
0.75733951, -0.13772477, -0.10270837, -1.59153191, -0.94093858],
[ 1.01421669, -0.64482199, -1.19968905, -0.29650658, 0.21354805,
-0.233707 , -0.84922388, 0.38375312, -0.3886712 , -0.28680926],
[ 0.26912722, 0.3832668 , -1.56047648, 1.55956818, -0.84004616,
-0.35190349, -0.54684824, 0.83748666, -0.95408109, 0.61570842],
[ 1.42284436, 1.47742409, 1.24482391, -0.85638551, -0.78176885,
0.78364858, 0.3804224 , 0.68402399, -1.51515355, 0.77536699],
[ 0.80657544, -2.01318421, 0.0262837 , 0.14704248, -1.05968065,
0.09993582, 0.3437732 , 0.71795499, 2.40652949, -0.24287448],
[ 0.60314452, 0.96139177, 0.42617912, -1.50385243, 1.89889768,
-0.18784024, -0.29100909, -0.61710869, 1.00194018, 0.81604849],
[ 0.27520902, -1.01320489, -1.32230684, 0.91961478, 1.08834228,
1.52541641, 0.83242223, -0.70249323, -1.41539373, 0.35746912],
[-0.37485341, -0.81440897, 0.64964391, -2.64441164, 0.51285708,
-0.00280402, -0.36267136, -0.89061862, -0.2587532 , 1.36505027],
[ 0.30396154, -1.17431444, 0.3697711 , -0.58526674, -1.00467336,
1.80141639, 0.44061838, 0.66772324, 0.00462039, -1.1309502 ],
[-0.28877008, 0.89796664, -0.80642533, -1.38372865, -0.72438918,
0.34978787, 0.9175374 , -0.43026127, -0.409859 , -1.43388418]])
tf.random.normal((10, 10), mu, sigma)
<tf.Tensor: shape=(10, 10), dtype=float32, numpy=
array([[-0.47082466, 0.8840835 , 0.13613819, -0.03887384, -1.3103229 ,
-0.87125725, 0.1467262 , -1.205572 , -0.9371071 , 0.5023256 ],
[-1.180266 , -1.1548375 , 1.3918712 , 0.43585238, 0.01733993,
-1.790916 , 0.12158127, -0.18356071, -0.28034893, -0.68480223],
[-2.3942738 , -1.0831766 , 0.2986123 , -0.11818152, 1.964042 ,
0.32228935, -0.20232098, 1.050008 , 0.68574095, -0.42878217],
[-0.2769131 , -2.0021179 , 1.4159348 , 0.22262587, 0.43598378,
-0.46475738, -0.6122648 , -1.0528542 , -0.99552286, -1.0606335 ],
[ 2.1345575 , -1.1459693 , 0.17686844, -0.9734485 , -0.94634855,
1.3928679 , -0.5110315 , 0.4557909 , 1.3669354 , -0.2503584 ],
[-0.96597624, -1.3229077 , -0.09891371, 0.6545881 , -0.13871759,
-0.32090858, 0.82951075, -1.2182976 , 0.4526086 , -0.41823685],
[-0.46264172, -1.0363445 , 0.7605979 , -1.1535795 , -0.97582847,
1.0007198 , 0.6450034 , -0.6664228 , -0.63123536, -0.07606531],
[ 0.6581902 , -0.18795264, -1.2491583 , -1.1792243 , -1.6373378 ,
-1.1988202 , 1.2502977 , 0.7889295 , -0.17174181, -0.37365198],
[ 1.4740059 , 1.1723006 , -0.25428358, -0.7858001 , 0.9736877 ,
0.716497 , -0.82188153, -0.11518795, -0.8567569 , -0.730805 ],
[-1.2619729 , 1.128404 , 0.4920151 , -0.3575905 , -0.4083109 ,
-0.06316691, 0.7730259 , -0.8047515 , 0.72060764, -0.3748437 ]],
dtype=float32)>
22.8.7. 指数族¶
上面列出的所有分布都有一个共同的属性,即它们都属于所谓的指数族。指数族是一组分布,其密度可以表示为以下形式
由于这个定义可能有点微妙,让我们仔细研究一下。
首先,\(h(\mathbf{x})\) 被称为基础测度或基测度。这可以看作是我们用指数权重修改的原始测度选择。
其次,我们有向量 \(\boldsymbol{\eta} = (\eta_1, \eta_2, ..., \eta_l) \in \mathbb{R}^l\),称为自然参数或规范参数。这些定义了如何修改基测度。自然参数通过将这些参数与 \(\mathbf{x}= (x_1, x_2, ..., x_n) \in \mathbb{R}^n\) 的某个函数 \(T(\cdot)\) 进行点积并取指数来进入新的测度。向量 \(T(\mathbf{x})= (T_1(\mathbf{x}), T_2(\mathbf{x}), ..., T_l(\mathbf{x}))\) 被称为 \(\boldsymbol{\eta}\) 的充分统计量。之所以使用这个名称,是因为 \(T(\mathbf{x})\) 所表示的信息足以计算概率密度,而不需要样本 \(\mathbf{x}\) 的其他信息。
第三,我们有 \(A(\boldsymbol{\eta})\),它被称为累积量函数,它确保上述分布 (22.8.20) 积分为一,即
具体来说,让我们考虑高斯分布。假设 \(\mathbf{x}\) 是一个单变量,我们看到它的密度为
这与指数族的定义相匹配,其中
基础测度:\(h(x) = \frac{1}{\sqrt{2 \pi}}\),
自然参数:\(\boldsymbol{\eta} = \begin{bmatrix} \eta_1 \\ \eta_2 \end{bmatrix} = \begin{bmatrix} \frac{\mu}{\sigma^2} \\ \frac{1}{2 \sigma^2} \end{bmatrix}\),
充分统计量:\(T(x) = \begin{bmatrix}x\\-x^2\end{bmatrix}\),以及
累积量函数:\(A({\boldsymbol\eta}) = \frac{1}{2 \sigma^2} \mu^2 + \log(\sigma) = \frac{\eta_1^2}{4 \eta_2} - \frac{1}{2}\log(2 \eta_2)\)。
值得注意的是,上述各项的确切选择有些随意。实际上,重要的是分布可以表示为这种形式,而不是形式本身。
正如我们在 4.1.2.2节 中提到的,一个广泛使用的技术是假设最终输出 \(\mathbf{y}\) 服从指数族分布。指数族是机器学习中经常遇到的一个常见而强大的分布族。
22.8.8. 小结¶
伯努利随机变量可以用来建模具有是/否结果的事件。
离散均匀分布模型从有限的可能性集合中进行选择。
连续均匀分布从一个区间中进行选择。
二项分布模型一系列伯努利随机变量,并计算成功的次数。
泊松随机变量模型稀有事件的到达。
高斯随机变量模型将大量独立随机变量相加的结果。
以上所有分布都属于指数族。