我想用下面的代码计算一批特征向量的协方差矩阵(这里用torch.randn代替):
import torch
a = torch.randn(64, 512)
cov_mat = (a.T @ a) / (a.size(0) - 1)
所产生的cov_mat是对称的和半正定的。因此,我通过添加cov_mat = (cov_mat + cov_mat.T) / 2
更改了上面的子句
现在协方差矩阵是对称的,但仍然不是半正定的。我试过手电筒,但还是不行。是不是和精确度有关?
以下是具体版本:
Python3.7
PyTorch1.8.1
1条答案
按热度按时间fzsnzjdm1#
我得到了类似的问题,结论确实是这是一个精度问题。当我执行你的代码时(没有你的修改),我观察到cov_mat几乎是对称的,有一个大约1 e-6的错误。这实际上是预期的,如here所解释的:
浮点精度限制了您可以准确依赖的位数。torch.float32的精度在6到7位之间,与指数无关,即对于<1 e-6的值,预计会出现精度问题。类似地,torch.float64对于<1 e-15的值也会有精度问题。
如果你真的需要更高的精度,你可以使用torch.float64:
虽然使用
cov_mat = (cov_mat + cov_mat.T) / 2
的解决方案也可以使用float 32实现类似的精度(在矩阵完全对称的意义上),但它会使矩阵“更少”psd。不幸的是,无论你做什么,你总是会受到精度误差的影响(float 32为1 e-6,float 64为1 e-15)。因此,我们可以看到协方差矩阵的特征值可能略低于零。我尝试手动将特征值设置为0,但仍然存在错误。
TL;DR我的最终建议是:
*如果你绝对需要矩阵是psd,你可以这样做:
c += 1e-12 * torch.eye(a.size(1))
(如果你不需要它,我不推荐它,因为它修改了矩阵)希望对你有帮助!