我有一个非常大的吸收马尔可夫链(扩展到问题大小 - 从10个状态到数百万个)非常稀疏(大多数状态只能对4或5个其他状态做出反应)。
我需要计算该链的基本矩阵的一行(给定一个起始状态的每个状态的平均频率)。
通常,我会通过计算(I - Q)^(-1)
来做到这一点,但我找不到一个实现稀疏矩阵逆算法的好库!我已经看过几篇论文,其中大部分是P.h.D.水平的工作。
我的大多数Google搜索结果都指向我在讨论在解决线性(或非线性)方程组时不应该使用矩阵逆的帖子......我觉得这没有特别有用。基本矩阵的计算是否类似于求解方程组,而我根本不知道如何以另一个的形式表达一个?
所以,我提出两个具体问题:
计算稀疏矩阵的逆的行(或所有行)的最佳方法是什么?
OR
计算大吸收马尔可夫链的基本矩阵的行的最佳方法是什么?
Python解决方案会很精彩(因为我的项目目前仍然是一个概念验证),但是如果我必须弄清楚一些好的'Fortran或C',那不是问题。
编辑:我刚刚意识到矩阵A的逆B可以定义为AB = I,其中I是单位矩阵。这可能允许我使用一些标准的稀疏矩阵求解器来计算逆...我必须跑掉,所以随意完成我的思路,我开始认为可能只需要一个非常基本的矩阵属性...
答案 0 :(得分:3)
你得到不使用矩阵求逆求解方程的建议是因为数值稳定性。当矩阵具有零或接近零的特征值时,您会遇到问题:缺少逆(如果为零)或数值稳定性(如果接近零)。因此,解决问题的方法是使用不需要存在逆的算法。解决方案是使用Gaussian elimination。这并没有提供完整的反转,而是让你采用行 - 梯形式,一种上三角形的概括。如果矩阵是可逆的,则结果矩阵的最后一行包含一行反转。因此,只需安排您消除的最后一行是您想要的行。
我会留给你理解为什么I-Q
总是可逆的。
答案 1 :(得分:2)
假设你要做的就是expected number of steps before absorbtion,来自“有限马尔可夫链”(Kemeny and Snell)的等式,在维基百科上再现:
或扩展基本矩阵
重新排列:
这是使用函数求解线性方程组的标准格式
将其付诸实践,以展示性能上的差异(即使对于比您所描述的系统小得多的系统)。
import networkx as nx
import numpy
def example(n):
"""Generate a very simple transition matrix from a directed graph
"""
g = nx.DiGraph()
for i in xrange(n-1):
g.add_edge(i+1, i)
g.add_edge(i, i+1)
g.add_edge(n-1, n)
g.add_edge(n, n)
m = nx.to_numpy_matrix(g)
# normalize rows to ensure m is a valid right stochastic matrix
m = m / numpy.sum(m, axis=1)
return m
介绍计算预期步数的两种替代方法。
def expected_steps_fundamental(Q):
I = numpy.identity(Q.shape[0])
N = numpy.linalg.inv(I - Q)
o = numpy.ones(Q.shape[0])
numpy.dot(N,o)
def expected_steps_fast(Q):
I = numpy.identity(Q.shape[0])
o = numpy.ones(Q.shape[0])
numpy.linalg.solve(I-Q, o)
选择一个足以证明计算基本矩阵时出现的问题类型的例子:
P = example(2000)
# drop the absorbing state
Q = P[:-1,:-1]
产生以下时间:
%timeit expected_steps_fundamental(Q)
1 loops, best of 3: 7.27 s per loop
和
%timeit expected_steps_fast(Q)
10 loops, best of 3: 83.6 ms per loop
需要进一步的实验来测试稀疏矩阵的性能影响,但很明显,计算逆矩阵比你预期的慢很多。
与此处介绍的方法类似的方法也可用于步骤数的方差