Konvolüsyon, Hızlı Fourier Dönüşümü ve Polinomlar (2022)
(alvarorevuelta.com)- Büyük dereceli polinomları lise yöntemiyle açtığınızda tüm terim çiftlerini çarpmak gerektiğinden O(n²) maliyeti hızla darboğaza dönüşür
- Polinomların katsayı vektörü çarpımı, ayrık sinyallerdeki konvolüsyon ile aynıdır;
[2, 3, 4]ve[5, 6, 7]için sonuç[10, 27, 52, 45, 28]olur - DFT, ayrık sinyali frekans alanına taşır; FFT ise aynı dönüşümü O(n log n) zamanda hesaplayarak büyük girdilerde fark yaratır
- Zaman alanındaki konvolüsyon, frekans alanında eleman bazında çarpıma dönüştüğünden, FFT ile dönüştürüp çarptıktan sonra IFFT ile geri dönmek polinom çarpımını daha hızlı işleyebilir
- Küçük derecelerde FFT/IFFT gidiş-dönüş maliyeti kazanımı dengeleyebilir; ancak derece büyüdükçe FFT yöntemi daha verimli olur
Polinom çarpımı neden yavaşlar?
- Bir polinom
P(x), katsayılara_kile değişkenx’in kuvvet terimlerinin toplamı olarak ifade edilir- Örnek
P(x)=5x²+2x+9, derecesi 2 olan bir polinomdur - Katsayı vektörü, gösterim biçimine göre
[5, 2, 9]veya[9, 2, 5]gibi yazılabilir
- Örnek
- Toplama ve çıkarma, aynı derecedeki terimleri toplayıp çıkarmakla yapıldığından görece basittir
- Python’da
zip(p, q)ile her katsayı üzerinde dolaşıpa + bveyaa - bhesaplanabilir - Dereceler farklıysa
zip_longestkullanılabilir
- Python’da
- Çarpımda her terimi birbiriyle çarpıp sonra aynı derecedeki terimleri yeniden toplamak gerektiği için hesaplama miktarı artar
(2x²+3x+4) × (5x²+6x+7)sonucu10x⁴+27x³+52x²+45x+28olur- Bu yöntemin karmaşıklığı O(n²)’dir ve derece büyüdükçe gereken çarpım sayısı artar
Katsayı vektörü ve konvolüsyon
- Ayrık alanda iki sinyal
pveqiçin konvolüsyony[n]=Σ p[k]·q[n-k]olarak tanımlanır - Hesaplama,
qters çevrilippüzerinde soldan sağa kaydırılırken çakışan elemanların çarpımlarını toplama biçiminde yapılır - Örnek sinyaller şöyledir
p = [2, 3, 4]q = [5, 6, 7]
qters çevrilip kaydırıldığında her çıktı katsayısı şu sırayla oluşur2×5 = 102×6 + 3×5 = 272×7 + 3×6 + 4×5 = 523×7 + 4×6 = 454×7 = 28
- Konvolüsyon sonucu
y = [10, 27, 52, 45, 28]olur- Bu, polinom çarpımından elde edilen
10x⁴+27x³+52x²+45x+28katsayılarıyla aynıdır - Dolayısıyla polinom çarpımı, katsayı vektörlerinin konvolüsyonu olarak görülebilir
- Bu, polinom çarpımından elde edilen
Fourier dönüşümü ve FFT
- Fourier dönüşümü, sinyali zaman alanından frekans alanına dönüştürür
- Zaman bakış açısından sinyal, belirli anlardaki değerleriyle görülür
- Frekans bakış açısından sinyal, farklı titreşim frekanslarının toplamı olarak yorumlanır
- Titreşim frekansları sinüs ve kosinüslerle ifade edilir; her birinin katsayısı ve fazı vardır
- 5Hz saf sinüs dalgasına FFT uygulandığında, frekans alanında 5Hz konumunda delta gibi görünür
- Bu, zaman alanındaki sinüs dalgasının tek bir 5Hz sinüsle ifade edilebildiğini gösterir
- İlgili terimler şöyle ayrılır
- Fourier Transform(FT): Sürekli alanda tanımlanan Fourier dönüşümü
- Discrete Fourier Transform(DFT): Ayrık sinyaller için tanımlanan Fourier dönüşümü
- Fast Fourier Transform(FFT): DFT’yi O(n²) yerine O(n log n) zamanda hesaplayan algoritma
- DFT, ayrık zaman sinyali
x[n]’i frekans alanındakiX[k]’ye dönüştürür- Her
X[k], giriş örneklerinin belirli bir frekansı temsil eden karmaşık sayılarla çarpılıp toplanmasıyla hesaplanır
- Her
Frekans alanında çarpıma dönüştürmek
- DFT’nin ve frekans alanının temel avantajı, konvolüsyonu eleman bazında çarpıma dönüştürebilmesidir
- Zaman alanında iki sinyali konvolüsyona sokmak, frekans alanında iki sinyali çarpmakla aynıdır
- Çarpım, konvolüsyondan daha hızlı hesaplanabilir
- Polinom çarpımını hızlı yapmak için izlenen prosedür şöyledir
- Polinomları FFT ile frekans alanına dönüştürmek: O(n log n)
- Frekans alanında eleman bazında çarpmak: O(n)
- Sonucu IFFT ile yeniden zaman alanına dönüştürmek: O(n log n)
- Genel olarak FFT kullanıldığında polinom çarpımı O(n log n) karmaşıklıkla yapılabilir
- Büyük polinomlarda, lise yöntemi O(n²) çarpımdan daha hızlıdır
Python uygulaması ve benchmark
multiply_naive, iç içe döngülerle tüm katsayı çiftlerini çarpıp sonuç konumui + j’ye ekler- Sonuç uzunluğu
len(p) + len(q) - 1olur - Karmaşıklığı O(n²)’dir
- Sonuç uzunluğu
multiply_fft, katsayı çarpımını FFT/IFFT tabanlı gerçekleştirir- Sonuç uzunluğunu kapsayabilmek için
len(p) + len(q) - 1veya daha büyük, 2’nin kuvveti olan bir uzunluk hesaplar - İki girdiyi
np.padile doldurur np.fft.fftile dönüştürülen değerleri eleman bazında çarparnp.fft.ifftile geri döndürdükten sonra gerçek kısmı yuvarlayarak tam sayı katsayılara dönüştürür
- Sonuç uzunluğunu kapsayabilmek için
- Örnek girdi
p = [2, 3, 4],q = [5, 6, 7]için iki yöntem de[10, 27, 52, 45, 28]döndürür - Benchmark’ta
multiply_naiveyerinenp.convolvekullananmultiply_convolveile FFT yöntemi karşılaştırılır- Bunun nedeni
multiply_naive’in Python döngülerinin yavaş olması venp.fft.fftkullanan FFT yöntemiyle doğrudan karşılaştırmanın zor olmasıdır np.convolveaynı işlemi düşük seviyeli C koduyla gerçekleştirir
- Bunun nedeni
- Derece,
range(1, 30000, 1000)aralığında artırılır ve her derecede 1 ile 999999 arasında rastgele katsayılara sahip iki polinom oluşturulur- Her yöntem için
n_runs = 5ile ortalama süre ölçülür - Düşük derecelerde FFT/IFFT gidiş-dönüş dönüşüm maliyeti nedeniyle FFT yöntemi avantajlı olmayabilir
- Derece arttıkça FFT yöntemi çok daha verimli sonuçlar gösterir
- Her yöntem için
1 yorum
Hacker News yorumları
Bu tür açıklamalarda beni hep rahatsız eden şey, genelde sayısal hataların unutulması.
Katsayı çarpımını öylece “sabit zamanlı” diye soyutlayamazsınız. Bunu yapacaksanız en baştan çarpmanın tamamını soyutlamak da aynı kapıya çıkar. Sayısal hassasiyet hesaba katıldığında O(n (log n)^3)’e daha yakındır [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
Bu yöntemle uzun sayıları birbiriyle çarpabilirsiniz. Kilit nokta, polinom çarpımının elde (carry) yapmadan yapılan sıradan uzun sayı çarpımıyla aynı olması.
Örneğin 1000 basamaklı bir sayınız varsa, her basamağı 1000 elemanlı bir polinomun katsayısı yaparsınız. Sonra yazıda anlatılan FFT yöntemiyle bu polinomları çarpabilirsiniz. Sonucu tekrar sayıya çevirmek için elde işlemini yapmanız gerekir. Bir eleman 10’dan büyükse fazlalığı bir sonraki basamağa aktarır, katsayıları da sayıya çevirirsiniz.
Temel fikir bu; elde işlemi için gereken hassasiyet ve FFT sonucunu en yakın tamsayıya yuvarlamanın doğru sonucu vereceğini garanti etme kısmında ince noktalar var. Bu yöntem, alanın önde gelen kütüphanesi GMP’nin büyük sayı çarpımı yapma biçimidir
Pratikte anlamlı olması için sayıların ne kadar büyük olması gerektiğini ve nerelerde kullanıldığını merak ediyorum
Henüz izlemediyseniz bu videoya bakmanız iyi olur
https://youtu.be/h7apO7q16V0?si=bmgUEMTQSqU3flIv
Polinom çarpımı üzerinden FFT algoritmasını türetiyor; gerçekten harika. Yaklaşık 6 ayda bir tekrar izliyorum
FFT’nin “konvolüsyon noktasal çarpımdır” özelliği, herhangi bir döngüsel çarpma grubu için de geçerlidir. Daha cebirsel bir türetme için https://www.sciencedirect.com/science/article/pii/S002200007... bakın
Buna bazen “harmonik FFT” denir; harmonik olmayan FFT’ler de vardır: GF(2^n) üzerinde [LCH14] “additive NTT”, sonlu cisimdeki birim çember X^2+Y^2=1 üzerinde [HLP24] circle FFT, eliptik eğri izojeni dizileri üzerinde [BCKL21] ecfft
[LCH14]: https://arxiv.org/abs/1404.3458
[HLP24]: https://eprint.iacr.org/2024/278
[BCKL21]: https://arxiv.org/pdf/2107.08473
Daha hızlı polinom çarpımı için FFT kullanmayı ilk kim önermişti?
Geçenlerde merak edip baktım; atıf zincirini çok iyi izleyemesem de David Eppstein’in 1995 tarihli makalesine [0] kadar geri gidebildim. Orada bunu, artımlı güncellemelerden sonra kısmi toplam problemini verimli biçimde çözmek için kullanıyor. Eminim Knuth’un TAOCP’sinde daha da erken bir yerde vardır.
FFT polinom çarpımıyla, tekrara izin veren kesin kısmi toplam probleminin altüssel zamanda çözülebilmesi de epey şaşırtıcıydı [1]. Önemli nokta şu: Bu algoritma O(N log N), ama buradaki N kümenin boyutu değil, en büyük eleman; dolayısıyla P ≠ NP’ye karşı bir örnek falan değil.
[0] https://escholarship.org/content/qt6sd695gn/qt6sd695gn.pdf
[1] https://x.com/festivitymn/status/1788362552998580473?s=46&t=...
Strassen’in 1968’de Pollard tarzı yaklaşımı keşfettiği söylenir, ama yazılı kayıt yok. Ayrıca FFT’nin bizzat doğuşu olmasa bile, Cooley-Tukey’nin 1965 tarihli makalesinin [4] FFT ve uygulamaları üzerine araştırmaları gerçekten ateşlediğini de görmek gerekir. Bunlar ondan birkaç yıl sonra oluyor.
[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
Bence tüm makine öğrenmesi, konvolüsyon denklemleri çözme işidir.
Bu makale konuyu pekiştirmeli öğrenme bağlamında ele alıyor https://arxiv.org/abs/1712.06115, ama yaklaşımların çoğu bu paradigmanın içine oturuyor.
Az önce FFT kullanarak, zaman serisi alt dizilerinin büyük bir kümesi için iç çarpımları hesaplayan bir algoritma (matrix profile) implemente ettim. Zaman serisi uzunluğu n yüz milyonlar mertebesine çıkabiliyor.
FFT ile hızlı konvolüsyon hesabı sayesinde hesaplama süresi O(n)’den O(log n)’ye düşüyor; bu ölçekte hızlanma muazzam. GPU da kullanınca daha da hızlanıyor; örneğin dizüstünde 10 milyon veri noktasını 0,1 saniyede işlemek gibi.
Bu işlemin temel “numarası” şu fark ediş gibi görünüyor:
“Zaman alanında iki sinyalin konvolüsyonunu yapmak, frekans alanında iki sinyali çarpmakla aynıdır” şeklinde bir özellik var; FFT de zaman alanından frekans alanına geçmemizi sağlar. Bu yüzden polinomları FFT ile frekans alanına taşıyıp, o alanda yalnızca çarpma yapmak yeterlidir. Konvolüsyondan daha hızlıdır. Eksik adımı bunun netleştirip netleştirmediğini merak ediyorum; eksik kalan bir yer varsa yazıyı güncelleyebilirim.
Öyleyse tamsayı çarpanlara ayırma ayrık dekonvolüsyon mudur? FFT gösterimini, yani noktasal çarpmanın ters işlemini, tableax ile, yani klasik uzun çarpma/elde toplama ile yan yana koyunca simetri bozulur da hızlı bir algoritma için yeterli bilgi elde edilebilir mi, merak ediyorum.
Elbette naif polinom çarpımı, polinom derecesine göre yavaştır. Peki pratikte iki 100. dereceden polinom ile uğraşmak ne zaman gerekir?
Bu nedenle bilgisayar cebiri sistemlerinde bu yöntemin kullanılmadığı izlenimi var
https://www.youtube.com/watch?v=CcZf_7Fb4Us
https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_cor... buna bir örnektir
[1]: https://github.com/8051enthusiast/delsum
Hazy Research’ün 2020~2023 arasındaki blog yazılarında bu yaklaşım hakkında çok bilgi var
“(...) fizik araştırmalarında neredeyse 1 terabayt uzunluğunda ve 100 milyondan fazla terim içeren ifadelerle uğraştığım oldu”