2014-12-20 41 views
12

我有一個腳本,它不使用隨機化,當我運行它時會給我不同的答案。我希望每次運行腳本時答案都是一樣的。這個問題似乎只發生在某些(病態)輸入數據上。確定性的python腳本以非確定性的方式行爲

該片段來自一種算法,用於爲線性系統計算特定類型的控制器,它主要由做線性代數(矩陣求逆,Riccati方程,特徵值)組成。

顯然,這是我的一個主要擔心,因爲我現在不能相信我的代碼給我正確的結果。我知道結果可能是錯誤的條件不佳的數據,但我期望一貫錯誤。爲什麼我的Windows機器上的回答不總是一樣的?爲什麼Linux的Windows機器不能提供相同的結果?

我使用Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win 32,Numpy版本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]) 

我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 

(編輯修剪的問題下)

+0

您是否給發生器播種? http://docs.scipy.org/doc/numpy/reference/generated/numpy.random.seed.html – NPE

+0

我添加了'np.random.seed(0)'作爲代碼的第一行(就在輸入之後),並沒有區別。將更新問題。 – mwmwm

+0

道歉,我以某種方式誤解你的問題,說明代碼*使用隨機化。哎呀。 – NPE

回答

7

一般情況下,在Windows linalg庫給在機器精度級別在不同的運行不同的答案。我從來沒有聽說過爲什麼這種情況只發生或主要發生在Windows上的解釋。

如果你的矩陣病態,那麼inv將主要是數值噪聲。在Windows上,連續運行時噪聲並不總是相同的,但在其他操作系統上,噪聲可能總是相同,但可能因線性代數庫的細節,線程選項,緩存使用情況等而異。

我已經看到併發布到scipy郵件列表上的這個在Windows上的幾個例子,我主要使用ATLAS BLAS/LAPACK的官方32位二進制文​​件。

唯一的解決方案是讓計算結果不要太依賴於浮點精度問題和數值噪聲,例如調整矩陣求逆,使用廣義逆,pinv,重新參數化或類似方法。

+3

數字噪聲的一部分來自內存中的數據對齊,即它是否恰好位於適合CPU的sse等指令的位置 - 兩種情況下的操作順序不同,因此浮點舍入錯誤是不同。 win32標準內存分配器afaik傾向於返回平均比linux分配器更少對齊的內存塊,因此存在更多抖動。如果你的結果很大程度上取決於FP舍入誤差的方式,你的問題公式在數值上是不穩定的。 –

2

由於pvcomments to user333700's answer中指出,以前的Riccati求解器的公式雖然在理論上是正確的,但在數值上是不穩定的。這個問題固定在SciPy的開發版本上,求解器也支持廣義Riccati方程。

Riccati解算器已更新,解算器將從版本0.19開始提供。你可以檢查development branch docs here

如果使用的問題給出的例子中我

for _ in range(5): 
    x = scipy.linalg.solve_continuous_are(A, B, Q, R) 
    Res = [email protected] + [email protected] + q - [email protected]@ np.linalg.solve(r,b.T)@ x 
    print(Res) 

替換最後一個循環我得到(窗口10,py3.5.2)

[[ 2.32314924e-05 -2.55086270e-05 -7.66709854e-06 -9.01878229e-06] 
[ -2.62447211e-05 2.61182140e-05 8.27328768e-06 1.00345896e-05] 
[ -7.92257197e-06 8.57094892e-06 2.50908488e-06 3.05714639e-06] 
[ -9.51046241e-06 9.80847472e-06 3.13103374e-06 3.60747799e-06]] 
[[ 2.32314924e-05 -2.55086270e-05 -7.66709854e-06 -9.01878229e-06] 
[ -2.62447211e-05 2.61182140e-05 8.27328768e-06 1.00345896e-05] 
[ -7.92257197e-06 8.57094892e-06 2.50908488e-06 3.05714639e-06] 
[ -9.51046241e-06 9.80847472e-06 3.13103374e-06 3.60747799e-06]] 
[[ 2.32314924e-05 -2.55086270e-05 -7.66709854e-06 -9.01878229e-06] 
[ -2.62447211e-05 2.61182140e-05 8.27328768e-06 1.00345896e-05] 
[ -7.92257197e-06 8.57094892e-06 2.50908488e-06 3.05714639e-06] 
[ -9.51046241e-06 9.80847472e-06 3.13103374e-06 3.60747799e-06]] 
[[ 2.32314924e-05 -2.55086270e-05 -7.66709854e-06 -9.01878229e-06] 
[ -2.62447211e-05 2.61182140e-05 8.27328768e-06 1.00345896e-05] 
[ -7.92257197e-06 8.57094892e-06 2.50908488e-06 3.05714639e-06] 
[ -9.51046241e-06 9.80847472e-06 3.13103374e-06 3.60747799e-06]] 
[[ 2.32314924e-05 -2.55086270e-05 -7.66709854e-06 -9.01878229e-06] 
[ -2.62447211e-05 2.61182140e-05 8.27328768e-06 1.00345896e-05] 
[ -7.92257197e-06 8.57094892e-06 2.50908488e-06 3.05714639e-06] 
[ -9.51046241e-06 9.80847472e-06 3.13103374e-06 3.60747799e-06]] 

僅供參考,返回的解決方案

array([[-3449.15531305, 4097.1707738 , 1142.52971904, 1566.51333847], 
     [ 4097.1707738 , -4863.70533241, -1356.66524959, -1860.15980716], 
     [ 1142.52971904, -1356.66524959, -378.32586814, -518.71965102], 
     [ 1566.51333847, -1860.15980716, -518.71965102, -711.21062988]])