【发布时间】:2015-10-28 08:04:13
【问题描述】:
我需要使用一些 python 代码使用其转移矩阵的左特征向量找到马尔可夫模型的稳态。
在this question 中已经确定 scipy.linalg.eig 无法提供所描述的实际左特征向量,但在那里演示了修复。官方文档像往常一样大多是无用和难以理解的。
比不正确的格式更大的问题是产生的特征值没有任何特定的顺序(没有排序并且每次都不同)。因此,如果您想找到与 1 个特征值相对应的左特征向量,您必须寻找它们,这会带来它自己的问题(见下文)。数学很清楚,但如何让 python 计算并返回正确的特征向量尚不清楚。这个问题的其他答案,比如this one,似乎没有使用左特征向量,所以这些不是正确的解决方案。
This question 提供了部分解决方案,但它没有考虑较大转移矩阵的无序特征值。所以,只需使用
leftEigenvector = scipy.linalg.eig(A,left=True,right=False)[1][:,0]
leftEigenvector = leftEigenvector / sum(leftEigenvector)
很接近,但通常不起作用,因为[:,0] 位置中的条目可能不是正确特征值的特征向量(在我的情况下通常不是)。
好的,但是scipy.linalg.eig(A,left=True,right=False) 的输出是一个数组,其中[0] 元素是每个特征值的列表(不按任何顺序),并且在位置[1] 后面跟着一个特征向量数组这些特征值的对应顺序。
我不知道如何通过特征值对整个事物进行排序或搜索以提取正确的特征向量(特征值为 1 的所有特征向量都由向量条目的总和归一化。)我的想法是获取索引的特征值等于 1,然后从特征向量数组中提取这些列。我的这个版本既慢又麻烦。首先,我有一个函数(不太好用)来查找最后一个匹配值的位置:
# 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匹配的特征向量。
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
但实际上这不起作用。有一个 eigenvalue = 1.00000000e+00 +0.00000000e+00j 没有找到,即使另外两个有。
我的期望是我不是第一个使用 python 来查找马尔可夫模型的平稳分布的人。更精通/经验丰富的人可能有一个可行的通用解决方案(无论是否使用 numpy 或 scipy)。考虑到马尔可夫模型的流行程度,我预计会有一个库供他们执行此任务,也许它确实存在,但我找不到。
【问题讨论】:
-
我对马尔可夫链分析不太熟悉,但听起来你或多或少已经掌握了它。您为您想要的特征值搜索的解决方案似乎很合理。如果性能是一个问题,也许发布您正在使用的代码以便有人可以查看?
-
性能不是一个严重的问题,只要它确实有效。目前在特征值列表中搜索等于 1 的那些不起作用:它错过了其中一个。另外两个不对应于实际的稳态,因此特征向量条目的顺序也可能以文档中未说明的某种方式混乱。或者问题可能是我的矩阵有多个独立的吸引子状态。
-
可能是精度问题?您可以尝试使用 epsilon 一些合适的小数字代替
x == a之类的x < a + epsilon && x > a - epsilon。 -
w, vl = eig(P, right=False, left=True); tol = 1e-15; v1 = vl[:,abs(w - 1)
标签: python numpy scipy eigenvector markov-chains