【问题标题】:Inconsistent eigenvalues from eigs function in Scipy sparseScipy稀疏中eigs函数的特征值不一致
【发布时间】:2014-04-02 09:02:00
【问题描述】:

我正在使用 scipy.sparse.linalg 模块中的 eigs 函数,发现一些不一致的结果。运行两次相同的代码会得到不同的结果,即 np.allclose 的输出为 False。谁能解释这是为什么?

from scipy.sparse.linalg import eigs
from scipy.sparse import spdiags
import numpy as np


n1 = 100
x, dx = linspace(0, 2, n1, retstep=True)
e1 = ones(n1)
A = 1./(dx**2)*spdiags([e1, -2*e1, e1], [-1,0,1], n1, n1)

np.allclose(eigs(A, 90)[0], eigs(A, 90)[0])

IPython中的例子可以看here(抱歉不知道如何发布IPython输出)

编辑 1:

这不是@Kh40tiK 建议的对特征值进行排序的问题。见here。

编辑 2:

在尝试了不同版本的 Scipy 并运行 @Kh40tiK 发布的脚本并额外调用 scipy.show_config() 之后,似乎是用 MKL 编译的 SciPy 版本有问题。

使用 MKL:

2.7.6 |Anaconda 1.9.1 (64-bit)| (default, Jan 17 2014, 10:13:17) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)]
('numpy:', '1.8.1')
('scipy:', '0.13.3')
umfpack_info:
  NOT AVAILABLE
lapack_opt_info:
    libraries = ['mkl_lapack95_lp64', 'mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core',         'iomp5', 'pthread']
    library_dirs = ['/home/jpsilva/anaconda/lib']
    define_macros = [('SCIPY_MKL_H', None)]
    include_dirs = ['/home/jpsilva/anaconda/include']
blas_opt_info:
    libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']
    library_dirs = ['/home/jpsilva/anaconda/lib']
    define_macros = [('SCIPY_MKL_H', None)]
    include_dirs = ['/home/jpsilva/anaconda/include']
openblas_info:
  NOT AVAILABLE
lapack_mkl_info:
    libraries = ['mkl_lapack95_lp64', 'mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']
    library_dirs = ['/home/jpsilva/anaconda/lib']
    define_macros = [('SCIPY_MKL_H', None)]
    include_dirs = ['/home/jpsilva/anaconda/include']
blas_mkl_info:
    libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']
    library_dirs = ['/home/jpsilva/anaconda/lib']
    define_macros = [('SCIPY_MKL_H', None)]
    include_dirs = ['/home/jpsilva/anaconda/include']
mkl_info:
    libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']
    library_dirs = ['/home/jpsilva/anaconda/lib']
    efine_macros = [('SCIPY_MKL_H', None)]
    include_dirs = ['/home/jpsilva/anaconda/include']
False
False
False
False
False
False
False
False

没有 MKL:

2.7.5+ (default, Feb 27 2014, 19:37:08) 
[GCC 4.8.1]
('numpy:', '1.8.1')
('scipy:', '0.13.3')
umfpack_info:
  NOT AVAILABLE
atlas_threads_info:
  NOT AVAILABLE
blas_opt_info:
    libraries = ['f77blas', 'cblas', 'atlas']
    library_dirs = ['/usr/lib/atlas-base']
    define_macros = [('ATLAS_INFO', '"\\"3.10.1\\""')]
    language = c
    include_dirs = ['/usr/include/atlas']
atlas_blas_threads_info:
  NOT AVAILABLE
openblas_info:
  NOT AVAILABLE
lapack_opt_info:
    libraries = ['lapack', 'f77blas', 'cblas', 'atlas']
    library_dirs = ['/usr/lib/atlas-base/atlas', '/usr/lib/atlas-base']
    define_macros = [('ATLAS_INFO', '"\\"3.10.1\\""')]
    language = f77
    include_dirs = ['/usr/include/atlas']
atlas_info:
    libraries = ['lapack', 'f77blas', 'cblas', 'atlas']
    library_dirs = ['/usr/lib/atlas-base/atlas', '/usr/lib/atlas-base']
    define_macros = [('ATLAS_INFO', '"\\"3.10.1\\""')]
    language = f77
    include_dirs = ['/usr/include/atlas']
lapack_mkl_info:
  NOT AVAILABLE
blas_mkl_info:
  NOT AVAILABLE
atlas_blas_info:
    libraries = ['f77blas', 'cblas', 'atlas']
    library_dirs = ['/usr/lib/atlas-base']
    define_macros = [('ATLAS_INFO', '"\\"3.10.1\\""')]
    language = c
    include_dirs = ['/usr/include/atlas']
mkl_info:
  NOT AVAILABLE
True
False
True
False
True
False
True
False

【问题讨论】:

    标签: python scipy sparse-matrix arpack


    【解决方案1】:

    eigs 返回的特征值是随机顺序的。如果对它们进行排序,您应该会发现每次都得到相同的结果(除非起始向量运气不佳)。

    默认情况下,ARPACK 对 Krylov 进程使用随机起始向量,这解释了为什么每次调用都会得到不同的结果。如果您需要“可重现”的结果,请指定 v0 参数。

    请注意,“reproducible”在引号中,因为由于编译器优化,浮点舍入错误并不总是可重现的。

    【讨论】:

      【解决方案2】:

      sp.sparse.linalg.eigs() 不一定返回有序特征值,这意味着结果特征值可能是随机顺序的。您可能希望在调用 np.allclose 之前对特征值进行排序。

      另外,对np.allclose 尝试不同的容差,例如:

      np.allclose( eigs(A, 90)[0]), eigs(A,90)[0], 1e-3, 1e-5 )
      

      希望对你有帮助。

      编辑

      我在 Python 3(不是 IPython)上稍微修改了脚本,sort 很重要。

      #!/usr/bin/python3
      import sys
      from scipy.sparse.linalg import eigs
      from scipy.sparse import spdiags
      import numpy as np
      import scipy as sp
      
      n1 = 100
      x, dx = np.linspace(0, 2, n1, retstep=True)
      e1 = np.ones(n1)
      A = 1./(dx**2)*spdiags([e1, -2*e1, e1], [-1,0,1], n1, n1)
      
      print( sys.version )
      print( 'numpy:', np.version.version )
      print( 'scipy:', sp.version.version )
      for i in range(4):
          print (np.allclose(np.sort(eigs(A, 90)[0]), np.sort(eigs(A, 90)[0])))
          print (np.allclose(eigs(A, 90)[0], eigs(A, 90)[0]))
      

      输出:

      3.4.0 (default, Mar 22 2014, 22:51:25) 
      [GCC 4.8.2]
      numpy: 1.9.0.dev-b80ef75
      scipy: 0.15.0.dev-c2b7308
      True
      False
      True
      False
      True
      False
      True
      False
      

      如果sort 在您的系统中无法解决问题,则可能是版本差异或错误。

      【讨论】:

      • 好吧,对于np.eig(),我会接受它,但scipy.sparse.linalg.eigs 只计算几个排序的特征值(默认情况下,前6个和最大的数量级)我希望它返回有序的特征值。
      • 排序并没有成功...检查here
      • 1-您在向 eigs 询问 90 特征值而不是 6。 2-eig 的文档中没有提到返回特征值的顺序,所以你不能假设它。
      • 我对 Scipy 0.13.3(当前版本在 pip 和 conda 上可用)进行了一些测试,使用 MKL 构建的 Scipy 版本出现故障,而标准版本则没有。 @flebool 1-这无关紧要 2-完全同意。
      • 为什么您的回答以对np.eig 的评论开头?问题是关于scipy.sparse.linalg.eigs。您的评论适用于scipy.sparse.linalg.eigs,并且对特征值进行排序对我有用,因此对np.eig 的引用令人困惑。
      猜你喜欢
      • 1970-01-01
      • 2012-08-20
      • 1970-01-01
      • 2012-11-04
      • 2014-09-23
      • 1970-01-01
      • 2015-04-12
      • 2013-09-25
      • 2017-08-14
      相关资源
      最近更新 更多