Faltung, schnelle Fourier-Transformation und Polynome (2022)
(alvarorevuelta.com)- Wenn man Polynome hohen Grades nach der Schulmethode ausmultipliziert, müssen alle Paare von Termen multipliziert werden; die Kosten von O(n²) werden daher schnell zum Flaschenhals
- Die Multiplikation von Koeffizientenvektoren eines Polynoms entspricht der Faltung diskreter Signale; das Ergebnis von
[2, 3, 4]und[5, 6, 7]ist[10, 27, 52, 45, 28] - Die DFT überführt ein diskretes Signal in den Frequenzbereich, und die FFT berechnet dieselbe Transformation in O(n log n), was bei großen Eingaben den Unterschied macht
- Eine Faltung im Zeitbereich wird im Frequenzbereich zu einer elementweisen Multiplikation. Wandelt man also per FFT um, multipliziert und wandelt anschließend per IFFT zurück, lässt sich die Polynommultiplikation schneller durchführen
- Bei kleinen Graden können die Kosten für Hin- und Rücktransformation per FFT/IFFT den Vorteil aufheben, doch mit wachsendem Grad wird das FFT-Verfahren effizienter
Warum Polynommultiplikation langsam wird
- Ein Polynom
P(x)wird als Summe von Koeffizientena_kund Potenzen der Variablenxdargestellt- Das Beispiel
P(x)=5x²+2x+9ist ein Polynom zweiten Grades - Der Koeffizientenvektor kann je nach Schreibweise etwa als
[5, 2, 9]oder[9, 2, 5]dargestellt werden
- Das Beispiel
- Addition und Subtraktion sind vergleichsweise einfach, weil man nur Terme gleichen Grades addiert oder subtrahiert
- In Python kann man mit
zip(p, q)die einzelnen Koeffizienten durchlaufen unda + bodera - bberechnen - Bei unterschiedlichen Graden kann
zip_longestverwendet werden
- In Python kann man mit
- Bei der Multiplikation muss jeder Term mit jedem anderen multipliziert und anschließend müssen Terme gleichen Grades wieder zusammengefasst werden, wodurch der Rechenaufwand steigt
- Das Ergebnis von
(2x²+3x+4) × (5x²+6x+7)ist10x⁴+27x³+52x²+45x+28 - Die Komplexität dieses Verfahrens beträgt O(n²), und mit wachsendem Grad steigt die Zahl der benötigten Multiplikationen
- Das Ergebnis von
Koeffizientenvektoren und Faltung
- Im diskreten Bereich ist die Faltung zweier Signale
pundqdefiniert alsy[n]=Σ p[k]·q[n-k] - Die Berechnung erfolgt, indem
qumgedreht und von links nach rechts überpverschoben wird, wobei die Produkte der überlappenden Elemente addiert werden - Die Beispielsignale sind wie folgt
p = [2, 3, 4]q = [5, 6, 7]
- Wenn man
qumdreht und verschiebt, entstehen die einzelnen Ausgabekoeffizienten in dieser Reihenfolge2×5 = 102×6 + 3×5 = 272×7 + 3×6 + 4×5 = 523×7 + 4×6 = 454×7 = 28
- Das Faltungsergebnis ist
y = [10, 27, 52, 45, 28]- Es entspricht den Koeffizienten von
10x⁴+27x³+52x²+45x+28, die man durch Polynommultiplikation erhält - Daher lässt sich Polynommultiplikation als Faltung von Koeffizientenvektoren auffassen
- Es entspricht den Koeffizienten von
Fourier-Transformation und FFT
- Die Fourier-Transformation wandelt ein Signal vom Zeitbereich in den Frequenzbereich um
- Aus zeitlicher Sicht betrachtet man ein Signal über seine Werte zu bestimmten Zeitpunkten
- Aus Frequenzsicht interpretiert man ein Signal als Summe verschiedener Schwingungsfrequenzen
- Schwingungsfrequenzen werden durch Sinus und Kosinus dargestellt und haben jeweils Koeffizient und Phase
- Wendet man die FFT auf eine reine 5-Hz-Sinuswelle an, erscheint sie im Frequenzbereich deltaartig an der 5-Hz-Position
- Das zeigt, dass die Sinuswelle im Zeitbereich durch einen einzelnen 5-Hz-Sinus dargestellt werden kann
- Die einschlägigen Begriffe werden wie folgt unterschieden
- Fourier Transform(FT): im kontinuierlichen Bereich definierte Fourier-Transformation
- Discrete Fourier Transform(DFT): für diskrete Signale definierte Fourier-Transformation
- Fast Fourier Transform(FFT): Algorithmus, der die DFT statt in O(n²) in O(n log n) berechnet
- Die DFT wandelt ein diskretes Zeitsignal
x[n]inX[k]im Frequenzbereich um- Jedes
X[k]wird berechnet, indem die Eingabesamples mit einer komplexen Zahl multipliziert und aufsummiert werden, die eine bestimmte Frequenz repräsentiert
- Jedes
Umwandlung in Multiplikation im Frequenzbereich
- Der zentrale Vorteil der DFT und des Frequenzbereichs besteht darin, dass sich Faltung in elementweise Multiplikation umwandeln lässt
- Zwei Signale im Zeitbereich zu falten ist gleichbedeutend damit, die beiden Signale im Frequenzbereich zu multiplizieren
- Multiplikation lässt sich schneller berechnen als Faltung
- Das Verfahren zur schnellen Polynommultiplikation sieht wie folgt aus
- Die Polynome per FFT in den Frequenzbereich transformieren: O(n log n)
- Im Frequenzbereich elementweise multiplizieren: O(n)
- Das Ergebnis per IFFT wieder in den Zeitbereich zurücktransformieren: O(n log n)
- Insgesamt kann Polynommultiplikation mit der FFT in O(n log n) durchgeführt werden
- Bei großen Polynomen ist das schneller als die Schulmethode mit O(n²)
Python-Implementierung und Benchmark
multiply_naivemultipliziert mit einer doppelten Schleife alle Koeffizientenpaare und addiert sie an der Ergebnispositioni + j- Die Ergebnislänge ist
len(p) + len(q) - 1 - Die Komplexität beträgt O(n²)
- Die Ergebnislänge ist
multiply_fftführt die Koeffizientenmultiplikation auf Basis von FFT/IFFT aus- Es berechnet eine Zweierpotenz-Länge, die mindestens
len(p) + len(q) - 1aufnehmen kann - Die beiden Eingaben werden mit
np.padgepaddet - Die mit
np.fft.ffttransformierten Werte werden elementweise multipliziert - Nach der Rücktransformation mit
np.fft.ifftwird der Realteil gerundet und in ganzzahlige Koeffizienten umgewandelt
- Es berechnet eine Zweierpotenz-Länge, die mindestens
- Für die Beispieleingaben
p = [2, 3, 4],q = [5, 6, 7]liefern beide Verfahren[10, 27, 52, 45, 28] - Im Benchmark wird
multiply_convolve, dasnp.convolveverwendet, mit dem FFT-Verfahren verglichen, stattmultiply_naivezu nutzen- Denn
multiply_naiveist wegen der Python-Schleifen langsam und daher schwer direkt mit dem FFT-Verfahren zu vergleichen, dasnp.fft.fftverwendet np.convolveführt dieselbe Operation in Low-Level-C-Code aus
- Denn
- Der Grad wird im Bereich
range(1, 30000, 1000)erhöht, und für jeden Grad werden zwei Polynome mit zufälligen Koeffizienten zwischen 1 und 999999 erzeugt- Für jedes Verfahren wird mit
n_runs = 5die Durchschnittszeit gemessen - Bei niedrigen Graden kann das FFT-Verfahren wegen der Kosten für Hin- und Rücktransformation per FFT/IFFT im Nachteil sein
- Mit steigendem Grad zeigt das FFT-Verfahren deutlich effizientere Ergebnisse
- Für jedes Verfahren wird mit
1 Kommentare
Kommentare auf Hacker News
Was mich an solchen Erklärungen immer stört, ist, dass sie meist numerische Fehler vergessen.
Koeffizientenmultiplikation kann man nicht einfach als „konstante Zeit“ abstrahieren. Wenn man das tut, könnte man genauso gut gleich die gesamte Multiplikation abstrahieren. Berücksichtigt man die numerische Genauigkeit, liegt es eher bei 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
Mit dieser Methode kann man lange Zahlen miteinander multiplizieren. Der Kern ist, dass Polynommultiplikation dasselbe ist wie die normale schriftliche Multiplikation langer Zahlen ohne Überträge (carry).
Wenn man zum Beispiel eine 1000-stellige Zahl hat, nimmt man jede Ziffer als Koeffizienten eines Polynoms mit 1000 Elementen. Anschließend kann man diese Polynome mit der im Artikel beschriebenen FFT-Methode multiplizieren. Um das Ergebnis wieder in eine Zahl umzuwandeln, muss man die Überträge verarbeiten. Wenn ein Element größer als 10 ist, gibt man den Überschuss an die nächste Stelle weiter und wandelt die Koeffizienten in Ziffern um.
Das ist die Grundidee; bei der für die Überträge nötigen Genauigkeit und der Garantie, dass das Runden der FFT-Ergebnisse auf die nächste ganze Zahl korrekt ist, gibt es einige Feinheiten. Auf diese Weise führt GMP, die führende Bibliothek in diesem Bereich, Multiplikationen großer Zahlen durch.
Ich frage mich, wie groß Zahlen sein müssen, damit das in der Praxis sinnvoll ist, und wofür es eingesetzt wird.
Falls du es noch nicht gesehen hast, ist dieses Video empfehlenswert:
https://youtu.be/h7apO7q16V0?si=bmgUEMTQSqU3flIv
Es leitet den FFT-Algorithmus aus der Polynommultiplikation her und ist wirklich hervorragend. Ich schaue es mir etwa alle sechs Monate wieder an.
Die FFT-Eigenschaft „Faltung ist punktweise Multiplikation“ gilt auch für beliebige zyklische multiplikative Gruppen. Für eine stärker algebraische Herleitung siehe https://www.sciencedirect.com/science/article/pii/S002200007...
Das wird manchmal als „harmonische FFT“ bezeichnet; es gibt auch nicht-harmonische FFTs: [LCH14] „additive NTT“ über GF(2^n), [HLP24] circle FFT auf dem Einheitskreis X^2+Y^2=1 eines endlichen Körpers, [BCKL21] ecfft über Isogeniefolgen elliptischer Kurven.
[LCH14]: https://arxiv.org/abs/1404.3458
[HLP24]: https://eprint.iacr.org/2024/278
[BCKL21]: https://arxiv.org/pdf/2107.08473
Wer hat eigentlich zuerst vorgeschlagen, FFT für schnellere Polynom-Multiplikation zu verwenden?
Ich habe kürzlich aus Neugier recherchiert und bin, auch wenn ich die Zitationskette nicht sauber verfolgen konnte, bis zu einem Paper von David Eppstein aus dem Jahr 1995 [0] zurückgegangen. Dort wird sie verwendet, um nach inkrementellen Aktualisierungen das Partialsummenproblem effizient zu lösen. In Knuths TAOCP stand das bestimmt schon früher
Dass man mit FFT-Polynom-Multiplikation das exakte Partialsummenproblem mit Wiederholungen in subexponentieller Zeit lösen kann, fand ich ebenfalls ziemlich verblüffend [1]. Wichtig ist, dass dieser Algorithmus O(N log N) ist, wobei N nicht die Größe der Menge, sondern das maximale Element ist; es ist also kein Gegenbeispiel zu P ≠ NP
[0] https://escholarship.org/content/qt6sd695gn/qt6sd695gn.pdf
[1] https://x.com/festivitymn/status/1788362552998580473?s=46&t=...
Von Strassen heißt es, er habe 1968 einen Pollard-artigen Ansatz gefunden, aber dazu gibt es keine schriftliche Dokumentation. Außerdem sollte man berücksichtigen, dass auch wenn es nicht die Geburt der FFT selbst war, Cooley-Tukeys Paper von 1965 [4] die Forschung zu FFT und ihren Anwendungen erst richtig angestoßen hat. Das hier geschah einige Jahre danach
[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
Ich denke, dass alles maschinelle Lernen letztlich darin besteht, Faltungsgleichungen zu lösen
Dieses Paper behandelt es im Kontext von Reinforcement Learning https://arxiv.org/abs/1712.06115, aber die meisten Ansätze passen in dieses Paradigma
Ich habe gerade einen Algorithmus (matrix profile) implementiert, der FFT verwendet, um Skalarprodukte für eine große Menge von Teilsequenzen einer Zeitreihe zu berechnen. Die Länge n der Zeitreihe kann bis in den Bereich von Hunderten Millionen gehen
Durch schnelle Faltungsberechnung per FFT sinkt die Rechenzeit von O(n) auf O(log n), und in dieser Größenordnung ist der Geschwindigkeitsgewinn enorm. Mit GPU wird es noch schneller, etwa 10 Millionen Datenpunkte in 0,1 Sekunden auf einem Laptop
Der zentrale „Trick“ dieser Operation scheint diese Erkenntnis zu sein:
Es gibt die Eigenschaft: „Eine Faltung zweier Signale im Zeitbereich durchzuführen ist dasselbe, wie die beiden Signale im Frequenzbereich zu multiplizieren“, und FFT ermöglicht es, vom Zeitbereich in den Frequenzbereich zu transformieren. Deshalb verschiebt man die Polynome per FFT in den Frequenzbereich und muss dort nur noch multiplizieren. Das ist schneller als eine Faltung. Ich frage mich, ob der fehlende Schritt damit klarer wird; falls noch etwas fehlt, kann der Artikel aktualisiert werden
Ist Ganzzahlfaktorisierung dann diskrete Dekonvolution? Ich frage mich, ob man genug Informationen für einen schnellen Algorithmus gewinnen könnte, wenn man die FFT-Darstellung, also die Umkehrung der punktweisen Multiplikation, und tableax, also die normale schriftliche Multiplikation/Addition mit Übertrag, nebeneinanderstellt und dadurch die Symmetrie bricht
Natürlich ist naive Polynommultiplikation in Bezug auf den Grad des Polynoms langsam. Aber wann muss man in der Praxis schon einmal mit zwei Polynomen 100. Grades umgehen?
Aus diesem Grund hat man den Eindruck, dass Computer-Algebra-Systeme diese Methode nicht verwenden
https://www.youtube.com/watch?v=CcZf_7Fb4Us
https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_cor... ist ein Beispiel dafür
[1]: https://github.com/8051enthusiast/delsum
In den Blogbeiträgen von Hazy Research aus den Jahren 2020 bis 2023 gibt es viele Informationen zu diesem Ansatz
„(...) In der Physikforschung habe ich einmal mit Ausdrücken gearbeitet, die fast 1 Terabyte groß waren und mehr als 100 Millionen Terme hatten“