Avis de non-responsabilité: je sais que ce sujet est plus ancien, mais si l'on recherche une "plage dynamique élevée de convolution rapide et précise" ou similaire, c'est l'un des premiers des quelques résultats décents. Je veux partager mes idées sur ce sujet afin que cela puisse aider quelqu'un à l'avenir. Je m'excuse si je pourrais utiliser les mauvais termes dans ma réponse, mais tout ce que j'ai trouvé sur ce sujet est assez vague et conduit à la confusion même dans ce fil. J'espère que le lecteur comprendra de toute façon.
La convolution directe est généralement précise à la précision de la machine pour chaque point, c'est-à-dire que l' erreur relative est généralement approximativement ou proche de 1.e-16 pour une double précision pour chaque point du résultat. Chaque point a 16 chiffres corrects. Cependant, les erreurs d'arrondi peuvent être importantes pour des convolutions inhabituellement importantes, et à proprement parler, il faut faire attention à l'annulation et utiliser quelque chose comme la sommation de Kahan et des types de données de précision suffisamment élevée, mais dans la pratique, l'erreur est presque toujours optimale.
L'erreur d'une convolution FFT en dehors des erreurs d'arrondi est une erreur "relative globale", ce qui signifie que l'erreur en chaque point dépend de la précision de la machine et de la valeur de crête du résultat. Par exemple, si la valeur maximale du résultat est 2.e9
, alors l'erreur absolue en chaque point est . Donc, si une valeur dans le résultat est supposée être très petite, disons2 ⋅dix9⋅dix- 16= 2 ⋅dix- 7dix- 9, l'erreur relative à ce point peut être énorme. La convolution FFT est fondamentalement inutile si vous avez besoin de petites erreurs relatives dans la queue de votre résultat, par exemple vous avez une décroissance quelque peu exponentielle de vos données et avez besoin de valeurs précises dans la queue. Fait intéressant, si la convolution FFT n'est pas limitée par cette erreur, elle a des erreurs d'arrondi beaucoup plus petites que la convolution directe, car vous faites évidemment moins d'ajouts / multiplications. C'est en fait pourquoi les gens prétendent souvent que la convolution FFT est plus précise, et ils ont presque raison dans un certain sens, ils peuvent donc être assez catégoriques.
Malheureusement, il n'y a pas de solution universelle facile pour obtenir des convolutions rapides et précises, mais en fonction de votre problème, il peut y en avoir une ... J'en ai trouvé deux:
Si vous avez des noyaux lisses qui peuvent être bien approchés par un polynôme dans la queue, alors la méthode multipolaire rapide à boîte noire avec interpolation de Chebyshev pourrait être intéressante pour vous. Si votre noyau est "sympa", cela fonctionne parfaitement: vous obtenez à la fois une complexité de calcul linéaire (!) Et une précision de précision de la machine. Si cela correspond à votre problème, vous devez l'utiliser. Ce n'est cependant pas facile à mettre en œuvre.
Pour certains noyaux spécifiques (fonctions convexes je pense, généralement à partir des densités de probabilité), vous pouvez utiliser un "décalage exponentiel" pour obtenir une erreur optimale dans une partie de la queue du résultat. Il y a une thèse de doctorat et un github avec une implémentation de python qui l'utilisent systématiquement, et l'auteur l'appelle une convolution FFT précise . Dans la plupart des cas, cela n'est cependant pas très utile, car soit il régresse en convolution directe, soit vous pouvez utiliser la convolution FFT de toute façon. Bien que le code le fasse automatiquement, ce qui est bien sûr bien sûr.
--------------------ÉDITER:--------------------
J'ai regardé un peu l' algorithme de Karatsuba (j'ai en fait fait une petite implémentation), et il me semble qu'il a généralement un comportement d'erreur similaire à la convolution FFT, c'est-à-dire que vous obtenez une erreur par rapport à la valeur de crête du résultat. En raison de la nature de division et de conquête de l'algorithme, certaines valeurs dans la queue du résultat ont en fait une meilleure erreur, mais je ne vois pas de moyen systématique facile de dire lesquelles ou en tout cas comment utiliser cette observation. Dommage, au début, je pensais que Karatsuba pourrait être quelque chose d'utile entre la convolution directe et la FFT. Mais je ne vois pas de cas d'utilisation courants où Karatsuba devrait être préféré aux deux algorithmes de convolution communs.
Et pour ajouter au décalage exponentiel que j'ai mentionné ci-dessus: Il existe de nombreux cas où vous pouvez l'utiliser pour améliorer le résultat d'une convolution, mais encore une fois, ce n'est pas une solution universelle. J'utilise en fait cela avec la convolution FFT pour obtenir de très bons résultats (dans le cas général pour toutes les entrées: au pire, même erreur que la convolution FFT normale, au mieux erreur relative à chaque point de la précision de la machine). Mais encore une fois, cela ne fonctionne vraiment bien que pour des noyaux et des données spécifiques, mais pour moi, le noyau et les données ou quelque peu exponentiels en décomposition.
convolve()
n'appelle quefftconvolve()
maintenant, si la taille d'entrée est grande. Spécifiezmethod='direct'
si vous voulez directement.