Autokorelasi Python vs Julia

19

Saya mencoba melakukan autokorelasi menggunakan Julia dan membandingkannya dengan hasil Python. Kenapa mereka memberikan hasil yang berbeda?

Kode julia

using StatsBase

t = range(0, stop=10, length=10)
test_data = sin.(exp.(t.^2))

acf = StatsBase.autocor(test_data)

memberi

10-element Array{Float64,1}:
  1.0                   
  0.13254954979179642   
 -0.2030283419321465    
  0.00029587850872956104
 -0.06629381497277881   
  0.031309038331589614  
 -0.16633393452504994   
 -0.08482388975165675   
  0.0006905628640697538 
 -0.1443650483145533

Kode python

from statsmodels.tsa.stattools import acf
import numpy as np

t = np.linspace(0,10,10)
test_data = np.sin(np.exp(t**2))

acf_result = acf(test_data)

memberi

array([ 1.        ,  0.14589844, -0.10412699,  0.07817509, -0.12916543,
       -0.03469143, -0.129255  , -0.15982435, -0.02067688, -0.14633346])
Ross Mariano
sumber
1
Cetak data uji dalam kedua kasus
Gila Fisikawan

Jawaban:

26

Ini karena Anda test_databerbeda:

Python:

array([ 0.84147098, -0.29102733,  0.96323736,  0.75441021, -0.37291918,
        0.85600145,  0.89676529, -0.34006519, -0.75811102, -0.99910501])

Julia:

[0.8414709848078965, -0.2910273263243299, 0.963237364649543, 0.7544102058854344,
 -0.3729191776326039, 0.8560014512776061, 0.9841238290665676, 0.1665709194875013,
 -0.7581110212957692, -0.9991050130774393]

Ini terjadi karena Anda mengambil sinjumlah yang sangat besar. Misalnya, dengan angka terakhir tmenjadi 10, exp(10^2)adalah ~ 2.7 * 10 ^ 43. Pada skala ini, ketidakakuratan floating point adalah sekitar 3 * 10 ^ 9. Jadi, bahkan jika bit paling tidak signifikan berbeda untuk Python dan Julia, sinnilainya akan jauh.

Bahkan, kita dapat memeriksa nilai-nilai biner yang mendasari array awal t. Misalnya, mereka berbeda dalam nilai terakhir ketiga:

Julia:

julia> reinterpret(Int, range(0, stop=10, length=10)[end-2])
4620443017702830535

Python:

>>> import struct
>>> s = struct.pack('>d', np.linspace(0,10,10)[-3])
>>> struct.unpack('>q', s)[0]
4620443017702830536

Kita memang bisa melihat bahwa mereka tidak setuju dengan tepat satu mesin epsilon. Dan jika kita menggunakan Julia, ambil sinnilai yang diperoleh oleh Python:

julia> sin(exp(reinterpret(Float64, 4620443017702830536)^2))
-0.3400651855865199

Kami mendapatkan nilai yang sama dengan Python.

Jakob Nissen
sumber
9

Hanya untuk sedikit memperluas jawaban (menambahkan sebagai jawaban karena terlalu panjang untuk komentar). Di Julia Anda memiliki yang berikut ini:

julia> t = collect(range(0, stop=10, length=10))
10-element Array{Float64,1}:
  0.0               
  1.1111111111111112
  2.2222222222222223
  3.3333333333333335
  4.444444444444445 
  5.555555555555555 
  6.666666666666667 
  7.777777777777778 
  8.88888888888889  
 10.0               

julia> t .- [10*i / 9 for i in 0:9]
10-element Array{Float64,1}:
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0

sementara di Python:

>>> t = np.linspace(0,10,10)
>>> t - [10*i/9 for i in range(10)]
array([0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
       0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 8.8817842e-16,
       0.0000000e+00, 0.0000000e+00])

dan Anda melihat bahwa angka ke-8 dalam Python adalah perkiraan yang tidak akurat 70/9, sedangkan di Julia dalam kasus ini Anda mendapatkan urutan perkiraan terdekat untuk 10*i/9menggunakan Float64.

Jadi sepertinya karena urutan asli berbeda Anda sisanya mengikuti apa yang @Jakob Nissen berkomentar.

Namun hal-hal tidak sesederhana itu. Sebagai expfungsi dalam Julia dan Python sedikit berbeda dalam apa yang mereka hasilkan. Lihat Python:

>>> from math import exp
>>> from mpmath import mp
>>> mp.dps = 1000
>>> float(mp.exp((20/3)**2) - exp((20/3)**2))
-1957.096392544307

sementara di Julia:

julia> setprecision(1000)
1000

julia> Float64(exp(big((20/3)^2)) - exp((20/3)^2))
2138.903607455693

julia> Float64(exp(big((20/3)^2)) - nextfloat(exp((20/3)^2)))
-1957.096392544307

(Anda dapat memeriksa bahwa keduanya (20/3)^2sama Float64dalam Julia dan Python).

Jadi dalam hal ini dengan expPython sedikit lebih akurat daripada Julia. Oleh karena itu bahkan memperbaiki t(yang mudah dengan menggunakan pemahaman dalam Python, bukan linspace) tidak akan membuat ACF menjadi sama.

Kesimpulannya adalah apa yang dikomentari @Jakob Nissen untuk nilai sebesar itu, hasilnya akan sangat dipengaruhi oleh ketidakakuratan numerik.

Bogumił Kamiński
sumber