从多变量正态分布中抽样一个以上的元素

Sample more than one element from multivariable normal distribution

我有一个大小为 n*m 的二维均值矩阵,其中 n 是样本数,m 是数据的维度。 我还有 nm*m 的矩阵,即 sigma 是我的 n*m*m 形状的方差矩阵。 我希望从上面的分布中抽取 n 个样本,这样 x_i~N(mean[i], sigma[i])。 在 numpy 或任何其他标准库 w/o 运行 for 循环中有什么方法可以做到这一点?

我认为唯一的选择是使用 np.random.multivariate_normal() 将均值矩阵展平为一个向量,并将 3D sigma 展平为 2D 块对角矩阵。当然,之后要重塑。但这意味着我们将使用形状为 (n*m)*(n*m) 的 sigma 样本,这很容易变得非常大,并且仅计算和分配该矩阵(如果可能)可能比 for 循环中的 运行 花费更长的时间。

在我的特定任务中,现在 Sigma 是所有样本的相同矩阵,这意味着我可以在 m*m 中表示 Sigma,并且它对于所有 n 个点都是相同的。但我对通用解决方案感兴趣。

感谢您的帮助。

没有可测试的代码很难判断,但这应该很接近:

A = numpy.linalg.cholesky(sigma)                # => shape (n, m, m), same as sigma
Z = np.random.normal(size = (n, m))             # shape (n, m)
X = np.einsum('ijk, ik -> ij', A, Z) + mean     # shape (n, m)

发生了什么:

我们根据概述的标准 Cholesky 分解方法手动对多元正态分布进行采样 hereA 的构建使得 A@A.T = sigma。然后 X(多元正态)可以由 A 和单变量正态 N(0, 1) 向量 Z 的点积形成, 加上 mean.

你在第一个(index = 0,'i' in the einsum)轴的整个计算过程中保持无关维度,同时收缩最后一个('k')轴,形成点积。