Best way to calculate the fundamental matrix of an absorbing Markov Chain?

后端 未结 2 1798
你的背包
你的背包 2021-02-13 20:37

I have a very large absorbing Markov chain (scales to problem size -- from 10 states to millions) that is very sparse (most states can react to only 4 or 5 other states).

<
2条回答
  •  孤独总比滥情好
    2021-02-13 20:56

    Assuming that what you're trying to do is work out is the expected number of steps before absorbtion, the equation from "Finite Markov Chains" (Kemeny and Snell), which is reproduced on Wikipedia is:

    t=N1

    Or expanding the fundamental matrix

    t=(I-Q)^-1 1

    Rearranging:

    (I-Q) t = 1

    Which is in the standard format for using functions for solving systems of linear equations

    A x = b

    Putting this into practice to demonstrate the difference in performance (even for much smaller systems than those you're describing).

    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
    

    Presenting the two alternative approaches for calculating the number of expected steps.

    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)
    

    Picking an example that's big enough to demonstrate the types of problems that occur when calculating the fundamental matrix:

    P = example(2000)
    # drop the absorbing state
    Q = P[:-1,:-1]
    

    Produces the following timings:

    %timeit expected_steps_fundamental(Q)
    1 loops, best of 3: 7.27 s per loop
    

    And:

    %timeit expected_steps_fast(Q)
    10 loops, best of 3: 83.6 ms per loop
    

    Further experimentation is required to test the performance implications for sparse matrices, but it's clear that calculating the inverse is much much slower than what you might expect.

    A similar approach to the one presented here can also be used for the variance of the number of steps

提交回复
热议问题