【问题标题】:How to properly sample from a numpy.random.multivariate_normal (positive-semidefinite covariance matrix issue)如何从 numpy.random.multivariate_normal 正确采样(正半定协方差矩阵问题)
【发布时间】:2017-09-28 03:44:57
【问题描述】:

我希望从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(),进行特征分解以获得特征向量和值,裁剪值,然后将这些矩阵相乘以获得新的协方差矩阵,但这似乎很不稳定。这是在实践中完成的,还是有更好的方法?

【问题讨论】:

    标签: pandas numpy numpy-random


    【解决方案1】:

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

    In [71]: np.linalg.eigvals(np.cov(np.random.random((5,5))))
    Out[71]: 
    array([  1.87557170e-01,   9.98250875e-02,   6.85211153e-02,
             1.01062281e-02,  -5.99164839e-18])
    

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

    因此,在您的情况下,我会验证违规的幅度很小,然后剪辑为零。

    【讨论】:

    • 感谢您的回复@DSM。我不确定我是否完全理解:我已经验证了负特征值很小,但现在我知道了,如何获得一个具有 0 个特征值而不是微小的负值的协方差矩阵?
    猜你喜欢
    • 2017-03-27
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多