Penafian: Saya tahu topik ini lebih lama, tetapi jika seseorang mencari "konvolusi cepat rentang dinamis tinggi" atau serupa ini adalah salah satu yang pertama dari hanya beberapa hasil yang layak. Saya ingin berbagi wawasan saya tentang topik ini sehingga mungkin membantu seseorang di masa depan. Saya minta maaf jika saya mungkin menggunakan istilah yang salah dalam jawaban saya, tetapi semua yang saya temukan pada topik ini agak kabur dan menyebabkan kebingungan bahkan di utas ini. Saya harap pembaca akan mengerti juga.
Konvolusi langsung sebagian besar akurat ke presisi mesin untuk setiap titik, yaitu kesalahan relatif biasanya kira-kira atau mendekati 1.e-16 untuk presisi ganda untuk setiap titik hasil. Setiap titik memiliki 16 digit yang benar. Namun kesalahan pembulatan dapat signifikan untuk konvolusi besar yang tidak tipikal, dan secara tegas seseorang harus berhati-hati dengan pembatalan dan menggunakan sesuatu seperti penjumlahan Kahan dan tipe data presisi yang cukup tinggi, tetapi dalam praktiknya kesalahan tersebut hampir selalu optimal.
Kesalahan konvolusi FFT selain dari kesalahan pembulatan adalah kesalahan "relatif global", yang berarti kesalahan di setiap titik tergantung pada presisi mesin dan nilai puncak hasilnya. Misalnya jika nilai puncak dari hasilnya adalah 2.e9
, maka kesalahan absolut di setiap titik adalah2 ⋅109⋅10- 16= 2 ⋅10- 7. Jadi jika nilai dalam hasil seharusnya sangat kecil, katakanlah10- 9, kesalahan relatif pada titik itu bisa sangat besar. Konvolusi FFT pada dasarnya tidak berguna jika Anda memerlukan kesalahan relatif kecil di bagian hasil Anda, misalnya Anda memiliki peluruhan data yang agak eksponensial dan membutuhkan nilai yang akurat di bagian ekor. Menariknya jika konvolusi FFT tidak dibatasi oleh kesalahan itu, ia memiliki kesalahan pembulatan yang jauh lebih kecil dibandingkan dengan konvolusi langsung, karena Anda jelas melakukan penambahan / perkalian yang lebih sedikit. Inilah sebenarnya mengapa orang sering mengklaim konvolusi FFT lebih akurat, dan mereka dalam beberapa hal hampir benar, sehingga mereka bisa sangat bersikeras.
Sayangnya tidak ada perbaikan universal yang mudah untuk mendapatkan konvolusi yang cepat dan akurat, tetapi tergantung pada masalah Anda mungkin ada satu ... Saya telah menemukan dua:
Jika Anda memiliki kernel halus yang dapat didekati dengan baik oleh polinomial di bagian ekor, maka Metode Multipole Cepat kotak hitam dengan interpolasi Chebyshev mungkin menarik bagi Anda. Jika kernel Anda "baik" ini berfungsi dengan sangat sempurna: Anda mendapatkan kompleksitas komputasi linier (!) Dan akurasi presisi mesin. Jika ini cocok dengan masalah Anda, Anda harus menggunakannya. Namun tidak mudah untuk diimplementasikan.
Untuk beberapa kernel tertentu (saya pikir fungsi cembung, biasanya dari kepadatan probabilitas) Anda dapat menggunakan "pergeseran eksponensial" untuk mendapatkan kesalahan optimal di beberapa bagian ekor hasil. Ada tesis PHD dan github dengan implementasi python menggunakan itu secara sistematis, dan penulis menyebutnya konvolusi FFT akurat . Namun dalam kebanyakan kasus ini tidak terlalu berguna, karena ia akan kembali ke konvolusi langsung atau Anda tetap dapat menggunakan konvolusi FFT. Meskipun kode melakukannya secara otomatis, tentu saja itu bagus.
-------------------- EDIT: --------------------
Saya melihat sedikit pada algoritma Karatsuba (saya sebenarnya membuat implementasi kecil), dan bagi saya sepertinya memiliki perilaku kesalahan yang sama seperti konvolusi FFT, yaitu Anda mendapatkan kesalahan relatif terhadap nilai puncak hasil. Karena sifat membagi dan menaklukkan algoritma beberapa nilai di ekor hasil sebenarnya memiliki kesalahan yang lebih baik, tapi saya tidak melihat cara sistematis yang mudah untuk mengetahui mana atau dalam hal apa pun bagaimana menggunakan pengamatan ini. Sayang sekali, pada awalnya saya pikir Karatsuba mungkin sesuatu yang berguna di antara konvolusi langsung dan FFT. Tapi saya tidak melihat kasus penggunaan umum di mana Karatsuba harus lebih disukai daripada dua algoritma konvolusi umum.
Dan untuk menambah pergeseran eksponensial yang saya sebutkan di atas: Ada banyak kasus di mana Anda dapat menggunakannya untuk meningkatkan hasil konvolusi, tetapi sekali lagi ini bukan perbaikan universal. Saya benar-benar menggunakan ini bersama dengan konvolusi FFT untuk mendapatkan hasil yang cukup bagus (dalam kasus umum untuk semua input: pada kesalahan terburuk yang sama seperti konvolusi FFT normal, pada kesalahan relatif terbaik di setiap titik ke presisi mesin). Tetapi sekali lagi, ini hanya benar-benar berfungsi dengan baik untuk kernel dan data tertentu, tetapi bagi saya kernel dan data atau agak eksponensial dalam peluruhan.
convolve()
panggil sajafftconvolve()
sekarang, jika ukuran input besar. Tentukanmethod='direct'
jika Anda ingin mengarahkan.