使用标准正态分布生成任意 n 维正态分布
在研究概率论和多元统计时,如何从 n 个独立标准正态分布变量生成任意给定参数的 n 维正态分布,是一个十分常见的问题。本文通过理论推导和实现细节,完整展示这个过程。
问题描述
设
- 我们有 n n n 个独立的标准正态分布随机变量: ∀ i ∈ { 1 , 2 , … , n } A i ∼ N ( 0 , 1 ) \forall i \in \{1, 2, \dots, n\} \quad A_i \sim N(0, 1) ∀i∈{1,2,…,n}Ai∼N(0,1),且 Σ A = I \Sigma_A = \mathbf{I} ΣA=I(即: n n n 个随机变量 A n A_n An 独立同分布,服从标准正态分布)
- 我们的目标是生成满足以下要求的 n 维正态分布随机变量
X
⃗
:
\vec{X} :
X:
X ⃗ ∼ N ( μ X , Σ X ) , \begin{equation} \vec{X} \sim N\left(\mu_X, \Sigma_X\right), \end{equation} X∼N(μX,ΣX),
其中, μ X \mu_X μX 是目标分布的均值向量, Σ X \Sigma_X ΣX 是目标分布的协方差矩阵。
理论推导
假设我们有一个列向量
A
⃗
\vec{A}
A,其中包含
n
n
n 个独立的标准正态分布随机变量:
A
⃗
=
(
A
1
A
2
⋮
A
n
)
\begin{equation} \vec{A} = \begin{pmatrix} A_1 \\ A_2 \\ \vdots \\ A_n \end{pmatrix} \end{equation}
A=
A1A2⋮An
我们希望通过某种方式将
A
⃗
\vec{A}
A 转换为具有期望值
μ
X
\mu_X
μX 和协方差矩阵
Σ
X
\Sigma_X
ΣX 的 n 维正态分布
X
⃗
\vec{X}
X。令:
X
⃗
=
M
⋅
A
⃗
+
μ
⃗
,
\begin{equation} \vec{X} = \mathbf{M} \cdot \vec{A} + \vec{\mu}, \end{equation}
X=M⋅A+μ,
其中,
M
\mathbf{M}
M 是一个待定的矩阵,满足我们希望从标准正态分布得到目标协方差矩阵的要求。
μ
⃗
\vec{\mu}
μ 是一个待定的向量。
显然 E ( M ⋅ A ⃗ ) = M ⋅ E ( A ⃗ ) = 0 \mathbb{E}(\mathbf{M} \cdot \vec{A}) = \mathbf{M} \cdot \mathbb{E}(\vec{A}) = \mathbf{0} E(M⋅A)=M⋅E(A)=0
则 μ X = E [ M ⋅ A ⃗ ] + μ ⃗ = μ ⃗ \mu_X = \mathbb{E}[\mathbf{M} \cdot \vec{A}] + \vec{\mu} = \vec{\mu} μX=E[M⋅A]+μ=μ
又,
Σ
X
=
Σ
M
⋅
A
⃗
=
E
(
(
M
⋅
A
⃗
−
E
(
M
⋅
A
⃗
)
)
⋅
(
M
⋅
A
⃗
−
E
(
M
⋅
A
⃗
)
)
T
)
=
E
(
(
M
⋅
A
⃗
)
⋅
(
M
⋅
A
⃗
)
T
)
=
E
(
M
⋅
(
A
⃗
⋅
A
⃗
T
)
⋅
M
T
)
=
M
⋅
E
(
(
A
⃗
−
0
)
⋅
(
A
⃗
−
0
)
T
)
⋅
M
T
=
M
⋅
E
(
(
A
⃗
−
E
(
A
⃗
)
)
⋅
(
A
⃗
−
E
(
A
⃗
)
)
T
)
⋅
M
T
=
M
⋅
Σ
A
⋅
M
T
\begin{align*} \Sigma_X &= \Sigma_{\mathbf{M} \cdot \vec{A}} \\ &= \mathbb{E}((\mathbf{M} \cdot \vec{A} - \mathbb{E}(\mathbf{M} \cdot \vec{A})) \cdot (\mathbf{M} \cdot \vec{A} - \mathbb{E}(\mathbf{M} \cdot \vec{A}))^T) \\ &= \mathbb{E}((\mathbf{M} \cdot \vec{A}) \cdot (\mathbf{M} \cdot \vec{A})^T) \\ &= \mathbb{E}(\mathbf{M} \cdot (\vec{A} \cdot \vec{A}^T) \cdot \mathbf{M}^T)\\ &= \mathbf{M} \cdot \mathbb{E}((\vec{A} - \mathbf{0}) \cdot (\vec{A} - \mathbf{0})^T) \cdot \mathbf{M}^T \\ &= \mathbf{M} \cdot \mathbb{E}((\vec{A} - \mathbb{E}(\vec{A})) \cdot (\vec{A} - \mathbb{E}(\vec{A}))^T) \cdot \mathbf{M}^T \\ &= \mathbf{M} \cdot \Sigma_A \cdot \mathbf{M}^T \end{align*}
ΣX=ΣM⋅A=E((M⋅A−E(M⋅A))⋅(M⋅A−E(M⋅A))T)=E((M⋅A)⋅(M⋅A)T)=E(M⋅(A⋅AT)⋅MT)=M⋅E((A−0)⋅(A−0)T)⋅MT=M⋅E((A−E(A))⋅(A−E(A))T)⋅MT=M⋅ΣA⋅MT
而
Σ
A
=
I
\Sigma_A = \mathbf{I}
ΣA=I,则
Σ
X
=
M
⋅
M
T
\Sigma_X = \mathbf{M} \cdot \mathbf{M}^T
ΣX=M⋅MT
得到方程:
{
μ
⃗
=
μ
X
M
⋅
M
T
=
Σ
X
\begin{equation} \begin{cases} \vec{\mu} = \mu_X \\ \mathbf{M} \cdot \mathbf{M}^T = \Sigma_X \end{cases} \end{equation}
{μ=μXM⋅MT=ΣX
那么 M \mathbf{M} M 就可以通过对 Σ X \Sigma_X ΣX 进行 Cholesky 分解得到。
代码实现
以下是使用 python
的实现代码
import torch
torch.manual_seed(42) # 固定随机数种子使实验结果可重复
def randn_nD(N: int, /, mu: torch.Tensor, Sigma: torch.Tensor) -> torch.Tensor:
"""
生成符合指定均值和协方差矩阵的 n 维正态分布数据。
参数:
N (int): 数据点的数量
mu (torch.Tensor): 均值向量
Sigma (torch.Tensor): 协方差矩阵
返回:
torch.Tensor: 生成的 n 维正态分布数据,形状为 (N, n)
"""
dim = mu.shape[0]
# 参数校验
if Sigma.shape != (dim, dim):
raise ValueError("协方差矩阵的形状与均值向量形状不符。")
if torch.det(Sigma) <= 0:
raise ValueError("协方差矩阵 Sigma 必须是正定矩阵。")
if not torch.all(Sigma == Sigma.T):
raise ValueError("协方差矩阵必须是对称矩阵。")
A = torch.randn(N, dim)
M = torch.linalg.cholesky(Sigma)
# (M @ A.T + mu').T = A @ M.T + mu'.T = A @ M.t + mu
return A @ M.T + mu
# 数据组数
N = 10000
# 目标分布参数
mu = torch.FloatTensor([3, 1])
Sigma = torch.FloatTensor([[2 ** 2, 0.99 * 2 * 3], [0.99 * 2 * 3, 3 ** 2]])
data = randn_nD(N, mu, Sigma)
# 提取 X 和 Y
X = data[:, 0] # 提取第一列,表示 X 数据
Y = data[:, 1] # 提取第二列,表示 Y 数据
# 验证
mean_generated = torch.mean(data, dim=0)
cov_generated = torch.cov(data.T)
corr_matrix = torch.corrcoef(data.T)
print(f"生成数据的均值:\n{mean_generated}")
print(f"生成数据的协方差矩阵:\n{cov_generated}")
print(f"生成数据的相关系数矩阵:\n{corr_matrix}\n")
输出为
生成数据的均值:
tensor([3.0171, 1.0295])
生成数据的协方差矩阵:
tensor([[4.0617, 6.0300],
[6.0300, 9.1299]])
生成数据的相关系数矩阵:
tensor([[1.0000, 0.9902],
[0.9902, 1.0000]])
可视化
总结
本文从理论到实践,完整地展示了如何通过 n 个独立标准正态分布变量生成具有指定参数的 n 维正态分布。具有一定使用价值,可以用于 线性规划 的教学数据生成。