防止scipy特征向量因计算机而异

时间:2016-01-12 12:57:57

标签: python numpy scipy eigenvector eigenvalue

关于如何找到马尔可夫稳定状态的this question后续问题,我现在遇到的问题是它在我的实验室计算机上完美运行,但它不适用于任何其他电脑。具体来说,它总是找到正确数量的近一个特征值,因此哪些节点是吸引子节点,但它并不总是找到所有这些节点,并且它们没有被正确分组。例如,使用下面的64x64转换矩阵,它不工作的计算机总是随机产生三个不同的错误吸引子集合之一。在下面较小的矩阵M1上,所有测试的计算机都会得到相同的,正确的结果给吸引子组和静止分布。

所有测试的机器都运行Win7x64和WinPython-64bit-2.7.9.4。一台计算机总是正确的,另外三台计算机总是以同样的方式弄错。根据我发现like thisthis的几个帖子,这听起来可能是由于计算的浮点精度差异造成的。不幸的是,我不知道如何解决这个问题;我的意思是,我不知道如何改变从矩阵中拉出左特征值的代码,以强制所有计算机都可以处理的特定精度(我不认为它必须非常准确为此目的)。

这是我目前对结果如何不同的最佳猜测。如果您更好地了解为什么会发生这种情况以及如何阻止它发生,那么这也很棒。

如果有一种方法可以使scipy从一次运行到另一台计算机保持一致,我不认为这取决于我的方法的细节,但因为它是被请求的,所以它就是这样。两个矩阵都有3个吸引子。在M1中,第一个[1,2]是两个状态的轨道,另外两个[7]和[8]是平衡。 M2是在{2]和[26]处具有平衡的64x64 transition matrix以及使用[7,8]的轨道。

但有时候报告[[26],[2],[26]],有时报告[[2,7,8,26],[2],[26]]而不是找到那套吸引子,有时......每次运行都没有得到相同的答案,并且它永远不会[[2],[7,8],[26]](以任何顺序)。

import numpy as np
import scipy.linalg

M1 = np.array([[0.2, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
              [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
              [0.6, 0.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
              [0.0, 0.0, 0.2, 0.0, 0.1, 0.1, 0.3, 0.3],
              [0.0, 0.0, 0.2, 0.2, 0.2, 0.2, 0.1, 0.1],
              [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5],
              [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
              [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]])

M2 = np.genfromtxt('transitionMatrix1.csv', delimiter=',')

# For easy switching
M = M2
# Confirm the matrix is a valid Markov transition matrix
#print np.sum(M,axis=1)

其余部分与上一个问题中的代码相同,为方便起见,此处包含在此处。

#create a list of the left eigenvalues and a separate array of the left eigenvectors
theEigenvalues, leftEigenvectors = scipy.linalg.eig(M, right=False, left=True)  
# for stationary distribution the eigenvalues and vectors are always real, and this speeds it up a bit
theEigenvalues = theEigenvalues.real                 
#print theEigenvalues 
leftEigenvectors = leftEigenvectors.real
#print leftEigenvectors 
# set how close to zero is acceptable as being zero...1e-15 was too low to find one of the actual eigenvalues
tolerance = 1e-10
# create a filter to collect the eigenvalues that are near enough to zero                                    
mask = abs(theEigenvalues - 1) < tolerance
# apply that filter           
theEigenvalues = theEigenvalues[mask]
# filter out the eigenvectors with non-zero eigenvalues                
leftEigenvectors = leftEigenvectors[:, mask]         
# convert all the tiny and negative values to zero to isolate the actual stationary distributions
leftEigenvectors[leftEigenvectors < tolerance] = 0   
# normalize each distribution by the sum of the eigenvector columns
attractorDistributions = leftEigenvectors / leftEigenvectors.sum(axis=0, keepdims=True)   
# this checks that the vectors are actually the left eigenvectors
attractorDistributions = np.dot(attractorDistributions.T, M).T      
# convert the column vectors into row vectors (lists) for each attractor     
attractorDistributions = attractorDistributions.T                        
print attractorDistributions
# a list of the states in any attractor with the stationary distribution within THAT attractor
#theSteadyStates = np.sum(attractorDistributions, axis=1)                
#print theSteadyStates 

1 个答案:

答案 0 :(得分:-3)

不幸的答案是没有办法为scipy修复种子,因此无法强制它输出一致的值。这也意味着它无法可靠地生成正确的答案,因为只有一个答案是正确的。我试图从狡猾的人那里得到明确的答案或解决方法completely dismissed,但在面对这个问题时,有人可能会在这些话语中找到一些智慧。

作为问题的具体示例,当您运行上面的代码时,有时会得到以下一组特征向量,这些特征向量应该代表系统中每个吸引子的稳态。我的家用电脑总是产生这种结果(这与我的笔记本电脑和实验室电脑不同)。如问题中所述,正确的吸引子是[[2],[7,8],[26]]。正确识别[2][6]的均衡,但[7,8]的分布在[2,26]上返回无效的概率分布。正确答案分别是[0.19835, 0.80164]而不是[7,8]。我的实验室计算机正确找到了解决方案,但到目前为止还有其他六台计算机没有这样做。

这意味着什么(除非我的代码中还有其他一些未识别的错误)scipy.linalg对于找到Markov模型的稳定状态毫无价值。即使它有效一些

如果有人询问有关它的问题,我将发布如何使用scipy可靠地生成Markov模型的静态分布的代码。它的运行速度有点慢,但总是一样的,总是正确的。

[[ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.25707958  1.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.06867772  0.          1.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
...
 [ 0.          0.          0.        ]]