Haftungsausschluss: Ich weiß, dass dieses Thema älter ist, aber wenn man nach einem "schnellen, genauen Faltungs-Hochdynamikbereich" oder ähnlichem sucht, ist dies eines der ersten von nur wenigen anständigen Ergebnissen. Ich möchte meine Erkenntnisse zu diesem Thema teilen, damit es in Zukunft jemandem helfen kann. Ich entschuldige mich, wenn ich in meiner Antwort möglicherweise die falschen Begriffe verwende, aber alles, was ich zu diesem Thema gefunden habe, ist ziemlich vage und führt selbst in diesem Thread zu Verwirrung. Ich hoffe der Leser wird es trotzdem verstehen.
Die direkte Faltung ist meistens auf die Maschinengenauigkeit für jeden Punkt genau, dh der relative Fehler liegt normalerweise ungefähr oder nahe bei 1.e-16 für die doppelte Genauigkeit für jeden Punkt des Ergebnisses. Jeder Punkt hat 16 korrekte Ziffern. Rundungsfehler können für untypisch große Windungen von Bedeutung sein, und genau genommen sollte man beim Löschen vorsichtig sein und so etwas wie Kahan-Summierung und ausreichend genaue Datentypen verwenden, aber in der Praxis ist der Fehler fast immer optimal.
2.e9
2 ⋅ 109⋅ 10- 16= 2 ≤ 10- 710- 9kann der relative Fehler in diesem Punkt sehr groß sein. Die FFT-Faltung ist grundsätzlich nutzlos, wenn Sie kleine relative Fehler im Ende Ihres Ergebnisses benötigen, z. B. wenn Ihre Daten etwas exponentiell abfallen und genaue Werte im Ende benötigen. Interessanterweise weist die FFT-Faltung, wenn sie nicht durch diesen Fehler begrenzt ist, im Vergleich zur direkten Faltung viel kleinere Rundungsfehler auf, da Sie offensichtlich weniger Additionen / Multiplikationen durchführen. Dies ist tatsächlich der Grund, warum Menschen oft behaupten, dass die FFT-Faltung genauer ist, und sie haben in gewissem Sinne fast recht, so dass sie ziemlich unnachgiebig sein können.
Leider gibt es keine einfache universelle Lösung , um schnelle und genaue Windungen zu erhalten, aber abhängig von Ihrem Problem kann es eine geben ... Ich habe zwei gefunden:
Wenn Sie glatte Kernel haben, die durch ein Polynom im Schwanz gut angenähert werden können, ist die Black-Box-Fast-Multipole-Methode mit Chebyshev-Interpolation möglicherweise für Sie interessant. Wenn Ihr Kernel "nett" ist, funktioniert dies tatsächlich perfekt: Sie erhalten sowohl lineare (!) Rechenkomplexität als auch Maschinengenauigkeit. Wenn dies zu Ihrem Problem passt, sollten Sie es verwenden. Es ist jedoch nicht einfach zu implementieren.
Für einige spezifische Kernel (konvexe Funktionen, glaube ich, normalerweise aus Wahrscheinlichkeitsdichten) können Sie eine "exponentielle Verschiebung" verwenden, um einen optimalen Fehler in einem Teil des Endes des Ergebnisses zu erhalten. Es gibt eine Doktorarbeit und einen Github mit einer Python-Implementierung , die diese systematisch verwendet, und der Autor nennt sie eine genaue FFT-Faltung . In den meisten Fällen ist dies jedoch nicht besonders nützlich, da es entweder zur direkten Faltung zurückkehrt oder Sie die FFT-Faltung trotzdem verwenden können. Obwohl der Code es automatisch macht, ist das natürlich schön.
--------------------BEARBEITEN:--------------------
Ich habe mir den Karatsuba- Algorithmus ein wenig angesehen (ich habe tatsächlich eine kleine Implementierung vorgenommen), und für mich sieht es so aus, als ob er normalerweise ein ähnliches Fehlerverhalten wie die FFT-Faltung aufweist, dh Sie erhalten einen Fehler relativ zum Spitzenwert des Ergebnisses. Aufgrund der Teilung und Eroberung des Algorithmus weisen einige Werte am Ende des Ergebnisses tatsächlich bessere Fehler auf, aber ich sehe keine einfache systematische Methode, um festzustellen, welche oder auf jeden Fall, wie diese Beobachtung verwendet werden soll. Schade, zuerst dachte ich, Karatsuba könnte etwas Nützliches zwischen direkter und FFT-Faltung sein. Ich sehe jedoch keine häufigen Anwendungsfälle, in denen Karatsuba den beiden üblichen Faltungsalgorithmen vorgezogen werden sollte.
Und um die oben erwähnte exponentielle Verschiebung zu ergänzen : Es gibt viele Fälle, in denen Sie damit das Ergebnis einer Faltung verbessern können, aber es ist wiederum keine universelle Lösung. Ich verwende dies tatsächlich zusammen mit der FFT-Faltung, um ziemlich gute Ergebnisse zu erzielen (im allgemeinen Fall für alle Eingaben: im schlimmsten Fall der gleiche Fehler wie bei der normalen FFT-Faltung, bestenfalls relativer Fehler in jedem Punkt zur Maschinengenauigkeit). Aber auch dies funktioniert nur für bestimmte Kernel und Daten wirklich gut, aber für mich sowohl Kernel als auch Daten oder etwas exponentiell im Zerfall.
convolve()
nurfftconvolve()
jetzt aufgerufen wird , wenn die Eingabegröße groß ist. Gebenmethod='direct'
Sie an, ob Sie direkt möchten.