如何从numpy.random.multivariate_normal(正半定的协方差矩阵问题)中正确采样

时间:2017-04-30 13:39:07

标签: pandas numpy numpy-random

我希望能够产生新的"假的"来自我已经使用numpy.random.multivariate_normal的数据的数据。

在n x d pandas DataFrame中有n个样本和d个特征:

means = data.mean(axis=0)
covariances = data.cov()
variances = data.var()
means.shape, covariances.shape, variances.shape

>>> ((16349,), (16349, 16349), (16349,))

这看起来很好,但协方差矩阵covariances不是半正定的,这是numpy.random.multivariate_normal的要求。

x = np.linalg.eigvals(covariances)

np.all(x >= 0)
>>> False

len([y for y in x if y < 0])  # negative eigenvalues
>>> 4396

len([y for y in x if y > 0])  # positive eigenvalues
>>> 4585

len([y for y in x if y == 0])  # zero eigenvalues.
>>> 7368

然而,Wikipedia says

  

此外,每个协方差矩阵都是正半正定的。

这让我想知道pandas.DataFrame.cov是否能为您提供真正的协方差矩阵。 Here's the function's implementation.似乎主要推迟到numpy.cov,它似乎也承诺了一个协方差矩阵。

有人可以为我清楚吗?为什么pandas.DataFrame.covs()不是半正定的?

更新了问题:

从第一个答案看,似乎所有的负特征值都很小。该答案的作者建议剪切这些特征值,但我仍然不清楚如何用这些信息明智地生成一个合适的协方差矩阵。

我可以想象使用pd.DataFrame.cov(),进行特征分解以获得特征向量和值,剪切值,然后将这些矩阵相乘以获得新的协方差矩阵,但这似乎非常不稳定。这是在实践中完成,还是有更好的方法?

1 个答案:

答案 0 :(得分:1)

可能发生的事情是,结果 正半定,在计算的准确性范围内。例如:

JOIN

具有负特征值,但幅度很小。

所以,在你的鞋子里,我要确认违规的程度很小,然后剪辑为零。