代码之家  ›  专栏  ›  技术社区  ›  Aaron Bramson

防止计算机之间的scipy特征向量不同

  •  3
  • Aaron Bramson  · 技术社区  · 10 年前

    跟进 this question 关于如何找到马尔可夫稳态,我现在遇到了一个问题,那就是它在我的实验室计算机上工作得很好,但在其他任何计算机上都不行。具体地说,它总是找到接近一个特征值的正确数量,因此哪些节点是吸引子节点,但它并没有一致地找到所有这些节点,它们也没有正确分组。例如,使用下面的64x64转换矩阵,它不工作的计算机总是随机产生三个不同的错误吸引子集合中的一个。在下面较小的矩阵M1上,所有测试的计算机都得到了相同的、正确的吸引子群和平稳分布结果。

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

    这只是我目前对结果差异的最佳猜测。如果你对为什么会发生这种情况以及如何阻止这种情况的发生有更好的想法,那么这也很棒。

    如果有一种方法可以使scipy从运行到运行,从计算机到计算机保持一致,我不认为这取决于我的方法的细节,但因为它是被请求的,所以就在这里。这两个矩阵都有3个吸引子。在M1中,第一个[1,2]是两个状态的轨道,另外两个[7]和[8]是平衡的。M2是 64x64 transition matrix 平衡点在[2]和[26],轨道使用[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 回复  |  直到 9 年前
        1
  •  -3
  •   Aaron Bramson    10 年前

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

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

    这意味着(除非我的代码中有其他未识别的错误)scipy。linalg对于寻找马尔可夫模型的稳态是没有价值的。 尽管它有效 一些 在大多数情况下,它不能提供正确的答案,因此应该完全避免……至少对于马尔可夫模型稳态,以及可能与特征向量有关的一切。它就是不起作用。

    我将发布关于如何可靠地生成马尔可夫模型的平稳分布的代码 没有 如果有人提出问题,请使用scipy。它运行得有点慢,但总是一样的,总是正确的。

    [[ 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.        ]]