Sto cercando di visualizzare direttamente la relazione tra i coefficienti di dettaglio della trasformata wavelet discreta (DWT) e il segnale originale / la sua ricostruzione. L'obiettivo è mostrare la loro relazione in modo intuitivo. Vorrei porre (vedi le domande seguenti): se l'idea e il processo che ho escogitato sono corretti finora, e se ho ragione, potrebbe essere meglio sottrarre l'approssimazione di 1 ° livello dal segnale originale prima di visualizzare la loro relazione .
Esempio minimo
Ecco l'esempio minimo su cui baso la mia spiegazione, usando i dati di esempio ECG di Pythonpywavelets
, che ha 1024 valori, come un semplice segnale 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'])
La decomposizione viene eseguita utilizzando un Symmlet 5 con un totale di 6 livelli:
w = pywt.Wavelet('sym5')
plt.plot(w.dec_lo)
coeffs = pywt.wavedec(x, w, level=6)
La ricostruzione (con perdita) del segnale funziona come previsto quando si omettono intenzionalmente coefficienti di dettaglio di livello superiore (i segnali sono tracciati su scala x uniforme [0,1] per comodità):
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'])
Il DWT sopra fornisce un vettore di approssimazione di livello 1 di 24 valori, vettore di coefficienti di dettaglio di livello 1 di 24 valori, vettore di dettaglio di livello 2 di 40 valori, livello 3 di 72 valori, livello 4 di 135 valori, livello 5 di 262 valori e livello 6 di 516 valori:
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'])
Sembra che vediamo segnali chiari attorno ai picchi nei segnali originali (anche prestare attenzione alla scala y dei grafici sopra).
Ora alle mie domande:
- È corretto che possiamo collegare direttamente tali coefficienti al segnale? L'ampiezza del coefficiente corrisponde all'ampiezza con cui si verifica la wavelet nel segnale (asse y) e la posizione del coefficiente corrisponde al tempo (asse x). O c'è qualcosa nel mezzo che dobbiamo considerare?
Dopo il DWT rimane l'approssimazione finale lvl1. Ha senso non visualizzare la relazione dei coefficienti di dettaglio con il segnale originale, ma invece con il segnale originale meno l'approssimazione lvl1? (So che molto probabilmente vedrei anche la relazione tra coefficienti e segnale senza farlo, vedere ad esempio i grafici di seguito. È solo per questo che ha senso o no. Dovrebbe avere senso per i coefficienti di dettaglio di livello 1, potrebbe anche avere senso per coefficienti di dettaglio lvl2 da confrontare con il segnale originale meno l'approssimazione lvl2, giusto?). Un esempio:
# 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
La visualizzazione diretta della relazione tra i coefficienti di dettaglio e il segnale che uso traccia semplicemente sia il segnale che i coefficienti su un asse x di [0,1]. Ciò dovrebbe concettualmente essere valido, ma non sono sicuro che avrei effettivamente bisogno di un offset verso i margini (ad esempio, il primo e l'ultimo coefficiente del vettore non posizionato all'inizio o alla fine del segnale):
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'])
Esiste una spiegazione intuitiva per i coefficienti forti che non sono direttamente nelle posizioni dei picchi nei dati originali (ad esempio al livello 1 il più basso (negativo più forte) a circa 0,25, nonché il più alto (positivo più forte) intorno a 0,75 )? Sebbene esista un modello chiaro (ritardo positivo + ampiezza negativa, ritardo negativo + ampiezza positiva), per me sembrano un po '"lontani". Ma c'è probabilmente una buona spiegazione per questo.
Grazie per aver risposto!