如何从 numpy.random.multivariate_normal 中正确采样(半正定协方差矩阵问题)
How to properly sample from a numpy.random.multivariate_normal (positive-semidefinite covariance matrix issue)
我希望根据 numpy.random.multivariate_normal
已有的数据生成新的 "fake" 数据。
在 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
In addition, every covariance matrix is positive semi-definite.
这让我想知道 pandas.DataFrame.cov gets you a real covariance matrix. Here's the function's implementation. It seems to mostly defer to numpy.cov 是否也能保证协方差矩阵。
有人可以帮我解决这个问题吗?为什么 pandas.DataFrame.covs()
不是半正定的?
更新问题:
从第一个答案来看,似乎所有的负特征值都很小。该答案的作者建议剪切这些特征值,但我仍然不清楚如何使用这些信息明智地生成适当的协方差矩阵。
我可以想象使用 pd.DataFrame.cov()
,进行特征分解以获得特征向量和值,裁剪值,然后将这些矩阵相乘以获得新的协方差矩阵,但这似乎很不稳定。这是在实践中完成的,还是有更好的方法?
可能发生的情况是结果是半正定的,在计算的精度范围内。例如:
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])
具有负特征值,但量级很小。
所以从你的角度来看,我会验证违规的严重程度很小,然后将其削减为零。
我希望根据 numpy.random.multivariate_normal
已有的数据生成新的 "fake" 数据。
在 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
In addition, every covariance matrix is positive semi-definite.
这让我想知道 pandas.DataFrame.cov gets you a real covariance matrix. Here's the function's implementation. It seems to mostly defer to numpy.cov 是否也能保证协方差矩阵。
有人可以帮我解决这个问题吗?为什么 pandas.DataFrame.covs()
不是半正定的?
更新问题:
从第一个答案来看,似乎所有的负特征值都很小。该答案的作者建议剪切这些特征值,但我仍然不清楚如何使用这些信息明智地生成适当的协方差矩阵。
我可以想象使用 pd.DataFrame.cov()
,进行特征分解以获得特征向量和值,裁剪值,然后将这些矩阵相乘以获得新的协方差矩阵,但这似乎很不稳定。这是在实践中完成的,还是有更好的方法?
可能发生的情况是结果是半正定的,在计算的精度范围内。例如:
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])
具有负特征值,但量级很小。
所以从你的角度来看,我会验证违规的严重程度很小,然后将其削减为零。