Stack Overflow上有两个与此问题相关的线程:
以上是直截了当的,但非常昂贵。如果我们有一个订单n
的转换矩阵,那么在每次迭代时我们都会计算成本O(n ^ 3)
的矩阵 - 矩阵乘法。
有更有效的方法吗?我发生的一件事是使用特征分解。已知马尔可夫矩阵:
A = E * D * E^{-1}
; 静态分布是与特征值1相关联的特征向量,即第一特征向量。
嗯,这个理论很好,但是我无法理解它。在第一个链接问题中取矩阵P
:
P <- structure(c(0, 0.1, 0, 0, 0, 0, 0, 0.1, 0.2, 0, 0, 0, 0, 0, 0.2,
0.3, 0, 0, 0.5, 0.4, 0.3, 0.5, 0.4, 0, 0, 0, 0, 0, 0.6, 0.4,
0.5, 0.4, 0.3, 0.2, 0, 0.6), .Dim = c(6L, 6L))
如果我这样做:
Re(eigen(P)$vectors[, 1])
# [1] 0.4082483 0.4082483 0.4082483 0.4082483 0.4082483 0.4082483
发生了什么事?根据以前的问题,固定分布是:
# [1] 0.002590673 0.025906737 0.116580322 0.310880848 0.272020713 0.272020708
答案 0 :(得分:5)
好吧,要使用Eigen分解,我们需要使用t(P)
。
转移概率矩阵的定义在概率/统计和线性代数之间不同。在统计信息中,P
的所有行总和为1,而在线性代数中,P
的所有列总和为1.因此,我们需要eigen(P)
代替eigen(t(P))
:
e <- Re(eigen(t(P))$vectors[, 1])
e / sum(e)
# [1] 0.002590673 0.025906737 0.116580322 0.310880848 0.272020713 0.272020708
我们可以看到,我们只使用了第一个特征向量,即最大特征值的特征向量。因此,不需要使用eigen
计算所有特征值/向量。 power method可用于找到最大特征值的特征向量。让我们在R:
stydis1 <- function (A) {
n <- dim(A)[1L]
## checking
if (any(.rowSums(A, n, n) != 1))
stop (" 'A' is not a Markov matrix")
## implement power method
e <- runif (n)
oldnorm <- sqrt(c(crossprod(e)))
repeat {
e <- crossprod(A, e)
newnorm <- sqrt(c(crossprod(e)))
if (abs(newnorm / oldnorm - 1) < 1e-8) break
e <- e / newnorm
oldnorm <- newnorm
}
## rescale `e` so that it sums up to 1
c(e / sum(e))
}
stydis1 (P)
# [1] 0.002590673 0.025906737 0.116580322 0.310880848 0.272020713 0.272020708
结果是正确的。
实际上,我们不必利用特征分解。我们可以调整您的第二个链接问题中使用的方法。在那里,我们采用矩阵电源,这是昂贵的,你评论;但为什么不把它重新投入矩阵向量乘法?
stydis2 <- function (A) {
n <- dim(A)[1L]
## checking
if (any(.rowSums(A, n, n) != 1))
stop (" 'A' is not a Markov matrix")
## direct computation
b <- A[1, ]
oldnorm <- sqrt(c(crossprod(b)))
repeat {
b <- crossprod(A, b)
newnorm <- sqrt(c(crossprod(b)))
if (abs(newnorm / oldnorm - 1) < 1e-8) break
oldnorm <- newnorm
}
## return stationary distribution
c(b)
}
stydis2 (P)
# [1] 0.002590673 0.025906737 0.116580322 0.310880848 0.272020713 0.272020708
我们从任意初始分布开始,比如A[1, ]
,并迭代地应用转换矩阵,直到分布收敛。再次,结果是正确的。
答案 1 :(得分:2)
您的向量y = Re(eigen(P)$vectors[, 1])
不是分布(因为它不能加起来)并且解决P'y = y
,而不是x'P = x
。您链接的Q&amp; A的解决方案大致解决了后者:
x = c(0.00259067357512953, 0.0259067357512953, 0.116580310880829,
0.310880829015544, 0.272020725388601, 0.272020725388601)
all(abs(x %*% P - x) < 1e-10) # TRUE
通过转置P,您可以使用特征值方法:
x2 = Re(eigen(t(P))$vectors[, 1])
x2 <- x2/sum(x2)
(function(x) all(abs(x %*% P - x) < 1e-10))(
x2
) # TRUE
但是,在这种情况下,它找到了一个不同的静止向量。
答案 2 :(得分:0)
根据平稳概率矢量的定义,它是具有单位特征值的转移概率矩阵的左特征矢量。我们可以通过计算矩阵的特征分解,识别单位特征值,然后为这些单位特征值中的每个特征值计算固定概率矢量,从而找到此类对象。这是R
中的一个函数。
stationary <- function(P) {
#Get matrix information
K <- nrow(P)
NAMES <- rownames(P)
#Compute the eigendecomposition
EIGEN <- eigen(P)
VALS <- EIGEN$values
RVECS <- EIGEN$vectors
LVECS <- solve(VECS)
#Find the unit eigenvalue(s)
RES <- zapsmall(Mod(VALS - as.complex(rep(1, K))))
IND <- which(RES == 0)
N <- length(IND)
#Find the stationary vector(s)
OUT <- matrix(0, nrow = N, ncol = K)
rownames(OUT) <- sprintf('Stationary[%s]', 1:N)
colnames(OUT) <- NAMES
for (i in 1:length(IND)) {
SSS <- Re(eigen(t(P))$vectors[, IND[i]])
OUT[i,] <- SSS/sum(SSS) }
#Give the output
OUT }
(注意:使用eigen
计算的本征分解会遇到一些数字误差,因此不存在完全等于1的本征值。因此,我们zapsmall
只要不存在小于1的真实特征值,但又接近于1的真实特征值,它也将被“转换”为1,这将为我们提供正确的答案。 )
在此情况下,将此函数应用于转换概率矩阵可正确识别唯一的固定概率向量。计算中存在少量数值误差,但这在大多数情况下应该可以解决。
#Compute the stationary probability vector
S <- stationary(P)
#Show this vector and confirm stationarity
S
[,1] [,2] [,3] [,4] [,5] [,6]
Stationary[1] 0.002590674 0.02590674 0.1165803 0.3108808 0.2720207 0.2720207
S %*% P
[,1] [,2] [,3] [,4] [,5] [,6]
Stationary[1] 0.002590674 0.02590674 0.1165803 0.3108808 0.2720207 0.2720207
#Show error in computation
c(S %*% P - S)
[1] 4.336809e-17 2.775558e-17 1.110223e-16 -2.775558e-16 1.665335e-16 -5.551115e-17