Transformada de Hadamard: teoría, implementación en Python y comparativas
1. Introducción
La Transformada de Hadamard (también conocida como Walsh‑Hadamard Transform o WHT) es una herramienta de procesamiento de señales que convierte una secuencia de valores en una combinación lineal de funciones ortogonales de forma binaria (valores +1 y –1). A diferencia de la Transformada de Fourier, que emplea senos y cosenos continuos, la WHT utiliza únicamente sumas y restas, lo que la hace extremadamente rápida y adecuada para hardware de bajo consumo.
2. Fundamento matemático
Una matriz de Hadamard Hn de orden n = 2^k se define recursivamente:
H₁ = [1]
H₂ₖ = \begin{bmatrix} Hₖ & Hₖ \\ Hₖ & -Hₖ \end{bmatrix}
Para una señal x = [x₀, x₁, …, x_{n-1}], la transformada se calcula como:
y = Hₙ · x
Donde · indica el producto matricial. Como Hₙ es ortogonal, la inversa es simplemente Hₙ / n.
3. Propiedades clave
- Ortogonalidad: Hₙ·Hₙᵀ = n·Iₙ.
- Complejidad O(n log n): La versión fast (FWHT) reduce la complejidad a n·log₂ n, idéntica a la FFT.
- Operaciones binarias: Solo suma y resta, sin multiplicaciones por constantes complejas.
- Espectro real y simétrico: Útil para análisis de señales binarias y datos de imagen.
4. Implementación en Python (FWHT)
La versión iterativa más eficiente se basa en el algoritmo de “divide‑y‑vencerás”. A continuación, un ejemplo limpio y documentado.
import numpy as np
def fwht(x: np.ndarray) -> np.ndarray:
"""Fast Walsh‑Hadamard Transform (in‑place).
Parámetros
----------
x : np.ndarray
Vector de longitud 2ⁿ (se lanza ValueError si la longitud no es potencia de 2).
Returns
-------
np.ndarray
Transformada de Hadamard del vector ``x``.
"""
n = x.shape[0]
if n & (n - 1) != 0:
raise ValueError('La longitud del vector debe ser una potencia de 2')
h = 1
y = x.astype(float).copy()
while h < n:
for i in range(0, n, h * 2):
for j in range(i, i + h):
a = y[j]
b = y[j + h]
y[j] = a + b # suma
y[j + h] = a - b # resta
h *= 2
return y
# Ejemplo de uso
if __name__ == '__main__':
signal = np.array([1, 2, 3, 4, 0, 1, 0, 1])
transformed = fwht(signal)
print('Señal original :', signal)
print('Transformada :', transformed)
# Inversa (dividir por n)
inverse = fwht(transformed) / signal.size
print('Reconstruida :', inverse)
El algoritmo funciona in‑place, lo que reduce la huella de memoria, y su complejidad es O(n log n).
5. Comparativa con otras transformadas
Ventajas de Hadamard vs FFT
- Solo operaciones aritméticas simples (suma/resta).
- Sin números complejos → menos errores de redondeo.
- Ideal para datos binarios (imágenes en blanco‑negro, señales de comunicaciones).
- Menor consumo de energía en hardware FPGA/ASIC.
Desventajas de Hadamard vs FFT
- No captura componentes de frecuencia continua como la FFT.
- Menos útil para análisis espectral de señales analógicas.
- Requiere longitud potencia de 2 (aunque se pueden zero‑pad).
Hadamard vs DCT (Discrete Cosine Transform)
- Hadamard: bases {+1, -1}. DCT: bases sinusoidales reales.
- DCT suele dar mejor compresión en JPEG por su correlación con la percepción visual.
- Hadamard es más rápida en hardware de bajo nivel.
Hadamard vs Walsh (orden natural)
- Walsh es una permutación de Hadamard ordenada por “secuencia de Gray”.
- Ambas comparten la misma matriz base; la diferencia está en el orden de los coeficientes.
- En aplicaciones de multiplexado, la versión Walsh‑ordered es preferida.
6. Casos de uso reales
- Compresión de imágenes binarias: La WHT reduce la entropía de imágenes de texto o diagramas.
- Comunicación por línea de visión (Li-Fi) y CDMA: Codificación y decodificación de secuencias de chips.
- Algoritmos de aprendizaje rápido: Kernels basados en Hadamard para SVM y redes neuronales (Fastfood).
- Generación de patrones de prueba en hardware: Señales de pseudo‑aleatoriedad con bajo coste.
7. Buenas prácticas y optimizaciones
- Uso de NumPy vectorizado: Para vectores muy grandes (> 2⁰) considere
scipy.fftpackcon ``dtype=np.int8`` y luego convierta a float para evitar overflow. - Pre‑alocar buffers: Evite crear copias dentro del bucle; pasar un buffer pre‑inicializado a la función.
- Paralelismo con Numba o Cython: Decorar la función con
@njit(parallel=True)puede reducir el tiempo de ejecución en un 30‑50%. - Gestión de overflow: Para datos enteros de gran magnitud, convierta a ``float64`` antes de la transformación o normalice la señal.
8. Depuración y troubleshooting
Los problemas más frecuentes y sus soluciones:
| Problema | Posible causa | Solución |
|---|---|---|
| Resultado inesperado (todos ceros) | Longitud del vector no es potencia de 2 | Zero‑pad hasta la siguiente potencia de 2 o lanzar excepción. |
| Overflow en enteros de 16‑bit | Sumas/Restas superan el rango | Convertir a ``float64`` antes de la WHT. |
| Desfase entre señal original y reconstruida | No dividir por n al aplicar la inversa | Multiplicar por ``1/n`` después de la segunda llamada a ``fwht``. |
| Rendimiento pobre para vectores pequeños | Overhead de Python | Usar la versión recursiva para n ≤ 1024 o emplear C‑extensions. |
9. Compatibilidad, rendimiento y escalabilidad
La WHT está disponible en la mayoría de los entornos de cálculo numérico:
- Python: Implementación pura (como la mostrada) o
pywt(Wavelet Toolbox) que incluyehadamard. - MATLAB/Octave:
hadamardywht(Signal Processing Toolbox). - R: Paquete
pracmaconhadamard. - Hardware: FPGA/ASIC pueden ejecutar la WHT en < 10 ns para bloques de 1024 bits.
En clústeres de cómputo distribuido, la transformación se paraleliza fácilmente dividiendo el vector en sub‑bloques y combinando resultados con un reduce de tipo suma.
10. Conclusiones
La Transformada de Hadamard sigue siendo una alternativa poderosa a la FFT cuando:
- Se trabaja con datos binarios o de bajo ancho de banda.
- Se requiere una implementación ultra‑rápida y de bajo consumo.
- Se desea evitar la complejidad de números complejos.
Con la implementación en Python presentada, puedes experimentar rápidamente, ajustar el algoritmo con Numba o Cython y aplicar la WHT a problemas de compresión, comunicaciones y aprendizaje automático.
Transformada de Hadamard: teoría, implementación en Python y comparativas con otras transformadas