确定性python脚本以非确定性方式运行

mwm*_*mwm 12 python windows numpy scipy non-deterministic

我有一个不使用随机化的脚本,当我运行它时会给出不同的答案.每次运行脚本时,我都希望答案是一样的.问题似乎只发生在某些(病态的)输入数据上.

该片段来自为线性系统计算特定类型控制器的算法,它主要由线性代数(矩阵求逆,Riccati方程,特征值)组成.

显然,这对我来说是一个主要的担忧,因为我现在不能相信我的代码能给我正确的结果.我知道条件差的数据结果可能是错误的,但我预计一直都是错误的.为什么我的Windows机器上的答案并不总是一样的?为什么Linux和Windows机器没有给出相同的结果?

我正在使用Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win 32Numpy版本1.8.2和Scipy 0.14.0.(Windows 8,64位).

代码如下.我也尝试在两台Linux机器上运行代码,脚本总是给出相同的答案(但机器给出了不同的答案).一个是运行Python 2.7.8,Numpy 1.8.2和Scipy 0.14.0.第二个是使用Numpy 1.6.1和Scipy 0.12.0运行Python 2.7.3.

我三次解决Riccati方程,然后打印答案.我每次都期待相同的答案,而不是我得到序列'1.75305103767e-09; 3.25501787302e-07; 3.25501787302e-07' .

    import numpy as np
    import scipy.linalg

    matrix = np.matrix

    A = matrix([[  0.00000000e+00,   2.96156260e+01,   0.00000000e+00,
                        -1.00000000e+00],
                    [ -2.96156260e+01,  -6.77626358e-21,   1.00000000e+00,
                        -2.11758237e-22],
                    [  0.00000000e+00,   0.00000000e+00,   2.06196064e+00,
                         5.59422224e+01],
                    [  0.00000000e+00,   0.00000000e+00,   2.12407340e+01,
                        -2.06195974e+00]])
    B = matrix([[     0.        ,      0.        ,      0.        ],
                    [     0.        ,      0.        ,      0.        ],
                    [  -342.35401351, -14204.86532216,     31.22469724],
                    [  1390.44997337,    342.33745324,   -126.81720597]])
    Q = matrix([[ 5.00000001,  0.        ,  0.        ,  0.        ],
                    [ 0.        ,  5.00000001,  0.        ,  0.        ],
                    [ 0.        ,  0.        ,  0.        ,  0.        ],
                    [ 0.        ,  0.        ,  0.        ,  0.        ]])
    R = matrix([[ -3.75632852e+04,  -0.00000000e+00,   0.00000000e+00],
                    [ -0.00000000e+00,  -3.75632852e+04,   0.00000000e+00],
                    [  0.00000000e+00,   0.00000000e+00,   4.00000000e+00]])

    counter = 0
    while counter < 3:
            counter +=1

            X = scipy.linalg.solve_continuous_are(A, B, Q, R)
            print(-3449.15531628 - X[0,0])
Run Code Online (Sandbox Code Playgroud)

我的numpy配置如下 print np.show_config()

lapack_opt_info:
    libraries = ['mkl_blas95', 'mkl_lapack95', 'mkl_intel_c', 'mkl_intel_thread', 'mkl_core', 'libiomp5md', 'mkl_blas95', 'mkl_lapack95', 'mkl_intel_c', 'mkl_intel_thread', 'mkl_core', 'libiomp5md']
    library_dirs = ['c:/Program Files (x86)/Intel/Composer XE 2013 SP1/mkl/lib/ia32', 'C:/Program Files (x86)/Intel/Composer XE 2013 SP1/compiler/lib/ia32']
    define_macros = [('SCIPY_MKL_H', None)]
    include_dirs = ['c:/Program Files (x86)/Intel/Composer XE 2013 SP1/mkl/include']
blas_opt_info:
    libraries = ['mkl_blas95', 'mkl_lapack95', 'mkl_intel_c', 'mkl_intel_thread', 'mkl_core', 'libiomp5md']
    library_dirs = ['c:/Program Files (x86)/Intel/Composer XE 2013 SP1/mkl/lib/ia32', 'C:/Program Files (x86)/Intel/Composer XE 2013 SP1/compiler/lib/ia32']
    define_macros = [('SCIPY_MKL_H', None)]
    include_dirs = ['c:/Program Files (x86)/Intel/Composer XE 2013 SP1/mkl/include']
openblas_info:
  NOT AVAILABLE
lapack_mkl_info:
    libraries = ['mkl_blas95', 'mkl_lapack95', 'mkl_intel_c', 'mkl_intel_thread', 'mkl_core', 'libiomp5md', 'mkl_blas95', 'mkl_lapack95', 'mkl_intel_c', 'mkl_intel_thread', 'mkl_core', 'libiomp5md']
    library_dirs = ['c:/Program Files (x86)/Intel/Composer XE 2013 SP1/mkl/lib/ia32', 'C:/Program Files (x86)/Intel/Composer XE 2013 SP1/compiler/lib/ia32']
    define_macros = [('SCIPY_MKL_H', None)]
    include_dirs = ['c:/Program Files (x86)/Intel/Composer XE 2013 SP1/mkl/include']
blas_mkl_info:
    libraries = ['mkl_blas95', 'mkl_lapack95', 'mkl_intel_c', 'mkl_intel_thread', 'mkl_core', 'libiomp5md']
    library_dirs = ['c:/Program Files (x86)/Intel/Composer XE 2013 SP1/mkl/lib/ia32', 'C:/Program Files (x86)/Intel/Composer XE 2013 SP1/compiler/lib/ia32']
    define_macros = [('SCIPY_MKL_H', None)]
    include_dirs = ['c:/Program Files (x86)/Intel/Composer XE 2013 SP1/mkl/include']
mkl_info:
    libraries = ['mkl_blas95', 'mkl_lapack95', 'mkl_intel_c', 'mkl_intel_thread', 'mkl_core', 'libiomp5md']
    library_dirs = ['c:/Program Files (x86)/Intel/Composer XE 2013 SP1/mkl/lib/ia32', 'C:/Program Files (x86)/Intel/Composer XE 2013 SP1/compiler/lib/ia32']
    define_macros = [('SCIPY_MKL_H', None)]
    include_dirs = ['c:/Program Files (x86)/Intel/Composer XE 2013 SP1/mkl/include']
None

(编辑以减少问题)

Jos*_*sef 7

通常,Windows上的linalg库在机器精度级别的不同运行中给出不同的答案.我从来没有听说过为什么这种情况只发生在Windows上或主要发生在Windows上.

如果你的矩阵生病,那么inv将主要是数字噪声.在Windows上,连续运行时噪声并不总是相同,在其他操作系统上,噪声可能总是相同,但可能会有所不同,具体取决于线性代数库的详细信息,线程选项,缓存使用情况等.

我已经看到并在scipy邮件列表上发布了几个关于Windows的例子,我主要使用官方32位二进制文​​件和ATLAS BLAS/LAPACK.

唯一的解决方案是使计算的结果不依赖于浮点精度问题和数值噪声,例如将矩阵求逆,使用广义逆,pinv,重新参数化或类似.

  • 部分数值噪声来自内存中的数据对齐,即它是否恰好直接位于适合cpu sse等指令的位置 - 两种情况下的操作顺序不同,因此浮点舍入误差不同.win32标准内存分配器afaik倾向于返回平均比linux分配器更少对齐的内存块,因此存在更多的抖动.如果您的结果显着依赖于FP舍入误差的方式,那么您的问题公式在数值上是不稳定的. (4认同)