Ich versuche, die Beziehung zwischen den Detailkoeffizienten der diskreten Wavelet-Transformation (DWT) und dem ursprünglichen Signal / seiner Rekonstruktion direkt zu visualisieren. Ziel ist es, ihre Beziehung intuitiv darzustellen. Ich möchte fragen (siehe Fragen unten): Wenn die Idee und der Prozess, die ich mir ausgedacht habe, bisher korrekt sind und wenn ich Recht habe, dass es besser ist, die Näherung der 1. Ebene vom ursprünglichen Signal zu subtrahieren, bevor ich ihre Beziehung visualisiere .
Minimales Beispiel
Hier ist das minimale Beispiel, auf das ich meine Erklärung stütze, indem ich die EKG-Beispieldaten von Pythonpywavelets
mit 1024 Werten als einfaches 1D-Signal verwende:
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'])
Die Zerlegung erfolgt mit einem Symmlet 5 mit insgesamt 6 Stufen:
w = pywt.Wavelet('sym5')
plt.plot(w.dec_lo)
coeffs = pywt.wavedec(x, w, level=6)
Die (verlustbehaftete) Rekonstruktion des Signals funktioniert wie erwartet, wenn absichtlich Detailkoeffizienten höherer Pegel weggelassen werden (Signale werden der Einfachheit halber auf einer einheitlichen x-Skala [0,1] aufgezeichnet):
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'])
Die obige DWT ergibt einen Näherungsvektor der Stufe 1 von 24 Werten, einen Detailkoeffizientenvektor der Stufe 1 von 24 Werten, einen Detailvektor der Stufe 2 von 40 Werten, eine Stufe 3 von 72 Werten, eine Stufe 4 von 135 Werten, eine Stufe 5 von 262 Werten und eine Stufe 6 von 516 Werten:
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'])
Es scheint, dass wir in den Originalsignalen klare Muster um die Spitzen sehen (achten Sie auch auf die y-Skala der obigen Diagramme).
Nun zu meinen Fragen:
- Ist es richtig, dass wir diese Koeffizienten direkt mit dem Signal in Beziehung setzen können ? Die Amplitude des Koeffizienten entspricht der Amplitude, mit der das Wavelet im Signal auftritt (y-Achse), und die Position des Koeffizienten entspricht der Zeit (x-Achse). Oder gibt es etwas dazwischen, das wir berücksichtigen müssen?
Nach dem DWT bleibt die endgültige lvl1-Näherung erhalten. Ist es sinnvoll, die Beziehung der Detailkoeffizienten zum Originalsignal nicht zu visualisieren, sondern zum Originalsignal abzüglich der lvl1-Näherung? (Ich weiß, dass ich höchstwahrscheinlich auch die Beziehung zwischen Koeffizienten und Signal sehen würde, ohne dies zu tun, siehe z. B. Diagramme unten. Es ist nur dafür sinnvoll oder nicht. Sollte es für lvl1-Detailkoeffizienten sinnvoll sein, könnte es auch sinnvoll sein für lvl2-Detailkoeffizienten, die mit dem ursprünglichen Signal abzüglich der lvl2-Näherung verglichen werden sollen, richtig?). Ein Beispiel:
# 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
Die direkte Visualisierung der Beziehung zwischen Detailkoeffizienten und Signal, die ich verwende, zeichnet nur das Signal und die Koeffizienten auf einer x-Achse von [0,1]. Dies sollte konzeptionell gültig sein, aber ich bin mir nicht sicher, ob ich tatsächlich einen Versatz zu den Rändern benötigen würde (z. B. erster und letzter Koeffizient des Vektors, der nicht ganz am Anfang oder Ende des Signals positioniert ist):
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'])
Gibt es eine intuitive Erklärung für die starken Koeffizienten, die sich nicht direkt an den Positionen der Peaks in den Originaldaten befinden (z. B. auf Stufe 1 die niedrigste (stärkste negative) bei etwa 0,25 sowie die höchste (stärkste positive) bei etwa 0,75 )? Obwohl es ein klares Muster gibt (positive Verzögerung + negative Amplitude, negative Verzögerung + positive Amplitude), scheinen diese für mich ein bisschen "weit weg" zu sein. Aber dafür gibt es wahrscheinlich eine gute Erklärung.
Danke für die Antwort!