定义 f 为
f <- function(x) {
C <- (x[1]*x[2]*x[3])^(1/3)
log(x/C)
}
我们首先注意到,如果k 是任何标量常量,那么f(x) 和f(k*x) 给出相同的结果,所以如果我们有y = f(x),我们无法判断y 是来自x 还是来自k*x。也就是说,y 可能来自 x 的任何标量倍数;因此,我们无法从 y 中恢复 x。
线性公式
虽然我们无法恢复 x,但我们可以将 x 确定为标量倍数。定义矩阵A:
ones <- rep(1, 8)
a <- c(1, 1, 1, 0, 0, 0, 0, 0)
A <- diag(8) - outer(ones, a) / 3
在这种情况下 f(x) 等于:
A %*% log(x)
反演公式
根据这个公式,给定 y 并求解 x,x 的值将等于
exp(solve(A) %*% y) ## would equal x if A were invertible
如果 A 是可逆的,但不幸的是它不是。例如,rowSums(A) 等于 0,这表明 A 的列是线性相关的,这意味着不可逆。
all.equal(rowSums(A), rep(0, 8))
## [1] TRUE
等级和零空间
注意 A 是一个投影矩阵。这是因为它是幂等的,即A %*% A 等于A。
all.equal(A %*% A, A)
## [1] TRUE
这也源于它的特征值都是0和1:
zapsmall(eigen(A)$values)
## [1] 1 1 1 1 1 1 1 0
从特征值中我们看到 A 的秩为 7(非零特征值的数量),零空间的维数为 1(零特征值的数量)。
另一种理解方式是,知道 A 是一个投影矩阵,它的秩等于它的迹,即 7,因此它的零空间必须有维度 8-7=1。
sum(diag(A)) # rank of A
## [1] 7
采用标量倍数跨越一维空间,因此从零空间的维度为 1 的事实来看,它必须是映射到相同 y 的全部值。
关键公式
现在将上面## 中的solve 替换为广义逆ginv,我们有这个关键公式来近似x,因为对于某些x,y = f(x):
library(MASS)
exp(ginv(A) %*% y) # approximation to x accurate up to scalar multiple
或等效地,如果 y = f(x)
exp(y - mean(y))
虽然这些没有给出 x,但它们确实将 x 确定为一个标量倍数。也就是说,如果 x' 是上述表达式产生的值,那么对于某个标量常数 k,x 等于 k * x'。
例如,使用问题中的 x 和 y:
exp(ginv(A) %*% y)
## [,1]
## [1,] 1.2321318
## [2,] 0.5060149
## [3,] 3.4266146
## [4,] 0.1550034
## [5,] 0.2842220
## [6,] 3.7703442
## [7,] 1.0132635
## [8,] 2.7810703
exp(y - mean(y)) # same
## [1] 1.2321318 0.5060149 3.4266146 0.1550034 0.2842220 3.7703442 1.0132635
## [8] 2.7810703
exp(y - mean(y))/x
## [1] 2.198368 2.198368 2.198368 2.198368 2.198368 2.198368 2.198368 2.198368
注意
注意y - mean(y) 可以写成
B <- diag(8) - outer(ones, ones) / 8
B %*% y
如果 y = f(x) 那么 y 必须在 A 的范围内,所以我们可以验证:
all.equal(ginv(A) %*% A, B %*% A)
## [1] TRUE
矩阵 ginv(A) 等于 B 是不正确的。只有它们在 A 的范围上作用相同才是正确的,这就是我们所需要的。