欢迎光临
我们一直在努力

Steve Brunton | Probability Bootcamp | 笔记 | 第一部分:概率导论 | Lecture 7 | 二项分布与多项分布

目录

    • 前言
    • 1. 引言
    • 2. 二项式系数
    • 3. 定义多项分布
    • 4. 公式推导
    • 5. 结语
    • 结语
    • 参考

前言

学习 Steven Brunton 讲授的概率与统计入门概述视频,本篇文章记录第七讲:二项分布与多项分布,记录下个人学习笔记,和大家一起分享交流😄

video:https://www.youtube.com/playlist?list=PLMrJAkhIeNNR3sNYvfgiKgcStwuPSts9V

1. 引言

我们一直在研究如何计算概率问题,比如:一副扑克牌中能组成同花顺的手牌有多少种可能,或者出现满堂红的手牌组合有多少种,归根结底,这需要计算特定事件在所有可能情况中出现的概率。

在所有扑克牌组合中,需要统计出同花、满堂红等特定牌型的出现次数,这本质上就是统计事件数量的问题 — 比如计算所有可能的扑克手牌总数,或者统计包含单张 K 的手牌组合数量等。

我们总结出了一些非常实用的计算公式,现在我要写下一个重要公式,这个公式与二项式系数密切相关,之后我们会将其推广到多项式分布,这个公式在计算可能出现的扑克牌组合数量时非常实用,当我们从一副 52 张扑克牌中发出 5 张手牌时,其分布符合二项式分布。

如果我发两副扑克手牌,假设有两个玩家在玩,那么发两副或三副手牌分别由多少种发牌方式?这属于多项式分布的范畴,这套公式极其实用,是计算各类复杂概率问题的必备工具。

因此,我们能收集到的无序样本数量就是无序样本的总数,从总数为

n

n

n 的物件中抽取样本,那么

n

n

n 就是 52 张牌,我抽到的样本就是一手 5 张牌,无序样本的数量计算方式为:从总量

n

n

n 中无放回抽取,即当我发出第一张牌后,牌堆只剩

n

1

n-1

n1 张牌,发出第二张牌后,牌堆仅剩 50 张牌,因此,无放回的无序样本数量等于组合数

(

n

r

)

\\binom{n}{r}

(rn) ,记住

n

C

r

nC_r

nCr 是其简写形式,我们有时称之为 “从

n

n

n 中选取

r

r

r 个样本”,这个公式的字面含义就是 “

n

n

n

r

r

r ”,记住,这个公式的计算方式是:

(

n

r

)

=

n

!

(

n

r

)

!

r

!

\\binom{n}{r} = \\frac{n!}{(n-r)! \\, r!}

(rn)=(nr)!r!n!

这就是计算公式,这就是我们计算扑克牌可能发牌组合数的方法,从一副 52 张的扑克牌中,不考虑发牌顺序且无放回抽取,总共可以发出多少种不同的 5 张牌组合?无论是先拿到 7 还是先拿到 9,最终组合结果都是相同的,这就是从

n

n

n 个元素中无序抽取

r

r

r 的样本的组合数,记作

(

n

r

)

\\binom{n}{r}

(rn) ,这个数值与二项式系数密切相关。

2. 二项式系数

我想展示这个是因为它非常有趣 — 你可能在帕斯卡三角形和多项式展开系数的计算中见过它,若取

(

x

+

y

)

2

(x+y)^2

(x+y)2 或者更一般地考虑

(

x

+

y

)

n

(x+y)^n

(x+y)n ,展开后将得到:

(

x

+

y

)

n

=

k

=

0

n

(

n

k

)

(

x

k

y

n

k

)

(x+y)^n = \\sum_{k=0}^{n} \\binom{n}{k} (x^ky^{n-k})

(x+y)n=k=0n(kn)(xkynk)

若干形如

x

k

y

n

k

x^ky^{n-k}

xkynk 的项之和,求和符号从

k

=

0

k=0

k=0

n

n

n ,这些单项式的系数将是

(

n

k

)

\\binom{n}{k}

(kn) ,这些就是二项式系数,之所以称为 “二项式”,是因为我们实际上是将两个项相加后求幂,因此这个多项式就是所有这些单项式的总和,其中系数正是二项式系数,要计算这些系数,可以通过帕斯卡三角形来求解,想必大家对此早已熟悉。

现在观察系数,帕斯卡三角形的顶端数字是 1,因此

(

x

+

y

)

0

(x+y)^0

(x+y)0 的结果就是 1,

(

x

+

y

)

1

(x+y)^1

(x+y)1 展开后,

x

x

x

y

y

y 的系数都是 1,帕斯卡三角形中的这些数字就是对应的系数,

(

x

+

y

)

2

(x+y)^2

(x+y)2 展开后的系数是 1、2、1,展开式是

x

2

+

2

x

y

+

y

2

x^2 + 2xy + y^2

x2+2xy+y2

(

x

+

y

)

3

(x+y)^3

(x+y)3 展开后得到

x

3

+

3

x

2

y

+

3

x

y

2

+

y

3

x^3 + 3x^2y + 3xy^2 + y^3

x3+3x2y+3xy2+y3 ,注意这个三角形中,每个新项都是它上方两项之和,

(

x

+

y

)

4

(x+y)^4

(x+y)4 的展开系数为 1、4、6、4、1,

(

x

+

y

)

5

(x+y)^5

(x+y)5 的展开系数为 1、5、10、10、5、1。

因此,我们可以直接从帕斯卡三角形中读出这个多项式展开的系数,构造起来非常简单,这个巧妙思路与概率论中频繁出现的

(

n

k

)

\\binom{n}{k}

(kn) 二项式系数密切相关,你会发现这种对称结构非常优美,蕴含着精妙的数学美感,这确实令人着迷。

但你会发现,当

n

n \\rightarrow \\infty

n 时,比如计算

(

x

+

y

)

100

(x+y)^{100}

(x+y)100 的展开式,这些系数的分布将逐渐收敛于正态分布,这种趋势在此已初现端倪,可以看出这个分布逐渐趋于正态分布。

事实上,你或许会想在计算机上编写代码实现这个现象,尝试取较大的

n

n

n 值构建三角形,逐行绘制每一层的分布,最终会收敛到优美的高斯分布(即正态分布)。

Python 示例代码如下:

"""
帕斯卡三角形(二项式系数)逐渐趋近正态分布的可视化。

数学关系:
C(n, k) / 2^n = P(X = k), X ~ Binomial(n, 1/2)

当 n 足够大时,将横坐标标准化:
z = (k – n/2) / sqrt(n/4)

标准化后的二项分布逐渐趋近标准正态分布 N(0, 1)。
"""

import argparse
import math
from typing import Iterable

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation

def pascal_row(n: int) > list[int]:
"""返回帕斯卡三角形第 n 行,即 (x+y)^n 的全部二项式系数。"""
if n < 0:
raise ValueError("n 必须是非负整数。")
return [math.comb(n, k) for k in range(n + 1)]

def binomial_probability(n: int) > tuple[np.ndarray, np.ndarray]:
"""
返回 X ~ Binomial(n, 1/2) 的横坐标 k 和概率 P(X=k)。

使用递推方式计算概率,避免直接把超大的组合数转换为浮点数:
p_0 = 2^(-n)
p_(k+1) = p_k * (n-k)/(k+1)
"""
if n < 0:
raise ValueError("n 必须是非负整数。")

k = np.arange(n + 1, dtype=float)

if n == 0:
return k, np.array([1.0])

probabilities = np.empty(n + 1, dtype=float)
probabilities[0] = math.exp(n * math.log(2.0))

for i in range(n):
probabilities[i + 1] = probabilities[i] * (n i) / (i + 1)

# 修正可能出现的微小浮点误差。
probabilities /= probabilities.sum()
return k, probabilities

def standard_normal_pdf(z: np.ndarray) > np.ndarray:
"""标准正态分布 N(0,1) 的概率密度函数。"""
return np.exp(0.5 * z**2) / math.sqrt(2.0 * math.pi)

def standardized_binomial(n: int) > tuple[np.ndarray, np.ndarray]:
"""
将 Binomial(n, 1/2) 标准化,并把离散概率转换为近似密度。

z = (k – μ) / σ
density ≈ P(X=k) / Δz = P(X=k) * σ
"""
k, probability = binomial_probability(n)

if n == 0:
return np.array([0.0]), np.array([1.0])

mean = n / 2.0
std = math.sqrt(n) / 2.0
z = (k mean) / std
density = probability * std
return z, density

def print_pascal_rows(max_n: int) > None:
"""在终端打印从第 0 行到第 max_n 行的帕斯卡三角形。"""
if max_n < 0:
raise ValueError("max_n 必须是非负整数。")

rows = [" ".join(map(str, pascal_row(n))) for n in range(max_n + 1)]
width = len(rows[1])

for n, row in enumerate(rows):
print(f"n={n:>2}: {row.center(width)}")

def plot_selected_rows(rows: Iterable[int]) > None:
"""绘制若干指定行,并与标准正态分布进行比较。"""
rows = sorted(set(rows))
if not rows or rows[0] < 1:
raise ValueError("用于标准化绘图的 n 必须是正整数。")

figure, axis = plt.subplots(figsize=(11, 7))

z_gaussian = np.linspace(4.5, 4.5, 1000)
axis.plot(
z_gaussian,
standard_normal_pdf(z_gaussian),
linewidth=3,
label="Standard normal distribution",
)

for n in rows:
z, density = standardized_binomial(n)
axis.plot(
z,
density,
marker="o" if n <= 20 else None,
markersize=4,
linewidth=1.8,
label=f"Pascal row n={n}",
)

axis.set_title("Pascal Triangle Coefficients Converging to a Gaussian Distribution")
axis.set_xlabel(r"Standardized position $z=(k-n/2)/\\sqrt{n/4}$")
axis.set_ylabel("Probability density")
axis.set_xlim(4.5, 4.5)
axis.grid(alpha=0.3)
axis.legend()
figure.tight_layout(rect=[0, 0, 1, 0.94])
plt.show()

def plot_original_distribution(n: int) > None:
"""以原始横坐标 k 绘制第 n 行系数归一化后的二项分布。"""
k, probability = binomial_probability(n)

figure, axis = plt.subplots(figsize=(11, 6))
axis.bar(k, probability, width=0.85)

mean = n / 2.0
std = math.sqrt(n) / 2.0
x = np.linspace(max(0.0, mean 4.5 * std), min(float(n), mean + 4.5 * std), 1000)

gaussian_approximation = (
np.exp(0.5 * ((x mean) / std) ** 2)
/ (std * math.sqrt(2.0 * math.pi))
)
axis.plot(x, gaussian_approximation, linewidth=3, label="Gaussian approximation")

axis.set_title(
rf"Normalized Coefficients of $(x+y)^{{{n}}}$: "
rf"$P(X=k)=\\binom{{{n}}}{{k}}/2^{{{n}}}$"
)
axis.set_xlabel("k")
axis.set_ylabel("Probability")
axis.grid(axis="y", alpha=0.3)
axis.legend()
figure.tight_layout()
plt.show()

def animate_convergence(
max_n: int = 100,
interval_ms: int = 100,
save_path: str | None = None,
) > None:
"""逐行绘制 n=1,…,max_n,动态展示其向标准正态分布收敛。"""
if max_n < 1:
raise ValueError("max_n 必须至少为 1。")

figure, axis = plt.subplots(figsize=(11, 7))
z_gaussian = np.linspace(4.5, 4.5, 1000)

axis.plot(
z_gaussian,
standard_normal_pdf(z_gaussian),
linewidth=3,
label="Standard normal distribution",
)
binomial_line, = axis.plot([], [], linewidth=2, marker="o", markersize=3)
title = axis.set_title(
r"Pascal row $n=1$: "
r"$\\binom{n}{k}/2^n \\longrightarrow N(0,1)$",
pad=12,
)

axis.set_xlabel(r"Standardized position $z=(k-n/2)/\\sqrt{n/4}$")
axis.set_ylabel("Probability density")
axis.set_xlim(4.5, 4.5)
axis.set_ylim(0.0, 0.45)
axis.grid(alpha=0.3)
axis.legend()

def update(n: int):
z, density = standardized_binomial(n)
binomial_line.set_data(z, density)
binomial_line.set_marker("o" if n <= 30 else "")
title.set_text(
rf"Pascal row $n={n}$: "
rf"$\\binom{{n}}{{k}}/2^n \\longrightarrow N(0,1)$"
)
return binomial_line, title

animation = FuncAnimation(
figure,
update,
frames=range(1, max_n + 1),
interval=interval_ms,
blit=False,
repeat=True,
)

figure.tight_layout()

if save_path:
try:
animation.save(save_path, writer="pillow", fps=max(1, 1000 // interval_ms))
print(f"动画已保存到:{save_path}")
except Exception as exc:
raise RuntimeError(
"保存 GIF 失败,请先安装 Pillow:pip install pillow"
) from exc
else:
plt.show()

def parse_rows(text: str) > list[int]:
"""把 '2,5,10,30,100' 转换为整数列表。"""
try:
rows = [int(item.strip()) for item in text.split(",") if item.strip()]
except ValueError as exc:
raise argparse.ArgumentTypeError("rows 必须是用逗号分隔的整数。") from exc

if not rows or any(n < 1 for n in rows):
raise argparse.ArgumentTypeError("rows 中的每个 n 都必须是正整数。")
return rows

def main() > None:
parser = argparse.ArgumentParser(
description="可视化帕斯卡三角形系数向正态分布收敛的现象。"
)
parser.add_argument(
"–mode",
choices=["triangle", "selected", "original", "animate"],
default="selected",
help=(
"triangle: 打印帕斯卡三角形;"
"selected: 比较若干行;"
"original: 绘制某一行的原始分布;"
"animate: 动态逐行绘制。"
),
)
parser.add_argument(
"–n",
type=int,
default=100,
help="用于 triangle、original 或 animate 模式的最大阶数,默认 100。",
)
parser.add_argument(
"–rows",
type=parse_rows,
default=[2, 5, 10, 30, 100],
help="selected 模式中的行号,例如:–rows 2,5,10,30,100",
)
parser.add_argument(
"–interval",
type=int,
default=100,
help="动画每帧间隔,单位毫秒,默认 100。",
)
parser.add_argument(
"–save",
type=str,
default=None,
help="动画保存路径,例如:–save pascal_to_gaussian.gif",
)
args = parser.parse_args()

if args.n < 0:
parser.error("–n 不能为负数。")
if args.interval <= 0:
parser.error("–interval 必须大于 0。")

if args.mode == "triangle":
print_pascal_rows(args.n)
elif args.mode == "selected":
plot_selected_rows(args.rows)
elif args.mode == "original":
if args.n < 1:
parser.error("original 模式要求 –n 至少为 1。")
plot_original_distribution(args.n)
elif args.mode == "animate":
if args.n < 1:
parser.error("animate 模式要求 –n 至少为 1。")
animate_convergence(
max_n=args.n,
interval_ms=args.interval,
save_path=args.save,
)

if __name__ == "__main__":
main()

执行指令如下:

python .\\pascal_gaussian.py –mode animate –n 100 –save pascal_to_gaussian.gif

生成的动态图如下所示:

需要注意:并不是帕斯卡三角形中的原始系数直接收敛到正态分布,而是归一化后的系数:

P

(

X

=

k

)

=

(

n

k

)

2

n

P(X=k) = \\frac{\\binom{n}{k}}{2^n}

P(X=k)=2n(kn)

构成参数为

n

n

n

p

=

1

2

p=\\frac{1}{2}

p=21 的二项分布。进一步令

z

=

k

n

2

n

4

,

z = \\frac{k-\\frac{n}{2}}{\\sqrt{\\frac{n}{4}}},

z=4n

k2n,

标准化后的分布会随着

n

n

n 增大趋近标准正态分布

N

(

0

,

1

)

N(0,1)

N(0,1)

还记得《价格猜猜猜》节目里的 Plinko 游戏吗?把球从顶部落下,经过格栅弹跳后最终掉进不同的收集槽里,这种装置有时被称为高尔顿板,德语中称作 Galtonbrett,若将大量珠子撒在布满钉子的格板上,经过弹跳后,它们会逐渐下落并最终形成高斯分布。

帕斯卡三角形正是快速计算多项式展开系数的工具,归根结底,这些系数就是无处不在的二项式系数 — 组合数

C

n

k

C_n^k

Cnk ,我们在概率计算中经常用到它们。

所以如果我想计算从一副 52 张牌中能抽出多少种五张扑克组合,直接用组合数

C

52

5

C_{52}^{5}

C525 就行了,对吧?计算起来非常简单。

而多项式分布则是将其推广到更高维分布的方法,适用于更复杂的纸牌游戏场景,假设现在我要发两副扑克牌,我和朋友一起玩,现在有两副五张牌的手牌,这种情况有多少种可能?最终得到的结果就是多项式分布,其计算过程也相当简便。

3. 定义多项分布

下面我们来推导下,那么有

n

n

n 个物体,划分为

r

r

r 个类别,其规模分别为

n

1

,

n

2

,

,

n

r

n_1,n_2,\\ldots,n_r

n1,n2,,nr ,比如我处理两副牌时,可能会各发五张牌,类似这样的情况,而且顺序不重要。将

n

n

n 个对象划分为

r

r

r 个类别,且不考虑顺序,那么样本总数就是下面这种组合数:

(

n

n

1

n

2

n

r

)

\\binom{n}{n_1n_2 \\ldots n_r}

(n1n2nrn)

接下来我将说明这个符号的定义,

n

1

n

2

n

r

n_1n_2 \\ldots n_r

n1n2nr 并非乘积关系,不是

n

1

×

n

2

×

×

n

r

n_1 \\times n_2 \\times \\ldots \\times n_r

n1×n2××nr 的形式,这并非从

n

n

n 个元素中选取这个大数值的组合,这是一种新的计数记号,明白吗?

其定义方式如下:

(

n

n

1

n

2

n

r

)

=

n

!

n

1

 

!

 

n

2

!

 

 

n

r

!

\\binom{n}{n_1n_2 \\ldots n_r} = \\frac{n!}{n_1 \\ ! \\ n_2! \\ \\cdots \\ n_r!}

(n1n2nrn)=n1 ! n2!  nr!n!

还有一点需要补充说明,这里有个前提条件:这些

n

i

n_i

ni 的总和必须等于

n

n

n ,因此,整副 52 张牌会被分成

r

r

r 手牌,想象一下你在玩黑桃牌戏:整副牌分给四位玩家后,会形成四手牌,所有手牌相加正好是 52 张,也就是说,这里假设

n

1

+

n

2

+

+

n

r

=

n

n_1 + n_2 + \\cdots + n_r = n

n1+n2++nr=n ,对吧?

这与计算从 52 张牌中发出 5 张手牌的组合数略有不同,但原理相通,同样的原理也可用于计算从 52 张牌中抽取 5 张手牌的组合数,这里假设将整个集合

n

n

n 划分为这

r

r

r 个组别,其计算公式如上所示。

4. 公式推导

通过基本原理推导这个公式的过程其实很有帮助,因为这能让你更熟练地掌握这类计算,所以这个公式并非凭空而来,完全可以通过列举所有可能性地方式来推导出这个公式,接下来我们来看看这个公式的推导过程。

这个概率的推导依据是:可能发生的事件总数等于从

n

n

n 个元素中选取

n

1

,

n

2

,

,

n

r

n_1,n_2,\\ldots, n_r

n1,n2,,nr 个元素的组合数。首先分配

n

1

n_1

n1 张牌,有多少种方法可以做到这一点?这就是我们前面提到的

(

n

n

1

)

\\binom{n}{n_1}

(n1n) ,现在我要分配第二组,这就是

(

n

n

1

n

2

)

\\binom{n-n_1}{n_2}

(n2nn1) ,现在剩下

n

n

1

n

2

n-n_1-n_2

nn1n2 张牌,我要用这些来分配

n

3

n_3

n3 ,所以是

(

n

n

1

n

2

n

3

)

\\binom{n-n_1-n_2}{n_3}

(n3nn1n2) ,依次类推,直到最后一项,即:

(

n

n

1

n

2

n

r

n

r

)

\\binom{n-n_1-n_2-\\cdots -n_r}{n_r}

(nrnn1n2nr)

其中每一项的简答排列都可以计算出来,这些本质上都是二项系数:从总数

n

n

n 种抽取

n

1

n_1

n1 张牌的组合数,以此类推,我们可以列出所有这些组合数的计算公式,然后将它们相乘,你会发现这些项会以非常巧妙地方式相互抵消,最终得到下面这个简洁的公式:

(

n

n

1

n

2

n

r

)

=

n

!

n

1

 

!

 

n

2

!

 

 

n

r

!

\\binom{n}{n_1n_2 \\ldots n_r} = \\frac{n!}{n_1 \\ ! \\ n_2! \\ \\cdots \\ n_r!}

(n1n2nrn)=n1 ! n2!  nr!n!

5. 结语

OK,让我们从整体视角来看,这就是所谓的多项系数,利用这个公式可以计算多种概率问题,在工厂生产零件时,若将合格品与不合格品分为两类,分别记为

n

1

n_1

n1

n

2

n_2

n2 ,这种分类情况就符合多项式分布。

通过这个多项式分布,可以计算在采样中出现特定数量不合格品的概率,用这个方法可以计算特定扑克牌型的概率,比如同花顺、四条等组合出现的可能性,能计算的情况非常丰富。

假设总人数为偶数,设为

2

n

2n

2n 人,有多少种方法可以将这些人两两配对?这些人能配成多少对组合?这是道课后习题,你需要针对不同的

n

n

n 值进行计算。

那如果是委员会决策呢?你正在组建一个分委员会,现有七位成员,需组建三个分委员会:两人组、三人组和两人组,从七人中选出这些小组委员会共有多少种方式?

这类问题可以通过多项式分布来计算,它是二项式分布的推广形式,这些二项式系数实在精妙绝伦,它是多项式展开的系数,源自帕斯卡三角形,当

n

n

n 足够大时,最终会收敛于正态分布。

OK,以上就是本讲的全部内容。

我们将在后续课程中演示如何从二项分布推导出正态分布,但我想让大家先对这些概念有个直观认识,因为借助基础的

(

n

r

)

\\binom{n}{r}

(rn) 组合数及其多项式推广,我们就能计算各种有趣事件的概率 — 比如纸牌游戏中的各类情形。

结语

本讲从二项式系数

(

n

r

)

\\binom{n}{r}

(rn) 出发,串联起帕斯卡三角形、多项式展开与高尔顿板,直观展示了归一化后的二项式系数随

n

n

n 增大逐渐收敛于高斯分布的过程 — 这为中心极限定理埋下了伏笔。在此基础上,我们将二项式系数推广为多项分布:

(

n

n

1

n

2

n

r

)

=

n

!

n

1

!

 

n

2

!

 

 

n

r

!

\\binom{n}{n_1 n_2 \\ldots n_r} = \\frac{n!}{n_1! \\ n_2! \\ \\cdots \\ n_r!}

(n1n2nrn)=n1! n2!  nr!n!

这一公式是解决 “将

n

n

n 个对象划分为

r

r

r 个无序组别” 的通用计数工具,可广泛应用于扑克牌型、委员会分组、质量抽检等场景。掌握从二项到多项的推广逻辑,就掌握了一套处理复杂组合计数问题的核心方法论 🤗。

参考

  • https://www.youtube.com/playlist?list=PLMrJAkhIeNNR3sNYvfgiKgcStwuPSts9V
赞(0)
未经允许不得转载:171主机测评 » Steve Brunton | Probability Bootcamp | 笔记 | 第一部分:概率导论 | Lecture 7 | 二项分布与多项分布
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址