Descargo de responsabilidad: Sé que este tema es más antiguo, pero si uno está buscando un "rango dinámico alto de convolución rápido y preciso" o similar, este es uno de los primeros de unos pocos resultados decentes. Quiero compartir mis ideas sobre este tema para que pueda ayudar a alguien en el futuro. Pido disculpas si podría usar los términos incorrectos en mi respuesta, pero todo lo que encontré sobre este tema es bastante vago y puede llevar a confusión incluso en este hilo. Espero que el lector lo entienda de todos modos.
La convolución directa es en su mayoría precisa para la precisión de la máquina para cada punto, es decir, el error relativo suele ser aproximadamente o cercano a 1.e-16 para obtener una precisión doble para cada punto del resultado. Cada punto tiene 16 dígitos correctos. Sin embargo, los errores de redondeo pueden ser significativos para convoluciones anormalmente grandes, y estrictamente hablando, uno debe tener cuidado con la cancelación y usar algo como la suma de Kahan y los tipos de datos de precisión suficientemente alta, pero en la práctica el error es casi siempre óptimo.
El error de una convolución FFT aparte de los errores de redondeo es un error "relativo global", lo que significa que el error en cada punto depende de la precisión de la máquina y del valor máximo del resultado. Por ejemplo, si el valor máximo del resultado es 2.e9
, entonces el error absoluto en cada punto es2 ⋅109 9⋅10- 16= 2 ⋅10- 7. Entonces, si se supone que un valor en el resultado es muy pequeño, digamos10- 9, el error relativo en ese punto puede ser enorme. La convolución FFT es básicamente inútil si necesita pequeños errores relativos en la cola de su resultado, por ejemplo, tiene una disminución algo exponencial de sus datos y necesita valores precisos en la cola. Curiosamente, si la convolución FFT no está limitada por ese error, tiene errores de redondeo mucho más pequeños en comparación con la convolución directa, ya que obviamente hace menos adiciones / multiplicaciones. Esta es realmente la razón por la cual las personas a menudo afirman que la convolución FFT es más precisa, y casi tienen razón en algún sentido, por lo que pueden ser bastante inflexibles.
Desafortunadamente, no hay una solución universal fácil para obtener convoluciones rápidas y precisas, pero dependiendo de su problema puede haber una ... He encontrado dos:
Si tiene granos lisos que se pueden aproximar bien por un polinomio en la cola, entonces el Método rápido multipolar de caja negra con interpolación de Chebyshev podría ser interesante para usted. Si su núcleo es "agradable", esto funciona realmente perfectamente: obtiene tanto la complejidad computacional lineal (!) Como la precisión de la precisión de la máquina. Si esto encaja con su problema, debe usarlo. Sin embargo, no es fácil de implementar.
Para algunos núcleos específicos (funciones convexas, creo, generalmente de densidades de probabilidad) puede usar un "cambio exponencial" para obtener un error óptimo en alguna parte de la cola del resultado. Hay una tesis de doctorado y un github con una implementación de Python que lo usa sistemáticamente, y el autor lo llama convolución FFT precisa . Sin embargo, en la mayoría de los casos esto no es súper útil, ya que regresa a la convolución directa o puede usar la convolución FFT de todos modos. Aunque el código lo hace automáticamente, lo cual es bueno, por supuesto.
--------------------EDITAR:--------------------
Miré un poco el algoritmo de Karatsuba (en realidad hice una pequeña implementación), y para mí parece que generalmente tiene un comportamiento de error similar al de la convolución FFT, es decir, obtienes un error relativo al valor máximo del resultado. Debido a la naturaleza de dividir y conquistar del algoritmo, algunos valores en la cola del resultado en realidad tienen un mejor error, pero no veo una manera sistemática fácil de decir cuáles o, en cualquier caso, cómo usar esta observación. Lástima, al principio pensé que Karatsuba podría ser algo útil entre convolución directa y FFT. Pero no veo casos de uso comunes donde Karatsuba deba preferirse sobre los dos algoritmos de convolución comunes.
Y para agregar al cambio exponencial que mencioné anteriormente: hay muchos casos en los que puede usarlo para mejorar el resultado de una convolución, pero nuevamente no es una solución universal. De hecho, utilizo esto junto con la convolución FFT para obtener resultados bastante buenos (en el caso general de todas las entradas: en el peor error que la convolución FFT normal, en el mejor error relativo en cada punto para la precisión de la máquina). Pero, de nuevo, esto solo funciona muy bien para núcleos y datos específicos, pero para mí tanto el núcleo como los datos o algo exponencial en decadencia.
convolve()
solo llamafftconvolve()
ahora, si el tamaño de entrada es grande. Especificamethod='direct'
si quieres directo.