본문 바로가기
딥러닝 with Python

[딥러닝 with Python] Mexican Hat Wavelet Transform을 활용한 시계열 데이터 처리

by CodeCrafter 2024. 10. 24.
반응형

 

이번에는 시계열 데이터 분석에서, 잡음을 최소화 시키고 시계열상 특정 패턴을 극대화 시키는 

 

Mexican Hat Wavelet Transform에 대해서 알아보겠습니다.

 

개념 정리 뿐만 아니라 파이썬 코드를 활용해서 예제 데이터에 대한 변환 및 결과 시각화 또한 진행해보겠습니다.

 

1. Mexican hat wavelet transform

- Mexican Hat Wavelet(Ricker Wavelet이라고도 불립니다)은 Gaussian 함수의 2차 미분 형태로 정의된 wavelet 입니다. 

이를 수식적으로 알아보면 아래와 같습니다.

 

 

* 여기서 t는 시간 축을 뜻하고, sigma는 scale을 뜻하고 이 값을 조정하면 wavelet의 넓이와 진폭이 조절되게 됩니다.

* sigma 값이 클수록 wavelet이 더 넓게 펼쳐지고 작을 수록 국소적 패턴에 더 민감하게 반응하게 됩니다.

 

- 이 함수는 중심에서 크게 발산한 후, 양 옆으로는 급겹히 줄어드는 종 모양의 커브를 가지게 되며, 이를 통해 시계열 데이터의 국부적(local) 특징을 강조하고, 특정 시간 구간에서 주파수 변화나 패턴의 차이를 민감하게 탐지할 수 있게 해줍니다.

 

- Maxican Hat Wavlet 함수에 대해서 시각화 해보면 아래와 같습니다.

 

import numpy as np
import matplotlib.pyplot as plt

def mexican_hat_wavelet(t, scale=1.0):
    """
    Mexican Hat Wavelet (Ricker Wavelet) 생성 함수
   
    Parameters:
    t : np.ndarray : 시간 또는 위치 벡터
    scale : float : 스케일 파라미터, 주파수 대역을 조정
   
    Returns:
    wavelet : np.ndarray : Mexican Hat Wavelet
    """
    C = 2 / (np.sqrt(3) * np.pi**0.25)  # 정규화 상수
    wavelet = C * (1 - (t / scale)**2) * np.exp(-(t / scale)**2 / 2)
    return wavelet

# 시간 벡터 생성
t = np.linspace(-5, 5, 500)

# 다양한 스케일로 Mexican Hat Wavelet 생성
scales = [0.5, 1.0, 2.0]

# 시각화
plt.figure(figsize=(10, 6))
for scale in scales:
    wavelet = mexican_hat_wavelet(t, scale=scale)
    plt.plot(t, wavelet, label=f'Scale = {scale}')

plt.title('Mexican Hat Wavelet (Ricker Wavelet)')
plt.xlabel('Time (t)')
plt.ylabel('Amplitude')
plt.legend()
plt.grid(True)
plt.show()

 

 

*이와 같이 scale(sigma) 값이 클수록 조금더 완만한 모자패턴을 보이며, scale이 작을수록 보다 좁은 구간에 대한 정보만 강조하는 패턴을 보이게 됩니다.

 

 

- 이러한 Maxican Hat Wavelet을 활용해 시계열 데이터를 변환(Transform) 하게되면 다음과 같은 장점을 가질 수 있습니다.

 

 1) 국소적 시간-주파수 분석 

  * 이 wavelet은 특정 시간 구간에서 일어나는 변화에 민감하게 반응하게 되는데, 중심 근처에서 높은 진폭을 가지지만, 양 옆으로 갈수록 급격히 줄어들게 됩니다. 그렇기에 국소적인 패턴을 증폭시킬 수 있게됩니다.

 2) Edge 및 Sharp transition 감지

 * 이 wavelet은 신호의 급격한 변화의 edge 또는 sharp transition을 탐지할 수 해줍니다. 즉, 신호의 중간 부분에서 변화가 생기게 된다면 이 변화를 증폭시켜주기 때문입니다.

 3) 다중 스케일 분석

 * 위 그림에서 보았듯 scale(sigma) 값을 변경하여 적용한다면, 국소적인 패턴에 대한 scale 또한 달라지기에 다양한 scale에서 변화가 증폭된 모습을 확인할 수 있습니다.

 

 

 

2.  예시 데이터를 통해 확인해보는 Mexican Hat Wavelet Transform

- 이번에는 시계열 데이터 예시를 생성해서 해당 Transform의 역할에 대해서 알아보겠습니다.

 

- 먼저, sine 함수에 노이즈를 추가한 시계열 데이터를 만들어줍니다.

# 예시 시계열 데이터 생성
np.random.seed(42)
time_steps = np.linspace(0, 50, 500)
signal = np.sin(time_steps) + np.random.normal(scale=0.5, size=time_steps.shape)

# 시계열 데이터 시각화
plt.figure(figsize=(10, 4))
plt.plot(time_steps, signal, label='Original Signal')
plt.title('Original Time Series Signal')
plt.xlabel('Time Steps')
plt.ylabel('Signal Value')
plt.grid(True)
plt.show()

 

 

- 다음으로 Mexican hat wavelet transform을 정의한 뒤, scale을 1로 해놓고 변환을 시켜보겠습니다.

from scipy.signal import convolve
import numpy as np
import matplotlib.pyplot as plt

def mexican_hat_wavelet(t, scale=1.0):
    """
    Mexican Hat Wavelet (Ricker Wavelet) 생성 함수
   
    Parameters:
    t : np.ndarray : 시간 또는 위치 벡터
    scale : float : 스케일 파라미터, 주파수 대역을 조정
   
    Returns:
    wavelet : np.ndarray : Mexican Hat Wavelet
    """
    C = 2 / (np.sqrt(3) * np.pi**0.25)  # 정규화 상수
    wavelet = C * (1 - (t / scale)**2) * np.exp(-(t / scale)**2 / 2)
    return wavelet


# Mexican Hat Wavelet 변환 적용
scale = 1.0
wavelet = mexican_hat_wavelet(np.linspace(-5, 5, 100), scale=scale)

# Convolution을 통해 시계열 데이터에 변환 적용
transformed_signal = convolve(signal, wavelet, mode='same')

# 변환된 시계열 데이터 시각화
plt.figure(figsize=(10, 4))
plt.plot(time_steps, transformed_signal, label='Wavelet Transformed Signal', color='orange')
plt.title('Wavelet Transformed Signal')
plt.xlabel('Time Steps')
plt.ylabel('Transformed Signal Value')
plt.grid(True)
plt.legend()
plt.show()

* 전반적인 패턴을 잘 포착하면서도 세부적인 noise를 제거해줌으로써 결과적으로 원형인 sine의 파형에 가까운 형태를 얻어낼 수 있는 것을 확인할 수 있습니다.

 

 

- 다음은 스케일을 바꿔가면서 진행해보겠습니다.

# 다양한 스케일로 시계열 데이터를 변환
scales = [0.5, 1.0, 2.0]
transformed_signals = []

for scale in scales:
    wavelet = mexican_hat_wavelet(np.linspace(-5, 5, 100), scale=scale)
    transformed_signal = convolve(signal, wavelet, mode='same')
    transformed_signals.append(transformed_signal)

# 여러 스케일에서의 변환 결과 시각화
plt.figure(figsize=(10, 6))
for i, scale in enumerate(scales):
    plt.plot(time_steps, transformed_signals[i], label=f'Scale = {scale}')

plt.title('Wavelet Transformed Signals at Different Scales')
plt.xlabel('Time Steps')
plt.ylabel('Transformed Signal Value')
plt.legend()
plt.grid(True)
plt.show()

* 스케일이 크게되면 전반적인 패턴을 더 강조하게 되는 것을 알 수있고, 스케일을 작게하면 전반적인 패턴 뿐만 아니라 국소적인 변화의 전반적인 변화까지 포착하는 모습을 알 수 있습니다.

 

 

- 이번에는 실제 데이터를 가지고 분석을 진행해보겠습니다. 분석에 활용할 데이터는 tsai 라이브러리를 활용해 UCR timeseries classification dataset 중 basic motions라는 데이터를 활용해보겠습니다.

 

- 먼저 tsai library를 설치해줍니다.

!pip install tsai

 

- 그리고 maxican hat wavelet transform을 정의한 뒤 basic motion data를 받아주고, 이를 바탕으로 scale을 달리해가며 변화를 확인해보겠습니다.

 

# 필요한 라이브러리 import
import numpy as np
import matplotlib.pyplot as plt
from tsai.all import get_UCR_data
import torch
import torch.nn.functional as F

# Mexican Hat Wavelet 함수 정의
def mexican_hat_wavelet(t, scale=1.0):
    C = 2 / (np.sqrt(3) * np.pi**0.25)  # 정규화 상수
    wavelet = C * (1 - (t / scale)**2) * np.exp(-(t / scale)**2 / 2)
    return wavelet.astype(np.float32)  # float32로 변환

# UCR 데이터 불러오기
X_train, y_train, X_test, y_test = get_UCR_data('BasicMotions', split_data=True)

# 시계열 데이터 시각화 함수
def plot_multivariate_timeseries(data, title="Original Multivariate Data", wavelet_transformed=False, scales=[1.0]):
    n_channels = data.shape[1]
    time_steps = data.shape[2]
   
    fig, axs = plt.subplots(n_channels, 1, figsize=(12, n_channels*2), sharex=True)
    t = np.linspace(-5, 5, time_steps)  # 시간 축 생성

    for i in range(n_channels):
        channel_data = data[0, i, :]  # 첫 번째 샘플의 i번째 채널 데이터
        axs[i].plot(channel_data, label=f'Original Channel {i+1}')
       
        # Mexican Hat Wavelet Transform을 적용한 경우
        if wavelet_transformed:
            for scale in scales:
                wavelet = mexican_hat_wavelet(t, scale=scale)
                transformed_data = F.conv1d(torch.tensor(channel_data).view(1, 1, -1).float(),
                                            torch.tensor(wavelet).view(1, 1, -1).float(), padding='same')
                axs[i].plot(transformed_data[0, 0].detach().numpy(),
                            label=f'Transformed (scale={scale})', linestyle='--')

        axs[i].set_ylabel(f'Channel {i+1}')
        axs[i].legend(bbox_to_anchor=(1.05, 1), loc='upper left')  # 범례를 우측에 배치
   
    plt.xlabel('Time Steps')
    plt.suptitle(title)
    plt.tight_layout()  # 그래프 레이아웃 자동 조정
    plt.show()

# 첫 번째 샘플에 대해 원본 데이터 시각화
plot_multivariate_timeseries(X_train, title="Original Multivariate Data")

# 첫 번째 샘플에 대해 Mexican Hat Wavelet Transform 후 시각화 (scale=0.5, 1.0, 1.5)
plot_multivariate_timeseries(X_train,
                             title="Transformed Multivariate Data with Mexican Hat Wavelet (scale=0.5, 1.0, 1.5)",
                             wavelet_transformed=True, scales=[0.5, 1.0, 1.5])

* 위 그림은 원본 데이터의 각 채널별 시계열에 따른 데이터의 모습을 시각화했습니다.

 

* 위 그림은 각 채널별 데이터에 대해 0.5 / 1 / 1.5 로 scale을 변경했을때 의 변화를 시각화 한 것입니다.

* 다중 scale의 정보를 활용한다면 큰 scale로부터 오는 전반적인 패턴이 강조된 정보와 작은 scale로부터 오는 국소적인 패턴까지도 강조된 정보가 융합되어 보다 세밀한 특징까지도 잘 잡아낼 수 있을 것 같습니다.

 

 

 

 

반응형

댓글