查找具有左特征值的马尔可夫稳态(使用numpy或scipy) [英] find Markov steady state with left eigenvalues (using numpy or scipy)

查看:100
本文介绍了查找具有左特征值的马尔可夫稳态(使用numpy或scipy)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用一些python代码,使用其转移矩阵的左特征向量来找到Markov模型的稳态.

I need to find the steady state of Markov models using the left eigenvectors of their transition matrices using some python code.

它已经在此问题中建立 scipy.linalg.eig无法提供所描述的实际左特征向量,但在那里进行了修复.官方文档通常像往常一样是无用的和令人费解的.

It has already been established in this question that scipy.linalg.eig fails to provide actual left eigenvectors as described, but a fix is demonstrated there. The official documentation is mostly useless and incomprehensible as usual.

比不正确的格式要大的问题是,生成的特征值没有任何特定的顺序(每次都没有排序和不同).因此,如果要查找与1个特征值相对应的左特征向量,则必须寻找它们,这是一个问题(请参阅下文).数学上很清楚,但是尚不清楚如何获取python进行计算并返回正确的特征向量.此问题的其他答案,例如

A bigger problem than than the incorrect format is that the eigenvalues produced are not in any particular order (not sorted and different each time). So if you want to find the left eigenvectors that correspond to the 1 eigenvalues you have to hunt for them, and this poses it's own problem (see below). The math is clear, but how to get python to compute this and return the correct eigenvectors is not clear. Other answers to this question, like this one, don't seem to be using the left eigenvectors, so those can't be correct solutions.

此问题提供了部分内容解决方案,但它不考虑较大过渡矩阵的无序特征值.因此,只需使用

This question provides a partial solution, but it doesn't account for the unordered eigenvalues of larger transition matrices. So, just using

leftEigenvector = scipy.linalg.eig(A,left=True,right=False)[1][:,0]
leftEigenvector = leftEigenvector / sum(leftEigenvector)

很接近,但通常无法正常工作,因为[:,0]位置中的条目可能不是正确特征值的特征向量(在我的情况下通常不是).

is close, but doesn't work in general because the entry in the [:,0] position may not be the eigenvector for the correct eigenvalue (and in my case it is usually not).

好吧,但是scipy.linalg.eig(A,left=True,right=False)的输出是一个数组,其中[0]元素是每个特征值的列表(不按任何顺序排列),并且在位置[1]后面是特征向量的数组这些特征值的对应顺序.

Okay, but the output of scipy.linalg.eig(A,left=True,right=False) is an array in which the [0] element is a list of each eigenvalue (not in any order) and that is followed in position [1] by an array of eigenvectors in a corresponding order to those eigenvalues.

我不知道一种通过特征值对整个事物进行排序或搜索以提取正确特征向量(通过向量项之和归一化为特征值1的所有特征向量)的好方法.我的想法是获取索引取等于1的特征值,然后从特征向量数组中拉出这些列.我对此的说法既缓慢又麻烦.首先,我有一个函数(不太有效),可以在最后一个与值匹配的位置中找到位置:

I don't know a good way to sort or search that whole thing by the eigenvalues to pull out the correct eigenvectors (all eigenvectors with eigenvalue 1 normalized by the sum of the vector entries.) My thinking is to get the indices of the eigenvalues that equal 1, and then pull those columns from the array of eigenvectors. My version of this is slow and cumbersome. First I have a function (that doesn't quite work) to find positions in a last that matches a value:

# Find the positions of the element a in theList
def findPositions(theList, a):
  return [i for i, x in enumerate(theList) if x == a]

然后我像这样使用它来获得与特征值= 1匹配的特征向量.

Then I use it like this to get the eigenvectors matching the eigenvalues = 1.

M = transitionMatrix( G )
leftEigenvectors = scipy.linalg.eig(M,left=True,right=False)
unitEigenvaluePositions = findPositions(leftEigenvectors[0], 1.000)
steadyStateVectors = []
for i in unitEigenvaluePositions:
    thisEigenvector = leftEigenvectors[1][:,i]
    thisEigenvector / sum(thisEigenvector)
    steadyStateVectors.append(thisEigenvector)
print steadyStateVectors

但是实际上这是行不通的.即使有另外两个特征值,也找不到一个特征值= 1.00000000e+00 +0.00000000e+00j.

But actually this doesn't work. There is one eigenvalue = 1.00000000e+00 +0.00000000e+00j that is not found even though two others are.

我的期望是,我不是第一个使用python查找Markov模型的平稳分布的人.精通/有经验的人可能有一个可行的通用解决方案(无论是否使用numpy或scipy).考虑到Markov模型的流行程度,我希望有一个库供他们执行此任务,也许它确实存在,但我找不到它.

My expectation is that I am not the first person to use python to find stationary distributions of Markov models. Somebody who is more proficient/experienced probably has a working general solution (whether using numpy or scipy or not). Considering how popular Markov models are I expected there to be a library just for them to perform this task, and maybe it does exist but I couldn't find one.

推荐答案

您已链接到

You linked to How do I find out eigenvectors corresponding to a particular eigenvalue of a matrix? and said it doesn't compute the left eigenvector, but you can fix that by working with the transpose.

例如,

In [901]: import numpy as np

In [902]: import scipy.sparse.linalg as sla

In [903]: M = np.array([[0.5, 0.25, 0.25, 0], [0, 0.1, 0.9, 0], [0.2, 0.7, 0, 0.1], [0.2, 0.3, 0, 0.5]])

In [904]: M
Out[904]: 
array([[ 0.5 ,  0.25,  0.25,  0.  ],
       [ 0.  ,  0.1 ,  0.9 ,  0.  ],
       [ 0.2 ,  0.7 ,  0.  ,  0.1 ],
       [ 0.2 ,  0.3 ,  0.  ,  0.5 ]])

In [905]: eval, evec = sla.eigs(M.T, k=1, which='LM')

In [906]: eval
Out[906]: array([ 1.+0.j])

In [907]: evec
Out[907]: 
array([[-0.32168797+0.j],
       [-0.65529032+0.j],
       [-0.67018328+0.j],
       [-0.13403666+0.j]])

In [908]: np.dot(evec.T, M).T
Out[908]: 
array([[-0.32168797+0.j],
       [-0.65529032+0.j],
       [-0.67018328+0.j],
       [-0.13403666+0.j]])

要对特征向量进行归一化(您应该知道它是真实的):

To normalize the eigenvector (which you know should be real):

In [913]: u = (evec/evec.sum()).real

In [914]: u
Out[914]: 
array([[ 0.18060201],
       [ 0.36789298],
       [ 0.37625418],
       [ 0.07525084]])

In [915]: np.dot(u.T, M).T
Out[915]: 
array([[ 0.18060201],
       [ 0.36789298],
       [ 0.37625418],
       [ 0.07525084]])

如果您事先不知道特征值1的多重性,请参阅@pv.的注释,该注释显示使用scipy.linalg.eig的代码.这是一个示例:

If you don't know the multiplicity of eigenvalue 1 in advance, see @pv.'s comment showing code using scipy.linalg.eig. Here's an example:

In [984]: M
Out[984]: 
array([[ 0.9 ,  0.1 ,  0.  ,  0.  ,  0.  ,  0.  ],
       [ 0.3 ,  0.7 ,  0.  ,  0.  ,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.25,  0.75,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.5 ,  0.5 ,  0.  ,  0.  ],
       [ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ,  1.  ],
       [ 0.  ,  0.  ,  0.  ,  0.  ,  1.  ,  0.  ]])

In [985]: import scipy.linalg as la

In [986]: evals, lvecs = la.eig(M, right=False, left=True)

In [987]: tol = 1e-15

In [988]: mask = abs(evals - 1) < tol

In [989]: evals = evals[mask]

In [990]: evals
Out[990]: array([ 1.+0.j,  1.+0.j,  1.+0.j])

In [991]: lvecs = lvecs[:, mask]

In [992]: lvecs
Out[992]: 
array([[ 0.9486833 ,  0.        ,  0.        ],
       [ 0.31622777,  0.        ,  0.        ],
       [ 0.        , -0.5547002 ,  0.        ],
       [ 0.        , -0.83205029,  0.        ],
       [ 0.        ,  0.        ,  0.70710678],
       [ 0.        ,  0.        ,  0.70710678]])

In [993]: u = lvecs/lvecs.sum(axis=0, keepdims=True)

In [994]: u
Out[994]: 
array([[ 0.75, -0.  ,  0.  ],
       [ 0.25, -0.  ,  0.  ],
       [ 0.  ,  0.4 ,  0.  ],
       [ 0.  ,  0.6 ,  0.  ],
       [ 0.  , -0.  ,  0.5 ],
       [ 0.  , -0.  ,  0.5 ]])

In [995]: np.dot(u.T, M).T
Out[995]: 
array([[ 0.75,  0.  ,  0.  ],
       [ 0.25,  0.  ,  0.  ],
       [ 0.  ,  0.4 ,  0.  ],
       [ 0.  ,  0.6 ,  0.  ],
       [ 0.  ,  0.  ,  0.5 ],
       [ 0.  ,  0.  ,  0.5 ]])

这篇关于查找具有左特征值的马尔可夫稳态(使用numpy或scipy)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆