来自Scigy稀疏的eigs函数的不一致特征值

时间:2014-04-02 09:02:01

标签: python scipy sparse-matrix arpack

我在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

2 个答案:

答案 0 :(得分:3)

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没有在您的系统中执行此操作,则可能是版本差异或错误。

答案 1 :(得分:3)

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

ARPACK默认使用Krylov过程的随机起始向量,这解释了为什么每次调用都会得到不同的结果。如果你需要"可重复的"结果,指定v0参数。

注意"可重复的"因为编译器优化,浮点舍入误差并不总是可重现的。