根据定义,具有零行列式的方阵不应是可逆的。然而,由于某种原因,在生成协方差矩阵之后,我成功地得到了它的倒数,但是采用协方差矩阵的行列式最终得到0.0的输出。
可能出现什么问题?我不应该相信行列式输出,还是应该不相信逆协方差矩阵?或两者兼而有之?
我的代码片段:
cov_matrix = np.cov(data)
adjusted_cov = cov_matrix + weight*np.identity(cov_matrix.shape[0]) # add small weight to ensure cov_matrix is non-singular
inv_cov = np.linalg.inv(adjusted_cov) # runs with no error, outputs a matrix
det = np.linalg.det(adjusted_cov) # ends up being 0.0
答案 0 :(得分:3)
numerical inversion of matrices不涉及计算行列式。 (Cramer's formula用于逆矩阵对于大矩阵是不实用的。)因此,行列式求值为0(由于浮点精度不足)的事实不是矩阵求逆程序的障碍。
关注BobChao87的评论,这是一个简化的测试用例(Python 3.4控制台,numpy作为np导入)
A = 0.2*np.identity(500)
np.linalg.inv(A)
输出:主对角线上有5的矩阵,它是A的正确倒数。
np.linalg.det(A)
输出:0.0,因为行列式(0.2 ^ 500)太小而无法以双精度表示。
一种可能的解决方案是pre-conditioning(这里只是重新缩放):在计算行列式之前,将矩阵乘以一个因子,使其条目平均接近1。在我的示例中,np.linalg.det(5*A)
返回1.
当然,这里使用因子5是作弊,但np.linalg.det(3*A)
也返回非零值(约1.19e-111)。如果你试图通过适度正整数运行np.linalg.det(2**k*A)
,你可能会遇到一个返回非零的整数。然后你就会知道原始矩阵的行列式大约是输出的2 **( - k * n)倍,其中n是矩阵大小。