python | numpy小记(九):理解 NumPy 中的 `np.random.multinomial`
python | numpy小记(九):理解 NumPy 中的 `np.random.multinomial`
Python np.random.multinomial 全面详解与实例
在 Python 数据分析和仿真中,我们经常会遇到多项分布(Multinomial Distribution)的采样需求,比如掷骰子统计各个点数出现次数、分类任务的类别计数等。numpy 提供了一个非常方便的函数——np.random.multinomial,可以直接完成这类任务。
一、函数简介
np.random.multinomial(n, pvals, size=None)
参数说明
n:试验总次数(非负整数)。pvals:概率向量(长度 K K K,非负且和为 1,可以有某些为 0)。size:可选,重复试验次数。如果设为 m m m,返回形状为(m, K)的二维数组。
返回值
- 长度为 K K K 的整数数组,表示每个类别被抽到的次数,且总和等于
n。 - 如果指定
size,返回二维数组,每一行都是一次实验结果。
二、数学原理
多项分布可以看作二项分布的推广:
假设有 $K$ 种可能的类别 C 1 , C 2 , … , C K {C_1, C_2, \dots, C_K} C1,C2,…,CK,每次实验选择其中一个类别,且概率分别为 p 1 , p 2 , … , p K p_1, p_2, \dots, p_K p1,p2,…,pK,那么 n n n 次实验的结果是一个长度为 K K K 的计数向量:
X ∼ M u l t i n o m i a l ( n , p ) X \sim \mathrm{Multinomial}(n, \mathbf{p}) X∼Multinomial(n,p)
- 期望:
E [ X i ] = n ⋅ p i \mathbb{E}[X_i] = n \cdot p_i E[Xi]=n⋅pi
- 方差:
V a r ( X i ) = n ⋅ p i ⋅ ( 1 − p i ) \mathrm{Var}(X_i) = n \cdot p_i \cdot (1 - p_i) Var(Xi)=n⋅pi⋅(1−pi)
- 协方差:
C o v ( X i , X j ) = − n ⋅ p i ⋅ p j , i ≠ j \mathrm{Cov}(X_i, X_j) = -n \cdot p_i \cdot p_j, \quad i \neq j Cov(Xi,Xj)=−n⋅pi⋅pj,i=j
当 K = 2 K=2 K=2 时,多项分布退化为二项分布。
三、使用示例
1. 掷骰子 100 次
import numpy as np
np.random.seed(0)
counts = np.random.multinomial(100, [1/6] * 6)
print(counts) # 每个点数的出现次数
print("总和:", counts.sum())
2. 重复实验,观察均值
exp = np.random.multinomial(100, [1/6] * 6, size=1000)
print(exp.mean(axis=0)) # 应接近 100/6 ≈ 16.67
3. n=1 时的 One-hot 抽样
one_hot = np.random.multinomial(1, [0.7, 0.2, 0.1])
print(one_hot) # 类似 [1, 0, 0] 或 [0, 1, 0]
4. 概率不归一化,手动归一
p = np.array([2, 1, 1], dtype=float)
p /= p.sum()
result = np.random.multinomial(20, p)
print(result)
5. size 复用同一 pvals
P = np.array([[0.7, 0.3], [0.4, 0.6]])
out = np.vstack([np.random.multinomial(50, p) for p in P])
print(out)
四、常见问题(FAQ)
-
pvals必须和为 1 吗?
是的(允许微小浮点误差),否则会报错。 -
pvals可以有 0 吗?
可以,该类别的计数几乎总是 0。 -
size和n的区别?n是一次实验的总次数。size是重复实验的次数。
-
和
np.random.choice的区别?choice返回的是样本序列。multinomial返回的是各类别的计数结果。
五、小结
np.random.multinomial是模拟多类别实验(如掷骰子、抽签、分类统计)的利器。- 使用时要保证概率向量
pvals的和为 1。 - 返回的计数向量总和一定是
n。 - 当类别数为 2 时,相当于二项分布。
建议在新项目中使用
np.random.default_rng().multinomial(),以便获得更好的随机数可控性。
更多推荐
所有评论(0)