簡體   English   中英

在給定轉移概率矩陣的情況下尋找馬爾可夫過程的平穩分布

[英]Finding stationary distribution of a markov process given a transition probability matrix

Stack Overflow 上有兩個線程與此問題相關:

上面的很簡單,但是很貴。 如果我們有一個n階轉換矩陣,那么在每次迭代時,我們都會以O(n ^ 3)成本計算矩陣-矩陣乘法。

有沒有更有效的方法來做到這一點? 我想到的一件事是使用特征分解。 已知馬爾可夫矩陣:

  • 在復域中可對角化: A = E * D * E^{-1}
  • 具有 1 的實特征值,以及長度小於 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

好吧,要使用特征分解,我們需要使用t(P)

轉移概率矩陣的定義在概率/統計和線性代數之間有所不同。 在統計中, P所有行總和為 1,而在線性代數中, P所有列總和為 1。因此,我們需要eigen(t(P))而不是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計算所有特征值/向量。 冪方法可用於找到最大特征值的特征向量。 讓我們在 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, ] ,並迭代地應用轉移矩陣直到分布收斂。 再次,結果是正確的。

您的向量y = Re(eigen(P)$vectors[, 1])不是分布(因為它加起來不x'P = x一)並且解決P'y = y ,而不是x'P = x 您鏈接的問答中的解決方案大致解決了后者:

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

不過,在這種情況下,它正在尋找不同的平穩向量。

根據平穩概率向量的定義,它是轉移概率矩陣的左特征向量單位特征值為 我們可以通過計算矩陣的特征分解,識別單位特征值,然后計算每個單位特征值的平穩概率向量來找到這類對象。 這是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計算出的eigen分解會受到一些數值誤差的影響,因此沒有完全等於 1 的特征值。因此,我們將模偏差從 1 中zapsmall以識別單位特征向量。這將給我們只要不存在小於 1 的真實特征值,但又非常接近 1 以致於它也被“zapped”到 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM