一、算法原理
1.1 随机向量
随机向量是定义在同一空间上的随机变量的列表。我们一般用一个的向量来表示。
的平均值向量为
,其中
;
的协方差矩阵为
,
。
1.2 线性变换
被称为对进行线性变换。其中,
是一个
的矩阵,
是一个
的向量。
在线性变换过程中,我们可以得到:
根据协方差矩阵的性质,矩阵对称,并且主对角线上的元素都得非负,这意味着
,即协方差矩阵半正定。
1.3 多元正态分布向量
如果向量中的元素都独立同分布于标准正态分布,那么
可以称之为多元正态分布向量,则
为零向量,
为单位矩阵。如果我们要根据平均值向量和协方差矩阵来生成多元正态分布向量的话,根据
我们令为平均值向量,根据
解出,便可以计算出随机多元正态分布向量了。
二、代码实现
- MVN.py
- main.py
MVN.py
import numpy as np
class MVN:
def __init__(self, mean, cov, size=None):
"""
generate multivariate normal random vectors
:param mean: list[int], mean of components of the vector in the distribution we need
:param cov: list[list[int]], covariance matrix of the distribution we need
:param size: int or tuple of ints, shape of the output
"""
self.mean = mean
self.cov = cov
if size is None:
self.size = len(mean)
elif type(size) == int:
self.size = (size,) + (len(mean),)
else:
self.size = size + (len(mean),)
def _preprocess_mean(self):
if self.mean.shape[0] != 1:
self.mean.reshape(1, -1)
@staticmethod
def Cholesky(matrix):
w = matrix.shape[0]
G = np.zeros((w, w))
for i in range(w):
G[i, i] = (matrix[i, i] - np.dot(G[i, :i], G[i, :i].T)) ** 0.5
for j in range(i + 1, w):
G[j, i] = (matrix[j, i] - np.dot(G[j, :i], G[i, :i].T)) / G[i, i]
return G
def _preprocess_cov(self):
if self.cov.shape[0] != self.cov.shape[1]:
raise
eigenvalue, _ = np.linalg.eig(self.cov)
for i in eigenvalue:
if i < 0:
raise
def get_vector(self):
Z = np.random.standard_normal(self.size)
vector = np.random.normal(self.mean, 0, self.size)
A = self.Cholesky(np.array(self.cov))
X = np.matmul(Z, A.T) + vector
return X
main.py
from MVN import MVN
a = MVN([1, 2, 3], [[1, 0, 0], [0, 1, 0], [0, 0, 1]], (1, 2, 3))
c = a.get_vector()
print(c)
print(c.shape)
运行结果:
三、参考资料
1. Random Multivariate Normal Vectors
2. Data 140 Textbook (23.2. Multivariate Normal Vectors)