# 제 데이터 적용 예시

#### 데이터셋 선정 및 전처리

실제 데이터에 웨이블릿 변환을 적용하기 위해서는 먼저 어떤 종류의 데이터를 사용할지 명확히 정의해야 한다. 시간축에 따라 변화량이 커서 주파수 성분이 시시각각 달라지는 데이터가 웨이블릿 변환에 적합하다고 할 수 있다. 예컨대 지진파 관측 신호나 심전도(ECG), 음성 신호처럼 불규칙한 진동 및 잡음이 내재된 시계열 자료가 그 대표적인 예다. 이러한 데이터를 다룰 때 주파수-시간 분해능을 함께 확보하는 데 웨이블릿 변환이 유용하다.

데이터를 수집한 뒤에는 기본적인 전처리를 수행해야 한다. 만약 결측값이나 이상치가 포함되어 있다면 이를 제거하거나 적절히 보정한다. 예컨대 매우 큰 스파이크 노이즈가 순간적으로 들어갔다면, 측정 오류인지 실제 이벤트인지 판단해야 하고, 측정 오류라면 해당 구간을 평활화나 보간(interpolation) 기법으로 보정할 수 있다. 또한 필요하다면 데이터의 샘플링 주파수나 길이를 재설정할 수도 있다. 긴 시계열의 경우 연산량이나 메모리 문제를 고려하여 다운샘플링을 수행하고, 특정 분석 구간만을 발췌해 분석하기도 한다.

데이터의 기본 통계량을 확인해 값의 스케일과 분산 정도를 파악한다. 예컨대 시간 구간에 따른 평균, 표준편차 그리고 최대·최소값 등 기초 통계를 통해 신호의 거동을 미리 확인할 수 있다. 이러한 사전 지식은 웨이블릿 변환 결과물을 해석할 때 도움을 준다. 특히 너무 잡음이 심한 경우에는 간단한 필터링 기법(예: 저역통과 필터)을 통해 잡음을 제거한 뒤 웨이블릿 변환을 적용하는 전략도 가능하다.

#### 웨이블릿 변환 수행 절차

전처리를 마친 데이터에 웨이블릿 변환을 적용할 때, 우선 연속 웨이블릿 변환(CWT)으로 신호 전체의 시간-주파수 분포를 시각화해 패턴을 파악할 수 있다. 연속 웨이블릿 변환은 시간축에서 스케일 파라미터와 시프트 파라미터를 연속적으로 변화시키며 다음 식에 따라 계산한다.

$$
Wf(a, b) = \int\_{-\infty}^{+\infty} f(t),\psi!\Big(\frac{t - b}{a}\Big),dt
$$

여기서 aa는 스케일(scale)을 의미하며, 값이 작을수록 고주파 성분 분석에, 클수록 저주파 성분 분석에 적합하다. bb는 시간축에서 웨이블릿 함수를 이동시키는 파라미터다. ψ\psi는 모함수(mother wavelet)를 지칭한다. 이렇게 스케일과 시프트를 연속적으로 변화시키며 적분을 수행한 결과가 2차원 도메인에서의 웨이블릿 계수 행렬을 생성하게 된다.

보다 효율적인 계산이 필요하거나 다중 해상도 분석을 통해 단순화된 계층적 정보를 얻고자 한다면 이산 웨이블릿 변환(DWT)을 적용한다. 이산 웨이블릿 변환은 다단계 필터뱅크 구조를 이용하며 보통 다음 과정을 거쳐 신호를 하위 대역과 상위 대역으로 반복 분해한다. 필터와 다운샘플링 연산을 병행함으로써 각 단계에서 파장을 절반씩 줄이면서 저주파 대역과 고주파 대역을 분리하고, 이를 재귀적으로 실행하여 다양한 주파수 대역의 정보를 계층적으로 확보한다.

다음은 Python 환경에서 PyWavelets를 활용해 이산 웨이블릿 변환을 수행하는 예시 코드이다.

```python
import pywt
import numpy as np

# 예시용 랜덤 신호
data = np.random.randn(1024)

# Haar 웨이블릿을 사용한 DWT
coeffs = pywt.wavedec(data, 'haar', level=4)

# coeffs[0] 은 최저주파수(스케일이 가장 큰) 성분
# coeffs[1:] 은 여러 대역에서의 세부 성분
```

이때 coeffs 배열의 각 원소는 서로 다른 대역폭을 나타내며, level 파라미터로 웨이블릿 분해 단계를 지정할 수 있다. 예제에서는 level=4로 설정하여 네 번의 필터 분해가 이루어진다. 적절한 웨이블릿 종류(예: Haar, Daubechies, Symlet 등)를 선택하면 데이터 유형에 맞게 변환 결과를 해석하기 수월해진다.

#### 웨이블릿 계수 해석 및 시각화

연속 웨이블릿 변환 계수를 2차원 스펙트로그래프 형태로 시각화하면 시간축과 스케일축(또는 주파수 축)에서 신호 특성이 어떻게 분포하는지 직관적으로 파악할 수 있다. 특정 시점에서 저주파 성분이 강하게 나타나는지, 혹은 고주파 진동이 집중적으로 발생하는 구간은 언제인지 등의 정보를 하나의 그림 안에서 확인할 수 있다. 이러한 시각화 기법을 통해 데이터 내부의 트렌드나 이상 신호가 발생하는 구간을 쉽게 식별할 수 있다.

이산 웨이블릿 변환의 경우에는 다단계 분해를 통해 획득한 각 레벨별 세부 계수(고주파 성분)와 근사 계수(저주파 성분)를 확인한다. 예컨대 최고 레벨에서의 저주파 계수는 신호의 대략적인 추세(trend)를 보여주고, 각 레벨에서의 세부 계수는 점진적으로 높은 주파수 대역의 변화를 나타낸다. 이 계수들을 시각화하면 어느 대역에서 신호 변동이 심한지, 잡음은 어떤 패턴으로 분포하는지 등을 구체적으로 이해할 수 있다.

#### 부분 재구성(Partial Reconstruction)

웨이블릿 계수를 분석할 때 특정 대역만을 선별적으로 사용해 신호를 재구성하는 기법이 유용하다. 예컨대 저주파 대역만을 남기고 다시 합성하면 신호의 완만한 추세만을 살펴볼 수 있고, 특정 고주파 대역만을 남기고 재구성하면 빠른 진동이나 이변 이벤트 등을 강조해서 볼 수 있다. 이 과정은 다음 식에 의해 나타나는 역이산 웨이블릿 변환(IDWT)이나 역연속 웨이블릿 변환(ICWT)을 활용해 수행한다.

$$
f(t) = \sum\_{\text{모든 스케일 } a, \text{모든 시프트 } b} Wf(a, b),\psi\_{a,b}(t)
$$

이 때 ψa,b(t)\psi\_{a,b}(t)는 모함수를 스케일 aa와 시프트 bb만큼 변환한 웨이블릿 함수다. 일부 계수를 선택적으로 0으로 만들거나 특정 구간만 유지한 후 위 수식을 계산하면 부분 재구성이 이루어지며, 분석자가 관심 있는 대역의 정보만 따로 추출 가능하다.

#### 선택적 노이즈 제거(Thresholding) 기법

신호 내부의 잡음을 제거하기 위해서는 웨이블릿 영역에서 임계값(threshold)을 적용하는 방법이 널리 쓰인다. 전통적으로 Donoho가 제안한 VisuShrink 등의 기법은 잡음이 가우시안 백색잡음이라고 가정했을 때 이론적인 최적 임계값을 산출한다.

예시 코드를 통해 파이썬에서 간단히 구현해볼 수 있다.

```python
import pywt
import numpy as np

data = np.random.randn(1024)  
wavelet = 'db4'
level = 3

# 이산 웨이블릿 변환
coeffs = pywt.wavedec(data, wavelet, level=level)

# 계수에 임계값 적용(소프트 임계화 예시)
threshold = 0.5
new_coeffs = []
for c in coeffs:
    new_coeffs.append(pywt.threshold(c, threshold, mode='soft'))

# 노이즈 제거 후 신호 재구성
denoised_data = pywt.waverec(new_coeffs, wavelet)
```

코드에서 threshold 변수에 임의의 임계값을 설정하고, pywt.threshold 함수를 통해 소프트 임계화(soft thresholding)를 수행한다. 이렇게 하면 계수의 절댓값이 threshold 이하인 부분이 0이 되어 잡음이 억제된다. 실제 응용에서는 데이터 분포나 잡음 특성을 고려해 더 정밀하게 임계값을 설정해야 한다.

#### 다단계 분해 흐름도

아래는 이산 웨이블릿 변환 과정에서 이루어지는 필터뱅크 연산을 단순화한 흐름도다.

{% @mermaid/diagram content="graph TB
A(원 신호) --> B(저주파 대역 필터)
A(원 신호) --> C(고주파 대역 필터)
B --> D(다운샘플링)
C --> E(다운샘플링)
D --> F(저주파 계수)
E --> G(고주파 계수)" %}

저주파 계수(근사 성분)는 신호의 전반적인 형태를 나타내고, 고주파 계수(세부 성분)는 국소적 변화나 노이즈 등을 나타낸다. 이를 여러 번 반복해 다단계로 확장할 수 있으며, 각 단계에서 생성된 계수들은 서로 다른 주파수 구간을 대표한다.

#### 웨이블릿 계수 기반 특징 벡터 구성

웨이블릿 계수를 단순 시각화나 재구성에 활용하는 것을 넘어, 계수 자체를 분석용 특징(feature)으로 삼는 방법이 있다. 시계열 데이터를 분해하여 생성된 각 주파수 대역별 계수는 특정 진동 특성이나 이벤트 발생 시점에 대한 정보를 함축하고 있기 때문이다. 예컨대 전력 사용량 데이터에서 갑작스러운 급등 구간을 검출하거나, 진동 신호에서 베어링 결함으로 인한 특이 주파수 성분을 찾아낼 때 이러한 웨이블릿 계수가 유용하다.

계수 벡터를 구성할 때 특정 대역별 에너지를 추출하거나, 통계값(평균, 표준편차, 왜도, 첨도 등)을 계수에 적용하여 조합하는 방식이 흔히 활용된다. 예를 들어 이산 웨이블릿 변환으로 레벨 4까지 분해한 뒤, 각 레벨에서의 계수에 대해 다음과 같은 통계 지표를 구해 연결한 벡터를 구성할 수 있다.

$$
\mathbf{x} = \big\[ T\_1(\mathbf{c\_1}),,T\_2(\mathbf{c\_1}),,...,, T\_1(\mathbf{c\_j}),,T\_2(\mathbf{c\_j}),,... \big]
$$

이때 cj\mathbf{c\_j}는 각 레벨에서 산출된 계수 벡터를 의미하고, T1,T2T\_1, T\_2 등은 통계 함수를 가리킨다. 이 벡터를 분류기나 군집 알고리즘에 입력하여 패턴 인식을 수행하면, 같은 형태로 진동하는 신호끼리는 가까운 군집에 속하고, 다른 특성을 지니는 신호는 멀리 떨어져 배치된다.

#### 이벤트 검출과 이상신호 판별

이상신호나 이벤트가 발생할 때 웨이블릿 계수에서 급격한 변동이 포착된다. 시계열 데이터에서 특정 구간에만 고주파 성분이 치솟거나, 저주파 대역의 진폭이 갑작스레 커지는 패턴이 발견되면 이벤트 발생 시점으로 추정할 수 있다. 이러한 방법은 전통적인 푸리에 스펙트럼 분석보다 시간 해상도가 높아 이벤트 시점을 더욱 정확히 짚어낼 수 있다는 장점이 있다.

다음 코드는 다중 스케일에서 계수를 구한 뒤, 특정 기준값을 초과하는지 확인하여 이벤트 발생 구간을 검출하는 예시다.

```python
import pywt
import numpy as np

data = np.sin(np.linspace(0, 10*np.pi, 1024))
data[500:510] += 3.0  # 인위적으로 이상 이벤트 추가

wavelet = 'db4'
level = 4
coeffs = pywt.wavedec(data, wavelet, level=level)

# 예시로 가장 높은 대역(최고 레벨의 세부 계수)에 대한 이벤트 검출
detail_coeffs = coeffs[-1]  
threshold = np.std(detail_coeffs) * 2.5
events = np.where(np.abs(detail_coeffs) > threshold)[0]

# events 배열에 이벤트 발생 위치(인덱스)가 저장됨
```

코드에서는 단순히 계수의 절댓값이 일정 임계값을 초과하는 구간을 이상 이벤트로 간주한다. 실제 현장 데이터에서는 잡음이나 여러 원인에 의해 이벤트 구간이 간헐적으로 산재할 수 있으므로, 이벤트 후보 지점들을 묶어서 연속 구간인지 확인하는 후처리가 필요할 수 있다.

#### 웨이블릿 기반 특이점 탐지

웨이블릿 변환은 신호의 국소적 변동에 대한 민감도가 높아, 특이점(dissimilarity point)이나 에지(edge)를 검출하는 분야에서도 자주 쓰인다. 연속 웨이블릿 변환 계수를 통해 신호 도함수의 근사치를 구할 수 있으며, 이를 통해 기울기가 큰 지점을 쉽게 추적할 수 있다. 이미지를 2차원 웨이블릿 변환으로 분석하여 에지를 찾는 방법도 동일한 원리로 동작한다.

시계열에 대해서는 다음과 같은 아이디어를 적용할 수 있다. 특정 스케일에서 웨이블릿 변환 계수가 극대(또는 극소) 값을 보이는 시점을 모아서, 그 분포를 시계열 축에 매핑한다. 만약 여러 스케일에 걸쳐 비슷한 시점에서 극값이 중첩된다면, 그 지점이 신호의 특이점일 가능성이 크다고 볼 수 있다.

분석자는 이렇게 찾아낸 특이점이 실제로 의미 있는 이벤트인지, 단순 노이즈나 측정 오류에 의한 것인지 후속 검증 단계를 통해 판단한다.

#### 시간-주파수 스펙트럼 시각화

웨이블릿 변환으로 산출된 계수를 시각적으로 표현할 때는 시간축과 스케일(또는 주파수)축을 양축으로 하는 스펙트럼 맵을 활용한다. 이때 스케일 축은 실제 주파수 단위가 아니라 웨이블릿 스케일 변수로 표현되는 경우가 많다. 주파수로 직접 변환하려면 모함수의 중심 주파수(central frequency)나 변환 관계를 고려해야 하며, 다우베시스(Daubechies), 모라렛(Morlet) 등 각 웨이블릿별로 고유의 변환 계수가 존재한다.

분석 과정에서 특정 시점에 해당하는 열(column)을 살펴보면, 그 시점의 다양한 주파수(스케일) 성분이 어떤 세기로 존재하는지 확인할 수 있다. 시점이 고정된 상태에서 스케일축을 따라 계수가 어떤 분포를 보이는지를 조사하면, 그 지점에서 저주파가 우세한지 혹은 고주파가 우세한지 판별이 가능하다. 반대로 특정 스케일에 해당하는 행(row)을 살펴보면, 해당 주파수 대역이 시간에 따라 어떤 변화를 거치는지 확인할 수 있다. 예컨대 지진파 신호에서 특정 지점에 고주파 에너지가 집중되는지, 심전도 신호에서 R파 구간 근처에 뚜렷한 고주파 변화가 나타나는지 등을 쉽게 알 수 있다.

시각화를 위해 Python의 matplotlib과 PyWavelets를 결합하여 그림을 그리는 예시 코드는 다음과 같다.

```python
import numpy as np
import matplotlib.pyplot as plt
import pywt

data = np.sin(np.linspace(0, 10*np.pi, 1024))
wavelet = 'cmor'
scales = np.arange(1, 64)  # 스케일 범위
coeffs, freqs = pywt.cwt(data, scales, wavelet)

plt.imshow(np.abs(coeffs), extent=[0, len(data), 1, len(scales)], cmap='jet', aspect='auto', origin='lower')
plt.xlabel('Time')
plt.ylabel('Scale')
plt.title('CWT Spectrum')
plt.colorbar(label='Magnitude')
plt.show()
```

코드에서 pywt.cwt 함수를 이용해 연속 웨이블릿 변환을 수행하고, 결과인 coeffs 배열의 절댓값을 색상으로 표현한다. freqs에는 스케일과 웨이블릿 종류에 대응하는 실제 주파수 정보가 저장될 수 있으나, 상황에 따라 추가 계산이 필요할 수 있다.

#### 웨이블릿 결과 해석 가이드

신호가 일반적으로 저주파 성분이 두드러지거나 천천히 변하는 경우라면, 스케일이 큰 영역(저주파 범위)에서 계수가 크게 나타난다. 반대로 빠르게 진동하거나 급격한 변화를 보이는 경우는 스케일이 작은 영역(고주파 범위)에서 계수가 강조된다.

특정 구간에서 두 영역이 모두 활발하게 나타난다면, 그 시점에 다양한 주파수 대역의 이벤트가 복합적으로 발생하고 있음을 시사한다.

이상을 검출하거나 상태를 모니터링할 때, 웨이블릿 스펙트럼이 평소와 달리 한쪽 스케일에만 갑자기 강한 계수가 집중되는 상황을 주목하면 된다. 예컨대 회전 기계 부품에서 일정 저주파 대역의 에너지는 정상 작동을 반영하지만, 고주파 영역에서 이례적인 계수가 발생하면 결함이나 불균형의 징후일 수 있다.

웨이블릿 변환 결과를 다른 신호 분석 기법(예: 스펙트럼 밀도 추정, 단순 STFT)과 비교하며 교차 검증하는 것도 바람직하다. 웨이블릿 변환은 스케일을 연속적으로 변화시키거나 다단계 필터링으로 구현되므로, 각 스케일(또는 세부 대역)이 실제로 어떤 현상을 반영하는지 사전에 충분한 사전 지식이 있어야 분석이 수월해진다.
