Numpy的eig/eigh函数对于一个对称正半定矩阵会给出负值。

6
以下是经过GCN处理的CIFAR数据集代码:
xtx = np.dot(dataset.train_data[i].transpose(), dataset.train_data[i])
e, q = np.linalg.eigh(xtx)
print(np.max(e), np.min(e))

产生以下输出:
2.65138e+07 -0.00247511

考虑到xtx是对称半正定的,这种情况不太一致。我猜可能是应用GCN的结果,但是最小特征值甚至与0相去甚远?

更新:因此,我的矩阵条件数为8.89952e+09。我之前忘记了取出平均值,现在最大特征值约为573,而最小特征值为-7.14630133e-08。我的问题是我正在尝试进行ZCA。在这种情况下,我该怎么办?向xtx添加对角线扰动还是对特征值进行操作?


xtx 的数据类型是什么(检查 xtx.dtype)?它是单精度 (np.float32) 吗? - Warren Weckesser
如果你考虑到最大和最小特征值之间有10个数量级,我会说它非常接近于零。正如@WarrenWeckesser所指出的那样,这在32位浮点数的误差范围内(平均精度为7-9位数字)。 - maxymoo
请发布 numpy.linalg.cond(xtx) 的结果。 - gg349
@maxymoo,您假设所有特征值具有相同的精度,这当然取决于eigh的工作方式。我对此表示怀疑,并尝试在LAPACK代码中快速查找,但没有成功。 - gg349
我已经更新了问题。 - Alex Botev
1个回答

0
如果您的特征值跨越多个数量级,您可以使用SVD分解,使得X.T @ X = (U @ S @ V.T).T @ (U @ S @ V.T) = V @ S @ S @ V.T
_, s, v = np.linalg.svd( dataset.train_data[i] )
e = s[:len(v)]**2

现在保证e是正数,并且假设你计算出的高奇异值大约为5e3,而舍入误差限制了其他SVD的精度在1e-7左右,这意味着当你计算e[1] = s[1]**2时,实际上会得到一个数量级为1e-14的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接