【问题标题】:Calculate inverse of a non-square matrix in R计算R中非方阵的逆
【发布时间】:2014-02-17 07:11:54
【问题描述】:

我是 R 语言的新手,并试图找出如何计算非正方形矩阵的逆矩阵。 (非方形?不规则?我不确定术语是否正确)。

根据我的书和快速的谷歌搜索(参见source),我发现您可以使用solve(a) 来查找矩阵的逆如果 a 是正方形。

据我了解,我创建的矩阵不是正方形:

  > matX<-matrix(c(rep(1, 8),2,3,4,0,6,4,3,7,-2,-4,3,5,7,8,9,11), nrow=8, ncol=3);
  > matX

       [,1] [,2] [,3]
  [1,]    1    2   -2
  [2,]    1    3   -4
  [3,]    1    4    3
  [4,]    1    0    5
  [5,]    1    6    7
  [6,]    1    4    8
  [7,]    1    3    9
  [8,]    1    7   11
  > 

是否有解决这种大小的矩阵的功能,或者我必须对每个元素做些什么?因为solve() 函数给出了这个错误:

  Error in solve.default(matX) : 'a' (8 x 3) must be square

我试图从上面的矩阵中得到的计算是:(matX'matX)^-1

提前致谢。

【问题讨论】:

  • 参考你的最后一行,试试:solve(t(matX) %*% matX)

标签: r matrix matrix-inverse


【解决方案1】:

ginv MASS 包中的ginv 将给出矩阵的广义逆。将原始矩阵乘以它会得到恒等式:

library(MASS)
inv <- ginv(matX)

# test it out
inv %*% matX
##               [,1]         [,2]          [,3]
## [1,]  1.000000e+00 6.661338e-16  4.440892e-15
## [2,] -8.326673e-17 1.000000e+00 -1.110223e-15
## [3,]  6.938894e-17 8.326673e-17  1.000000e+00

正如 cmets 中所建议的,这可以使用 zapsmall 以更好的方式显示:

zapsmall(inv %*% matX)
##      [,1] [,2] [,3]
## [1,]    1    0    0
## [2,]    0    1    0
## [3,]    0    0    1

matX'matX 的倒数现在是:

tcrossprod(inv)
##              [,1]         [,2]         [,3]
## [1,]  0.513763935 -0.104219636 -0.002371406
## [2,] -0.104219636  0.038700372 -0.007798748
## [3,] -0.002371406 -0.007798748  0.006625269

solve 但是,如果您的目标是计算 matX'matX 的倒数,那么您一开始就不需要它。这不涉及 MASS:

solve(crossprod(matX))
##              [,1]         [,2]         [,3]
## [1,]  0.513763935 -0.104219636 -0.002371406
## [2,] -0.104219636  0.038700372 -0.007798748
## [3,] -0.002371406 -0.007798748  0.006625269

svd也可以使用svd,同样不需要MASS:

with(svd(matX), v %*% diag(1/d^2) %*% t(v))
##              [,1]         [,2]         [,3]
## [1,]  0.513763935 -0.104219636 -0.002371406
## [2,] -0.104219636  0.038700372 -0.007798748
## [3,] -0.002371406 -0.007798748  0.006625269

添加了一些附加信息。

【讨论】:

  • zapsmall 可能会更清楚地显示inv %*% matX 的结果...
  • 哦酷 :D 感谢您抽出宝贵时间回答 :D 太好了。
  • 对于 svd 解决方案,为什么要对角矩阵求平方?诊断(1/d^2)
  • @user1143669,请阅读问题的倒数第二行。
【解决方案2】:

您可以执行所谓的“Moore–Penrose pseudoinverse”。这是一个函数exp.mat,它将为您执行此操作。还有一个示例概述了它的用法here

exp.mat():

#The exp.mat function performs can calculate the pseudoinverse of a matrix (EXP=-1)
#and other exponents of matrices, such as square roots (EXP=0.5) or square root of 
#its inverse (EXP=-0.5). 
#The function arguments are a matrix (MAT), an exponent (EXP), and a tolerance
#level for non-zero singular values.
exp.mat<-function(MAT, EXP, tol=NULL){
    MAT <- as.matrix(MAT)
    matdim <- dim(MAT)
    if(is.null(tol)){
        tol=min(1e-7, .Machine$double.eps*max(matdim)*max(MAT))
    }
    if(matdim[1]>=matdim[2]){ 
        svd1 <- svd(MAT)
        keep <- which(svd1$d > tol)
        res <- t(svd1$u[,keep]%*%diag(svd1$d[keep]^EXP, nrow=length(keep))%*%t(svd1$v[,keep]))
    }
    if(matdim[1]<matdim[2]){ 
        svd1 <- svd(t(MAT))
        keep <- which(svd1$d > tol)
        res <- svd1$u[,keep]%*%diag(svd1$d[keep]^EXP, nrow=length(keep))%*%t(svd1$v[,keep])
    }
    return(res)
}

使用示例:

source("exp.mat.R")
X <- matrix(c(rep(1, 8),2,3,4,0,6,4,3,7,-2,-4,3,5,7,8,9,11), nrow=8, ncol=3)
iX <- exp.mat(X, -1)
zapsmall(iX %*% X) # results in identity matrix
[,1] [,2] [,3]
[1,]    1    0    0
[2,]    0    1    0
[3,]    0    0    1

【讨论】:

  • 你好。谢谢你的时间。我需要使用特定的包来使用您上面所说的功能吗?
  • 哦等等,我猜你需要在你的程序中自己创建那个函数?
  • @Reanimation - 欢迎您。不,您可以按原样加载函数(即将函数代码传递给您的 R 环境)。如果您更喜欢加载包而不是sourcethis 函数,也可以在包corpcor 中找到类似的函数(pseudoinverse)。 exp.mat 函数的优点是它还可以采用其他指数值(例如 EXP=-0.5)。
  • MASS::ginv 也实现了伪逆,并带有标准的 R 安装...
  • @BenBolker - 干杯。我不敢相信我不知道 ginv - 感谢您指出这一点。
猜你喜欢
  • 2017-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-08
  • 2016-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多