시계열 데이터 전처리(Encoding Time Step Features)

2022. 1. 31. 16:55Data Science/02_Time Series Analysis

반응형

 

시계열 데이터를 분석하는 과정에서 주기적 성질 지니고 있는 데이터들을 빈번히 발견할 수 있습니다. 데이터가 주기적 성질을 지니고 있다면 사인함수, 코사인함수와 같은 삼각함수의 합으로 표현이 가능하고 이를 통해 데이터를 다른 관점에서 바라볼 수 있습니다. 

 

TIME SERIES FEATURES

시계열 데이터에는 일반적으로 시간 순차성(Time Step)과 지연값(Lag)이라는 고유한 2가지 특성이 존재합니다. 두 특성 모두 시간 축을 바탕으로 발생하며 시계열 문제를 머신러닝 모델로 접근하고 해결하기 위해 유용한 특성입니다. 첫번째, 시간 순차성(Time Step)은 시간축에서 직접 추출 가능하며 시작부터 끝가지 일정 시간 간격으로 측정된 년, 월, 일, 시간 특성이 대표적입니다. 이는 관측값이 주기적 성질을 지니고 있을 때 유용한 특성입니다. 두 번째, 지연 값(Lag)은 관측값에 시간 차이로 발생되며 현재 관측값들은 이전 관측값들로 표현됩니다. 이는 관측값이 자기 상관 또는 계열 상관성을 지니고 있을 때 유용한 특성입니다. 

 

이번 포스트에서는 시간 순차성(Time Step) 특성을 사용해서 주기적 성질을 지닌 시계열 데이터 패턴을보다 잘 이해하고 학습하기 위한 방법을 중점적으로 소개해드리겠습니다.

 

WHAT IS SEASONALITY

계절성(Seasonality)은 시간 순차적(Time Step) 특성에서 발생되는 대표적 요인 중 하나입니다. 여기서 계절성(Seasonaliy)이란 주기적 변동을 의미하며 시계열 데이터에서는 일, 주, 월, 년 단위로 관측값의 변동이 반복적으로 관측될 때 계절성을 나타낸다고 표현합니다.

 

주기적 변동인 계절성을 머신러닝 모델이 잘 이해하고 학습시키기 위한 데이터 전처리가 필요합니다. 1~24시, 월~일, 주 단위의 적은 관측값에서 발견되는 계절성은 특정 요일과 같이 해당 주기 단위를 직접 지시하여 표현하는 방법이 보다 유용하며 1/1~12/31, 위 그림 예시와 같이 년 단위 많은 관측값에서 발견되는 계절성은 푸리에 특징(Fourier Features)을 사용하여 표현하는 방식을 권장합니다.

 

FOURIER FEATURES

이 세상의 모든 복잡한 움직임 또는 운동이 주기적이란 성질을 갖고 있다면, 그것을 삼각함수(사인함수, 코사인 함수)로 이루어진 급수로 표현할 수 있다는 사실을 1822년 프랑스의 수학자 푸리에(Fourier, J.B.J. 1768~1830)가 발견했습니다. 삼각함수란 각에 대한 함수로서 삼각형의 각과 변의 길이를 연관시킨 것입니다. 그래서 우린 푸리에가 증명한 사실을 활용하여 복잡한 요소를 간단한 요소로 분해하고 그것을 재구성할 수 있습니다.

 

( 복잡한 주기성 데이터 ) = ( 사인 1 ) + ( 사인 2 ) + ( 코사인 1 ) + ( 코사인 2 ) +....

 

import numpy as np
import pandas as pd

def fourier_features(index, freq, order):
    time = np.arange(len(index), dtype=np.float32)
    k = 2 * np.pi * (1 / freq) * time
    features = {}
    for i in range(1, order + 1):
        features.update({
            f"sin_{freq}_{i}": np.sin(i * k),
            f"cos_{freq}_{i}": np.cos(i * k),
        })
    return pd.DataFrame(features, index=index)

 

위 증명을 활용하면 주기성을 지닌 시간 순차성(Time Step) 특성 데이터를 사인 함수와 코사인 함수로 변환해 머신러닝 모델이 패턴 학습을 보다 원활하도록 만들 수 있습니다. 이제 예제를 통해 시간 순차성 특징 데이터를 그대로 사용했을 때와 푸리에 특징으로 변환해 사용했을 때, 머신러닝 패턴 학습에 도움이 되는지를 비교해서 살펴보도록 하겠습니다.

 

EXAMPLE

데이콘에서 주관했던 동서발전 태양광 발전량 예측 AI 경진대회 데이터를 사용해서 활용하는 예시를 보여드리겠습니다.

 

https://dacon.io/competitions/official/235720/overview/description

 

동서발전 태양광 발전량 예측 AI 경진대회 - DACON

좋아요는 1분 내에 한 번만 클릭 할 수 있습니다.

dacon.io

 

데이터를 살펴보면 18-3-1부터 21-1-31일 까지 약 3년간 시간대별 태양광 발전량에 대한 데이터를 제공하고 있습니다. 간단한 비교 실험을 위해 당진 발전소에서 관측된 1년 치 데이터만 사용하고자 합니다. 시간대별 관측된 데이터이기 때문에 발전량의 주기성을 살펴보기 위해 시간축(=index)에서 시간 변수를 따로 추출하여 이를 같이 살펴봅니다.

 

시간대별 발전량을 살펴보면 하루 주기로 해가 뜨는 시점부터 발전량이 점차 증가하다가 해가 가장 높이 뜬 이후 지기 시작하면서 발전량이 감소하는 추세를 보이고 있습니다. 발전량 데이터는 하루 24시간을 기준으로 주기성을 지닌 시계열 데이터로 볼 수 있습니다. 그리고 태양이 뜨는 시간에 따라 발전량 추이를 보이고 있기 때문에 해가 빨리 뜨고 지는 계절 요인과 해를 가릴 수 있는 기상요인이 발전량에 영향을 미치는 주요 요인이라고 생각해볼 수 있을 것 같습니다.

 

 

머신러닝 모델에 주기성을 학습하기 위해서 우리는 시간 순차성(Time Step) 특성을 지닌 시간(Hour) 변수를 사전에 시간축에서 생성했습니다. 0~23시 까지 시간이 데이터로 표현됐기 때문에 머신러닝 모델은 이를 연속적으로 증가하는 숫자로 밖에 인식하지 못합니다. 그래서 3월 8일 23시와 3월 9일 0시를 23의 차이로 인식하게 되지만 실제 발전량은 0으로 차이가 없음을 보여주고 있습니다. 이런 시간 데이터를 그대로 머신러닝 모델에 학습하게 되면 연속적인 주기성을 제대로 학습하지 못하기 때문에 우리는 위에서 기술된 푸리에 특징을 사용하여 이를 간단한 요소로 분해하고 데이터가 연속성을 가질 수 있도록 표현합니다.

# Fourier Features
df['sin_hour_1'] = np.sin(2 * np.pi * df['hour']/24.0)
df['cos_hour_1'] = np.cos(2 * np.pi * df['hour']/24.0)

 

푸리에 특징으로 변환한 시간 데이터가 주기적 특징을 재대로 표현할 수 있는지 그림을 통해 직관적으로 확인할 수 있습니다.

 

 

이제 머신러닝 모델에 직접 입력해서 패턴 학습하는데 도움이 되는지, 아닌지를 비교해보겠습니다. 모델 학습 과정을 추적하기 위해 간단한 2개 층으로 구성된 DNN 모델을 구성하고 손실 함수는 MAE 학습률이 0.1인 Adam Optimizer를 사용했습니다. 이때 앞 11개월은 학습 데이터로 남은 1개월은 검증 데이터로 분리하여 진행했습니다.

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torch.utils.data as data_utils 

# DNN
class DNN(nn.Module):
    def __init__(self, x_dim):
        super(DNN, self).__init__()
        self.fc1 = nn.Linear(x_dim, 16)
        self.fc2 = nn.Linear(16, 8)
        self.fc3 = nn.Linear(8, 1)

    def forward(self, x):
        h1 = F.relu(self.fc1(x))
        h2 = F.relu(self.fc2(h1))
        
        return self.fc3(h2)

epoch = 100
lr = 0.1
optimizer = optim.Adam(model_raw.parameters(), lr=lr)
criterion = nn.L1Loss()

 

학습 후 두 실험의 결과를 살펴보면 그림에서 모두 푸리에 특징으로 변환했을 때 기존 시간 데이터를 입력하는 것에 비해 상대적으로 MAE가 낮고 수렴이 빠른 것을 확인할 수 있습니다.

 

LESSONS LEARNED

대부분의 사람들이 시계열 데이터 문제를 머신러닝 알고리즘으로 해결할 때 데이터보다 모델을 고도화하는데 더 많은 시간을 소요합니다. 하지만 사용하는 모델이 어떻게 데이터를 바라보는지 다시 한번 살펴보고 올바르게 입력해줘야 그 이후 단계에서 더 높은 성능 향상을 야기할 수 있습니다. 이번 포스트 예제에서는 푸리에 특징을 순환적인 측면에서 아주 간단하게 활용했지만 다른 차원에서의 해석이라는 관점에서도 응용할 수 있다면 복잡한 주기성을 지닌 데이터라도 쉽고 효과적으로 문제를 해결할 수 있습니다. 

반응형