行列式非零时无法计算矩阵逆

机器算法验证 r 回归 矩阵 线性代数 逆矩阵
2022-04-01 08:11:30

当我看到一些奇怪的事情时,我正试图在R中计算 OLS 回归。当且仅当行列式为 0 时方阵的逆不存在。此外,矩阵必须是满秩的。

所以不确定以下如何可能:

> dim(X)
[1] 20000    51
> det(t(X) %*% X)
[1] 3.863823e+161 #non-zero 

> solve(t(X) %*% X)
Error in solve.default(t(X) %*% X) :
system is computationally singular: reciprocal condition number = 3.18544e-17 

当我们知道行列式不为零时,为什么在尝试计算逆时solve()会抛出错误?我在这里想念什么?

检查矩阵是否具有满秩:

> qr(t(X) %*% X)$rank
[1] 51

但是为了进一步测试,我将其中一个 X 列重新分配给另一个相同的值:

> X[,2] = X[,3]

因此,X 矩阵的两列现在是相同的。

> qr(t(X) %*% X)$rank
[1] 50

我们现在可以确认X'X矩阵不是满秩的。

> det(t(X) %*% X)
[1] 1.634637e+138

但是行列式还是不等于0?这怎么可能,我错过了什么?

4个回答

我的猜测是数字太大(行列式很大)并且您遇到了计算问题。

我能够通过运行复制您的错误:

> X <- cbind(1,exp(rexp(100,rate=1/50)))
> det(t(X) %*% X)
[1] 5.156683e+126
> solve(t(X) %*% X)
> Error in solve.default...

问题是数字。您可以通过对矩阵进行一些转换来解决它,使数字更小,但允许您计算出是什么。X(XX)1

行列式的方法不同于矩阵求逆的方法。行列式使用较低的上分解。产品的行列式是行列式的乘积。L 大约非常小,U 大约非常大。在 16 点位精度下,非常小的数字舍入太大,当它实际上为 0 时产品会爆炸。

我会相信解决命令。矩阵是奇异的。r 帮助说“你不应该使用 det 来解决任何问题”。

看起来这里有一个类似的问题,我建议进行类似的探索。

你的矩阵的条件数是多少?您的矩阵可能几乎是奇异的,尽管我怀疑这不太可能。

的规模如何它的最大值是多少?由于缩放问题,您的行列式可能会溢出,在这种情况下,您可以将矩阵的值减少某个常数因子。X

我也同意评论者的观点——无需显式反转矩阵来解决线性回归。

好的,我认为这det是一个误导。

的特征值的乘积为零,则“真”行列式为零,如果单个特征值之一为零,则会发生这种情况。给定计算机算术,如果单个计算的特征值之一恰好为零,或者如果它们中的足够小以至于计算的乘积下溢,则行列式将被计算为零。下溢双精度需要很多,所以我们说的真的很小。没有下溢。XTX.Machine$double.eps^20

如果单个特征值之一为零,则矩阵是真正不可逆的。给定计算机算法,如果估计的条件数(最大和最小特征值之比)太大,则逆将被检测为数值奇异。默认阈值是条件数小于机器 epsilon 的倒数,仅为因此,放弃使下溢为零的矩阵容易得多。2522×1016solvedet

@John 的答案给出了一个秩为 2 的矩阵,该矩阵具有非零计算行列式,因为非零特征值很大,并且可能零特征值不完全为零。你的例子不是那样的,因为它会以无限精度获得满级,但它可能是相似的。最小特征值不是零,而是小于机器 epsilon 乘以最大特征值。

最后一点,当solvedet只是使用 Lapack 时,就像所有明智的人所做的那样,功能喜欢lmglm不喜欢 - 他们对奇异矩阵有更严格的容忍度,因为通常是双精度设计矩阵,有人没有故意设置为数值分析练习要么实际上是奇异的,要么具有比机器 epsilon 大得多的倒数条件数。如果它确实落入差距,用户可能需要知道。容差 (in qr(,LAPACK=FALSE)) 为因此,当仍然有效时,计算出的数字排名可能为零,这是故意的,并且有充分的理由。(我的意思是,除了你可能107qrsolveqrX而不是 )XTX