Konvolusi, Fast Fourier Transform, dan Polinomial (2022)
(alvarorevuelta.com)- Jika polinomial berderajat besar diekspansi dengan cara ala sekolah menengah, semua pasangan suku harus dikalikan, sehingga biaya O(n²) cepat menjadi bottleneck
- Perkalian vektor koefisien polinomial sama dengan konvolusi sinyal diskret, dan hasil dari
[2, 3, 4]dan[5, 6, 7]adalah[10, 27, 52, 45, 28] - DFT memindahkan sinyal diskret ke domain frekuensi, dan FFT menghitung transformasi yang sama dalam O(n log n), sehingga membuat perbedaan pada input besar
- Konvolusi di domain waktu berubah menjadi perkalian per elemen di domain frekuensi, jadi dengan mentransformasikannya memakai FFT, mengalikannya, lalu mengembalikannya dengan IFFT, perkalian polinomial dapat diproses lebih cepat
- Pada derajat kecil, biaya pulang-pergi FFT/IFFT dapat meniadakan keuntungannya, tetapi semakin besar derajatnya, metode FFT semakin efisien
Mengapa perkalian polinomial menjadi lambat
- Polinomial
P(x)dinyatakan sebagai bentuk penjumlahan suku-suku berupa koefisiena_kdan pangkat dari variabelx- Contoh
P(x)=5x²+2x+9adalah polinomial berderajat 2 - Vektor koefisien dapat ditampilkan sebagai
[5, 2, 9]atau[9, 2, 5], tergantung notasinya
- Contoh
- Penjumlahan dan pengurangan relatif sederhana karena cukup menjumlahkan atau mengurangkan suku dengan derajat yang sama
- Di Python, kita dapat mengiterasi setiap koefisien dengan
zip(p, q)lalu menghitunga + bataua - b - Jika derajatnya berbeda,
zip_longestdapat digunakan
- Di Python, kita dapat mengiterasi setiap koefisien dengan
- Perkalian membutuhkan setiap suku dikalikan satu sama lain lalu suku-suku dengan derajat yang sama dijumlahkan kembali, sehingga jumlah komputasinya membesar
- Hasil dari
(2x²+3x+4) × (5x²+6x+7)adalah10x⁴+27x³+52x²+45x+28 - Kompleksitas metode ini adalah O(n²), dan semakin besar derajatnya, semakin banyak perkalian yang diperlukan
- Hasil dari
Vektor koefisien dan konvolusi
- Dalam domain diskret, konvolusi dua sinyal
pdanqdidefinisikan sebagaiy[n]=Σ p[k]·q[n-k] - Perhitungannya dilakukan dengan membalik
q, lalu menggesernya dari kiri ke kanan di atasp, sambil menjumlahkan hasil kali elemen yang saling tumpang tindih - Contoh sinyalnya adalah sebagai berikut
p = [2, 3, 4]q = [5, 6, 7]
- Jika
qdibalik lalu digeser, setiap koefisien output terbentuk dalam urutan berikut2×5 = 102×6 + 3×5 = 272×7 + 3×6 + 4×5 = 523×7 + 4×6 = 454×7 = 28
- Hasil konvolusinya adalah
y = [10, 27, 52, 45, 28]- Ini sama dengan koefisien dari
10x⁴+27x³+52x²+45x+28yang diperoleh melalui perkalian polinomial - Karena itu, perkalian polinomial dapat dilihat sebagai konvolusi vektor koefisien
- Ini sama dengan koefisien dari
Transformasi Fourier dan FFT
- Transformasi Fourier mengubah sinyal dari domain waktu ke domain frekuensi
- Dari sudut pandang waktu, sinyal dilihat sebagai nilai pada titik waktu tertentu
- Dari sudut pandang frekuensi, sinyal ditafsirkan sebagai jumlah berbagai frekuensi osilasi yang berbeda
- Frekuensi osilasi direpresentasikan dengan sinus dan kosinus, masing-masing memiliki koefisien dan fase
- Jika FFT diterapkan pada gelombang sinus murni 5Hz, di domain frekuensi ia tampak seperti delta pada posisi 5Hz
- Ini menunjukkan bahwa gelombang sinus di domain waktu dapat direpresentasikan oleh satu sinus 5Hz
- Istilah terkait dibedakan sebagai berikut
- Fourier Transform(FT): transformasi Fourier yang didefinisikan pada domain kontinu
- Discrete Fourier Transform(DFT): transformasi Fourier yang didefinisikan untuk sinyal diskret
- Fast Fourier Transform(FFT): algoritme yang menghitung DFT dalam O(n log n), bukan O(n²)
- DFT mengubah sinyal waktu diskret
x[n]menjadiX[k]di domain frekuensi- Setiap
X[k]dihitung dengan mengalikan sampel input dengan bilangan kompleks yang merepresentasikan frekuensi tertentu, lalu menjumlahkannya
- Setiap
Mengubahnya menjadi perkalian di domain frekuensi
- Keunggulan utama DFT dan domain frekuensi adalah konvolusi dapat diubah menjadi perkalian per elemen
- Melakukan konvolusi dua sinyal di domain waktu sama dengan mengalikan dua sinyal di domain frekuensi
- Perkalian dapat dihitung lebih cepat daripada konvolusi
- Prosedur untuk melakukan perkalian polinomial dengan cepat adalah sebagai berikut
- Ubah polinomial ke domain frekuensi dengan FFT: O(n log n)
- Kalikan per elemen di domain frekuensi: O(n)
- Ubah hasilnya kembali ke domain waktu dengan IFFT: O(n log n)
- Secara keseluruhan, dengan menggunakan FFT, perkalian polinomial dapat dilakukan dengan kompleksitas O(n log n)
- Untuk polinomial besar, ini lebih cepat daripada perkalian ala sekolah menengah O(n²)
Implementasi Python dan benchmark
multiply_naivemenggunakan loop ganda untuk mengalikan semua pasangan koefisien dan menambahkannya ke posisi hasili + j- Panjang hasilnya adalah
len(p) + len(q) - 1 - Kompleksitasnya adalah O(n²)
- Panjang hasilnya adalah
multiply_fftmelakukan perkalian koefisien berbasis FFT/IFFT- Ia menghitung panjang berupa pangkat dua yang setidaknya sebesar
len(p) + len(q) - 1agar hasilnya dapat ditampung - Kedua input dipadding dengan
np.pad - Nilai yang ditransformasikan dengan
np.fft.fftdikalikan per elemen - Setelah dikembalikan dengan
np.fft.ifft, bagian realnya dibulatkan dan dikonversi menjadi koefisien bilangan bulat
- Ia menghitung panjang berupa pangkat dua yang setidaknya sebesar
- Pada contoh input
p = [2, 3, 4],q = [5, 6, 7], kedua metode mengembalikan[10, 27, 52, 45, 28] - Dalam benchmark, metode FFT dibandingkan dengan
multiply_convolve, yang menggunakannp.convolve, bukanmultiply_naive- Ini karena loop Python pada
multiply_naivelambat, sehingga sulit dibandingkan secara langsung dengan metode FFT yang menggunakannp.fft.fft np.convolvemelakukan operasi yang sama dengan kode C tingkat rendah
- Ini karena loop Python pada
- Derajat dinaikkan dalam rentang
range(1, 30000, 1000), dan pada setiap derajat dibuat dua polinomial dengan koefisien acak antara 1 hingga 999999- Setiap metode diukur waktu rata-ratanya dengan
n_runs = 5 - Pada derajat rendah, metode FFT mungkin tidak menguntungkan karena biaya transformasi pulang-pergi FFT/IFFT
- Ketika derajat meningkat, metode FFT menunjukkan hasil yang jauh lebih efisien
- Setiap metode diukur waktu rata-ratanya dengan
1 komentar
Komentar Hacker News
Yang selalu mengganggu dari penjelasan seperti ini adalah biasanya mereka melupakan galat numerik
Perkalian koefisien tidak bisa begitu saja diabstraksikan sebagai “waktu konstan”. Kalau mau begitu, dari awal seluruh operasi perkalian juga bisa diabstraksikan dengan cara yang sama. Jika memperhitungkan presisi numerik, kompleksitasnya lebih mendekati O(n (log n)^3) [1]
[1]: http://numbers.computation.free.fr/Constants/Algorithms/fft....
[1] One-Dimensional Quaternion Discrete Fourier Transform and an Approach to Its Fast Computation:
https://www.mdpi.com/2079-9292/12/24/4974
[2] Convolution Theorems for Quaternion Fourier Transform: Properties and Applications:
https://onlinelibrary.wiley.com/doi/10.1155/2013/162769
[3] On the Matrix Form of the Quaternion Fourier Transform and Quaternion Convolution:
https://arxiv.org/abs/2307.01836
Dengan metode ini, kita bisa mengalikan angka-angka panjang. Intinya adalah perkalian polinomial sama dengan perkalian angka panjang biasa tanpa carry
Misalnya jika ada angka 1000 digit, setiap digit dijadikan koefisien dari polinomial dengan 1000 elemen. Lalu polinomial-polynomial ini bisa dikalikan dengan metode FFT yang dijelaskan dalam tulisan. Untuk mengubah hasilnya kembali menjadi angka, carry harus diproses. Jika suatu elemen lebih besar dari 10, kelebihannya diteruskan ke digit berikutnya, lalu koefisien-koefisiennya diubah menjadi angka
Gagasan dasarnya seperti ini, dan ada bagian-bagian halus terkait presisi yang dibutuhkan untuk carry serta jaminan bahwa hasil FFT tetap benar jika dibulatkan ke bilangan bulat terdekat. Cara seperti inilah yang dipakai GMP, pustaka utama di bidang ini, untuk perkalian bilangan besar
Saya penasaran seberapa besar angkanya agar ini benar-benar berarti, dan dipakai untuk apa
Kalau belum menontonnya, video ini bagus untuk dilihat
https://youtu.be/h7apO7q16V0?si=bmgUEMTQSqU3flIv
Video itu benar-benar luar biasa dalam menurunkan algoritma FFT dari perkalian polinomial. Saya menontonnya lagi kira-kira setiap 6 bulan
Sifat FFT bahwa “konvolusi adalah perkalian titik-demi-titik” juga berlaku pada grup perkalian siklik apa pun. Untuk penurunan yang lebih aljabar, lihat https://www.sciencedirect.com/science/article/pii/S002200007...
Ini kadang disebut “FFT harmonik”, dan ada juga FFT non-harmonik: [LCH14] “additive NTT” di atas GF(2^n), [HLP24] circle FFT di atas lingkaran satuan X^2+Y^2=1 pada medan hingga, serta [BCKL21] ecfft di atas deret isogeni kurva eliptik
[LCH14]: https://arxiv.org/abs/1404.3458
[HLP24]: https://eprint.iacr.org/2024/278
[BCKL21]: https://arxiv.org/pdf/2107.08473
Siapa orang pertama yang mengusulkan penggunaan FFT untuk perkalian polinomial yang lebih cepat?
Belakangan saya penasaran dan mencoba mencarinya; meski tidak terlalu berhasil menelusuri sitasinya, saya bisa mundur sampai makalah David Eppstein tahun 1995 [0]. Di sana, ini digunakan untuk menyelesaikan masalah jumlah parsial secara efisien setelah pembaruan inkremental. Saya cukup yakin hal ini pasti sudah ada lebih awal di TAOCP milik Knuth
Fakta bahwa masalah jumlah parsial eksak yang mengizinkan pengulangan bisa diselesaikan dalam waktu subeksponensial dengan perkalian polinomial FFT juga cukup mengejutkan [1]. Yang penting, algoritma ini O(N log N), tetapi N di sini bukan ukuran himpunan, melainkan elemen maksimum, jadi ini bukan semacam kontra-contoh untuk P ≠ NP
[0] https://escholarship.org/content/qt6sd695gn/qt6sd695gn.pdf
[1] https://x.com/festivitymn/status/1788362552998580473?s=46&t=...
Strassen diketahui menemukan pendekatan ala Pollard pada 1968, tetapi tidak ada catatan tertulisnya. Selain itu, meskipun bukan kelahiran FFT itu sendiri, perlu juga dilihat bahwa makalah Cooley-Tukey tahun 1965 [4] benar-benar memicu penelitian tentang FFT dan aplikasinya. Ini terjadi beberapa tahun setelahnya
[1] https://doi.org/10.1090/S0025-5718-1971-0301966-0
[2] https://doi.org/10.1016/S0022-0000(71)80014-4
[3] https://doi.org/10.1007/BF02242355
[4] https://doi.org/10.1090/S0025-5718-1965-0178586-1
https://www.cis.rit.edu/class/simg716/FFT_Fun_Profit.pdf
Saya pikir semua machine learning adalah pekerjaan menyelesaikan persamaan konvolusi
Makalah ini membahasnya dalam konteks reinforcement learning https://arxiv.org/abs/1712.06115, tetapi sebagian besar pendekatan cocok masuk ke paradigma ini
Saya baru saja mengimplementasikan algoritma (matrix profile) yang menggunakan FFT untuk menghitung inner product pada kumpulan besar subsekuens deret waktu. Panjang deret waktu n bisa mencapai ratusan juta
Perhitungan konvolusi cepat dengan FFT mengurangi waktu komputasi dari O(n) menjadi O(log n), dan pada skala ini peningkatan kecepatannya luar biasa. Jika memakai GPU, bisa lebih cepat lagi, misalnya memproses 10 juta titik data dalam 0,1 detik di laptop
“Trik” inti operasi ini tampaknya adalah pemahaman berikut:
Ada sifat bahwa “melakukan konvolusi dua sinyal di domain waktu sama dengan mengalikan dua sinyal di domain frekuensi”, dan FFT memungkinkan kita mengubah dari domain waktu ke domain frekuensi. Jadi polinomial dipindahkan ke domain frekuensi dengan FFT, lalu di domain itu cukup dilakukan perkalian. Itu lebih cepat daripada konvolusi. Saya penasaran apakah ini memperjelas langkah yang hilang; kalau ada bagian yang terlewat, tulisannya bisa diperbarui
Kalau begitu, apakah faktorisasi bilangan bulat adalah dekonvolusi diskret? Saya penasaran apakah dengan menempatkan representasi FFT, yaitu operasi kebalikan dari perkalian titik demi titik, berdampingan dengan tableax, yaitu perkalian panjang biasa/penjumlahan carry, simetrinya bisa dipecah sehingga kita memperoleh informasi yang cukup untuk algoritma cepat
Tentu saja, perkalian polinomial secara naif lambat terhadap derajat polinomial. Namun, kapan sebenarnya kita perlu menangani dua polinomial derajat 100?
Karena alasan ini, ada kesan bahwa sistem aljabar komputer tidak menggunakan metode seperti ini
https://www.youtube.com/watch?v=CcZf_7Fb4Us
https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_cor... adalah salah satu contohnya
[1]: https://github.com/8051enthusiast/delsum
Tulisan blog Hazy Research dari 2020–2023 memuat banyak informasi tentang pendekatan ini
“(...) dalam riset fisika, saya pernah menangani ekspresi sepanjang hampir 1 terabyte dengan lebih dari 100 juta suku”