Transformación discreta de wavelets: visualización de la relación entre los coeficientes de detalle descompuestos y la señal


12

Estoy tratando de visualizar directamente la relación entre los coeficientes de detalle de la transformada wavelet discreta (DWT) y la señal original / su reconstrucción. El objetivo es mostrar su relación de forma intuitiva. Me gustaría preguntar (ver preguntas a continuación): si la idea y el proceso que se me ocurren son correctos hasta ahora, y si estoy en lo cierto, podría ser mejor restar la aproximación del primer nivel de la señal original antes de visualizar su relación .

Ejemplo mínimo

Este es el ejemplo mínimo en el que baso mi explicación, utilizando los datos de ejemplo de ECG de Pythonpywavelets , que tiene 1024 valores, como una simple señal 1D:

import pywt
import pywt.data
import numpy as np
import matplotlib.pyplot as plt

x = pywt.data.ecg()
plt.plot(x)
plt.legend(['Original signal'])

Señal original

La descomposición se realiza utilizando un Symmlet 5 con un total de 6 niveles:

w = pywt.Wavelet('sym5')
plt.plot(w.dec_lo)
coeffs = pywt.wavedec(x, w, level=6)

La reconstrucción (con pérdida) de la señal funciona como se espera cuando se omiten intencionalmente los coeficientes de detalle de los niveles superiores (las señales se trazan en una escala x uniforme [0,1] por conveniencia):

def reconstruction_plot(yyy, **kwargs):
    """Plot signal vector on x [0,1] independently of amount of values it contains."""
    plt.plot(np.linspace(0, 1, len(yyy)), yyy, **kwargs)

reconstruction_plot(pywt.waverec(coeffs, w)) # full reconstruction 
#reconstruction_plot(pywt.waverec(coeffs[:-1] + [None] * 1, w)) # leaving out detail coefficients up to lvl 5
#reconstruction_plot(pywt.waverec(coeffs[:-2] + [None] * 2, w)) # leaving out detail coefficients up to lvl 4
#reconstruction_plot(pywt.waverec(coeffs[:-3] + [None] * 3, w)) # leaving out detail coefficients up to lvl 3
reconstruction_plot(pywt.waverec(coeffs[:-4] + [None] * 4, w)) # leaving out detail coefficients up to lvl 2
#reconstruction_plot(pywt.waverec(coeffs[:-5] + [None] * 5, w)) # leaving out detail coefficients up to lvl 1
reconstruction_plot(pywt.waverec(coeffs[:-6] + [None] * 6, w)) # leaving out all detail coefficients = reconstruction using lvl1 approximation only
plt.legend(['Full reconstruction', 'Reconstruction using detail coefficients lvl 1+2', 'Reconstruction using lvl 1 approximation only'])

Señal reconstruida

El DWT anterior produce un vector de aproximación de nivel 1 de 24 valores, un vector de coeficiente de detalles de nivel 1 de 24 valores, un vector de detalle de nivel 2 de 40 valores, el nivel 3 de 72 valores, el nivel 4 de 135 valores, el nivel 5 de 262 valores y el nivel 6 de 516 valores:

plt.stem(coeffs[1]); plt.legend(['Lvl 1 detail coefficients'])
plt.stem(coeffs[2]); plt.legend(['Lvl 2 detail coefficients'])
plt.stem(coeffs[3]); plt.legend(['Lvl 3 detail coefficients'])
plt.stem(coeffs[4]); plt.legend(['Lvl 4 detail coefficients'])
plt.stem(coeffs[5]); plt.legend(['Lvl 5 detail coefficients'])
plt.stem(coeffs[6]); plt.legend(['Lvl 6 detail coefficients'])

Nivel 1 coeficientes de detalle Nivel 2 coeficientes de detalle Nivel 3 coeficientes de detalle Nivel 4 coeficientes de detalle Nivel 5 coeficientes de detalle Nivel 6 coeficientes de detalle

Parece que vemos patrones claros alrededor de los picos en las señales originales (también preste atención a la escala y de los gráficos de arriba).

Ahora a mis preguntas:

  1. ¿Es correcto que podamos relacionar directamente esos coeficientes con la señal? La amplitud del coeficiente corresponde a la amplitud con la que se produce la wavelet en la señal (eje y), y la posición del coeficiente corresponde al tiempo (eje x). ¿O hay algo en el medio que debemos considerar?
  2. Después del DWT, la aproximación final lvl1 permanece. ¿Tiene sentido no visualizar la relación de los coeficientes de detalle con la señal original, sino con la señal original menos la aproximación lvl1? (Sé que lo más probable es que también vea la relación entre los coeficientes y la señal sin hacer esto, ver, por ejemplo, las gráficas a continuación. Es solo para esto tiene sentido o no. Si tiene sentido para los coeficientes de detalle lvl1, entonces también podría tener sentido para Coeficientes de detalle lvl2 para comparar con la señal original menos la aproximación lvl2, ¿verdad?). Un ejemplo:

    # Reconstruction of signal using just lvl1 approximation
    approx_lvl1 = pywt.waverec(coeffs[:-6] + [None] * 6, w)
    # interpolate to original amount of samples (necessary due to numeric solution of transformation not yielding same amount of values)
    approx_lvl1_interp = np.interp(x=np.arange(0, 1024), xp=np.linspace(0, 1024, len(approx_lvl1)), fp=approx_lvl1)
    x_without_lvl1approx = x - approx_lvl1_interp
    
  3. La visualización directa de la relación entre los coeficientes de detalle y la señal que uso simplemente traza tanto la señal como los coeficientes en un eje x de [0,1]. Conceptualmente, esto debería ser válido, pero no estoy seguro de si realmente necesitaría un desplazamiento hacia los márgenes (por ejemplo, el primer y el último coeficiente del vector que no se coloca al principio o al final de la señal):

    def reconstruction_stem(yyy, **kwargs):
        """Plot coefficient vector on x [0,1] independently of amount of values it contains."""
        plt.stem(np.linspace(0, 1, len(yyy)), yyy, **kwargs)
    
    reconstruction_plot(x, color='orange')
    reconstruction_plot(x_without_lvl1approx, color='red')
    reconstruction_stem(coeffs[1])
    plt.legend(['Original signal', 'Original signal - lvl1 approximation', 'Detail coefficients'])
    

Relación entre coeficientes de detalle lvl1 y señal Relación entre coeficientes de detalle lvl2 y señal Relación entre coeficientes de detalle lvl3 y señal Relación entre coeficientes de detalle lvl4 y señal Relación entre coeficientes de detalle lvl5 y señal Relación entre coeficientes de detalle lvl6 y señal

¿Existe una explicación intuitiva para los coeficientes fuertes que no están directamente en las posiciones de los picos en los datos originales (por ejemplo, en el nivel 1, el más bajo (negativo más fuerte) en alrededor de 0.25, así como el más alto (positivo más fuerte) en torno a 0.75 )? Aunque hay un patrón claro (retraso positivo + amplitud negativa, retraso negativo + amplitud positiva), me parecen un poco "lejanos". Pero probablemente haya una buena explicación para eso.

¡Gracias por responder!


No obtuvo una respuesta, pero su pregunta en sí misma es un buen tutorial para implementar el análisis wavelet en Python. ¡Gracias!
Farzad

Respuestas:


1

Es necesario distinguir claramente entre los coeficientes de aproximación y detalle en cada nivel de descomposición y los niveles de Detalles y Aproximación asociados que implican no solo los coeficientes sino también los filtros inversos en ese nivel respectivamente


0

Solo ahora estoy empezando a incursionar en las wavelets, y todavía estoy luchando incluso con preguntas muy básicas como "¿cómo se elige entre el grupo de wavelets disponibles" (probablemente tiene que ver con la cantidad de niveles que necesita para alcanzar "lo suficientemente bueno" representación), y "de qué se trata todo el alboroto sobre la eliminación de ruido con wavelets", porque parece que soy capaz de lograr mejores resultados para mi tipo de datos con la eliminación de ruido gaussiano directo o los filtros de mediana. Pero yo divago....

Una cosa que noté en lo anterior es que su numeración de niveles parece inconsistente con lo que creo que son las convenciones de wavelet habituales. En particular, coeffs [0] es la amplitud de aproximación en el último nivel, en su caso 6 coeffs [1] es la amplitud de detalle en el nivel 6 coeffs [2] es la amplitud de detalle en el nivel 5 ... coeffs [6] es el amplitud de detalle en el nivel 1

Por lo tanto, sus reconstrucciones son solo del nivel 5 y 6, no del nivel 1 y 2 como se indica en sus parcelas.

=========

Actualización: Me equivoqué más con su código, y creo que su idea de ilustrar la correlación entre los coeficientes y las características de la señal es sólida, pero no perfecta. He revisado un poco tu código para ilustrarlo mejor, ver más abajo. Tenga en cuenta que en cada paso vuelvo a escalar los coeficientes a la magnitud de la señal. Esto permite hablar sobre el concepto de umbral también.

import pywt
import pywt.data
import numpy as np
import matplotlib.pyplot as plt

plt.close('all')

def reconstruction_plot(yyy, **kwargs):
    """Plot signal vector on x [0,1] independently of amount of values it contains."""
    #plt.figure()
    #plt.plot(np.linspace(0, 1, len(yyy)), yyy, **kwargs)
    ym = np.median(yyy)
    plt.plot(np.linspace(0, 1., num=len(yyy)), yyy-ym, **kwargs)


def reconstruction_stem(yyy, xmax, **kwargs):
    """Plot coefficient vector on x [0,1] independently of amount of values it contains."""
    ymax = yyy.max()
    plt.stem(np.linspace(0, 1., num=len(yyy)), yyy*(xmax/ymax), **kwargs)


x = pywt.data.ecg()
w = pywt.Wavelet('sym5')
nl = 6
coeffs = pywt.wavedec(x, w, level=nl)


'''
plt.figure()
plt.stem(coeffs[1]); plt.legend(['Lvl 6 detail coefficients'])
plt.figure()
plt.stem(coeffs[2]); plt.legend(['Lvl 5 detail coefficients'])
plt.figure()
plt.stem(coeffs[3]); plt.legend(['Lvl 4 detail coefficients'])
plt.figure()
plt.stem(coeffs[4]); plt.legend(['Lvl 3 detail coefficients'])
plt.figure()
plt.stem(coeffs[5]); plt.legend(['Lvl 2 detail coefficients'])
plt.figure()
plt.stem(coeffs[6]); plt.legend(['Lvl 1 detail coefficients'])
'''


xmax = x.max()
for i in range(nl):
    plt.figure()
    reconstruction_plot(x) # original signal 
    #reconstruction_plot(pywt.waverec(coeffs, w)) # full reconstruction 
    reconstruction_plot(pywt.waverec(coeffs[:i+2] + [None] * (nl-i-1), w)) # partial reconstruction 
    reconstruction_stem(coeffs[i+1], xmax, markerfmt ='none', linefmt='r-')
    #plt.legend(['Original', 'Full reconstruction', ('Rec to lvl %d')%(nl-i), ('Details for lvl %d')%(nl-i)])
    plt.legend(['Original', ('Rec to lvl %d')%(nl-i), ('Details for lvl %d')%(nl-i)])
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.