티스토리 뷰
시계열 데이터 분석 EDA부터 MLP 신경망 예측모델 예제
peter was here 2021. 12. 29. 07:30안녕하세요.
오늘은 캐글의 유명한 시계열 예제자료를 정리해보려고합니다.
참고자료 링크를 참고해주세요.
https://www.kaggle.com/code/arindamgot/eda-prophet-mlp-neural-network-forecasting
https://www.kaggle.com/code/dimitreoliveira/deep-learning-for-time-series-forecasting
EDA+Prophet+ MLP Neural Network Forecasting
요약:
이 튜토리얼은 매장 품목 수요 예측 챌린지 대회를 위한 Prophet 및 MLP 신경망 예측 모델링을 사용한 포괄적인 탐색적 데이터 분석으로 구성되어 있습니다. 문제의 목표는 5년간의 판매 내역을 사용하여 10개 매장의 50개 품목에 대한 3개월 매출을 예측하는 것입니다.
데이터에는 다음 파일이 포함됩니다:
train.csv: 판매 이력이 없는 훈련 데이터입니다.
test.csv: 매출 예측을 위한 테스트 데이터.
샘플 제출.csv: 샘플 제출 파일
데이터 필드
date - 판매 데이터의 날짜입니다. 휴일 효과나 매장 휴무일은 포함되지 않습니다.
store - 스토어 ID
item - 품목 ID
판매 - 특정 날짜에 특정 스토어에서 판매된 품목 수입니다.
소개:
시계열 예측은 아는 사람이 거의 없는 기술입니다. 머신 러닝은 멋진 기술입니다. 그리고 많은 사람들이 머신 러닝 전문가가 되고 싶어 합니다. 하지만 예측은 약간 특정 분야에 국한된 기술입니다.
Walmart, Target과 같은 소매업체는 예측 시스템과 도구를 사용하여 매장에서 제품을 보충합니다. 우수한 예측 시스템은 공급망의 다른 파이프라인을 확보하는 데 도움이 됩니다. 매장에서 품목의 판매를 예측하는 데 능숙하다면 재고 수를 잘 계획 할 수 있습니다. 구색을 잘 계획 할 수 있습니다.
좋은 예측은 공급망의 다른 파이프라인에서 연이은 승리로 이어집니다.
시계열이란 무엇인가요?
시계열은 일정 시간 간격으로 수집된 일련의 관찰 자료입니다. 여기서 시간은 중요한 역할을 합니다. 수집된 관찰은 수집되는 시간에 따라 달라집니다.
예를 들어 월마트와 같은 소매점에서 빵이라는 품목의 판매량은 시계열이 될 것입니다. 판매는 일별 또는 시간별 수준일 수 있습니다. 매일 뉴욕에서 스페인으로 비행기를 타는 사람의 수는 시계열입니다. 여기서 중요한 것은 시간입니다. 크리스마스 연휴 기간에는 이 숫자가 다른 날에 비해 엄청나게 많을 것입니다. 이를 계절성이라고 합니다.
시계열과 정규 계열의 차이점은 무엇인가요?
여기서 중요한 것은 시간 요소입니다. 시계열은 시간에 따라 달라집니다. 그러나 1, 2, 3...100과 같은 정규 계열에는 시간 성분이 없습니다. 시계열이 취할 값이 기록된 시간에 따라 달라지는 경우 시계열입니다.
Frequency
Frequency를 설정할 때 많은 사람들이 정확한 값이 무엇인지 혼란스러워합니다. 이것이 빈도에 대한 간단한 정의입니다. 빈도는 주기당 관측 횟수입니다. 그렇다면 시계열에서 주기를 어떻게 정의할까요?
방갈로르의 시간별 전력 소비량이 있다고 가정해 보겠습니다. 주기는 하루, 일주일 또는 연간일 수 있습니다. 모든 다른 유형의 시계열에 대해 어떤 주기가 될지 다루겠습니다.
계속 진행하기 전에 다시 한 번 강조하겠습니다.
빈도는 주기당 관측 횟수입니다.
서로 다른 간격 시계열에 대해 빈도가 어떤 값을 취하는지 살펴보겠습니다.
일별 데이터 : 주별 주기 또는 연간 주기가 있을 수 있습니다. 따라서 빈도는 7 또는 365.25가 될 수 있습니다.
일부 연도에는 366일(윤년)이 있습니다. 따라서 시계열 데이터의 주기가 더 긴 경우 빈도 = 365.25를 사용하는 것이 좋습니다. 이렇게 하면 데이터에 포함될 수 있는 윤년도 처리됩니다.
주별 데이터 : 연간 주기가 있을 수 있습니다. frequency = 52를 사용하고 윤년을 처리하려면 frequency = 365.25/7을 사용합니다.
월별 데이터 : 주기는 1년입니다. 따라서 빈도 = 12
분기별 데이터: 다시 주기는 1년입니다. 따라서 빈도 = 4
연간 데이터 : 빈도 = 1
시간별, 30분, 분, 초 시계열 데이터와 같이 더 작은 간격의 빈도도 있을 수 있습니다.
시계열 예측을 위한 딥 러닝
전통적으로 시계열 예측은 선형 방법이 많은 간단한 예측 문제에 대해 잘 이해되고 효과적이기 때문에 선형 방법이 지배적이었습니다.
딥러닝 신경망은 입력에서 출력에 이르는 임의의 복잡한 매핑을 자동으로 학습할 수 있으며 여러 입력과 출력을 지원합니다.
다층 퍼셉트론(MLP)
일반적으로 다층 퍼셉트론 또는 MLP와 같은 신경망은 다음과 같은 소수의 알고리즘에서만 제공하는 기능을 제공합니다:
노이즈에 강함: 신경망은 입력 데이터와 매핑 함수의 노이즈에 강하며, 결측값이 있는 경우에도 학습과 예측을 지원할 수 있습니다.
비선형 : 신경망은 매핑 함수에 대해 강한 가정을 하지 않으며 선형 및 비선형 관계를 쉽게 학습합니다.
다변량 입력: 임의의 수의 입력 기능을 지정할 수 있어 다변량 예측을 직접 지원할 수 있습니다.
다단계 예측: 임의의 수의 출력 값을 지정할 수 있으므로 다단계 및 다변량 예측을 직접 지원합니다.
이러한 기능만으로도 피드포워드 신경망은 시계열 예측에 유용할 수 있습니다.
CNN
CNN은 이미지 데이터를 효율적으로 처리하도록 설계된 신경망의 한 유형입니다.
원시 입력 데이터에서 특징을 학습하고 자동으로 추출하는 CNN의 기능은 시계열 예측 문제에 적용할 수 있습니다. 일련의 관측값은 1차원 이미지처럼 취급할 수 있으며, CNN 모델은 이를 읽고 가장 두드러진 요소로 추출할 수 있습니다.
특징 학습(Feature Learning) : 모델링 중인 예측 문제와 직접적으로 관련된 원시 입력 데이터에서 두드러진 특징을 자동으로 식별, 추출 및 증류합니다.
CNN은 다변량 입력, 다변량 출력, 임의적이지만 복잡한 함수 관계 학습 지원 등 시계열 예측을 위한 다층 퍼셉트론의 이점을 활용하지만, 모델이 지연 관측으로부터 직접 학습할 필요는 없습니다. 대신, 모델은 예측 문제와 가장 관련성이 높은 대규모 입력 시퀀스로부터 표현을 학습할 수 있습니다.
장단기 기억 네트워크(LSTM)
장단기 기억 네트워크 또는 LSTM과 같은 순환 신경망은 입력에서 출력으로 매핑 함수를 학습할 때 MLP나 CNN이 제공하지 않는 관찰 사이의 순서를 명시적으로 처리하는 기능을 추가합니다. 이들은 관찰 시퀀스로 구성된 입력 데이터에 대한 기본 지원을 추가하는 신경망의 한 유형입니다.
시퀀스에 대한 네이티브 지원. 순환 신경망은 입력 시퀀스 데이터에 대한 지원을 직접 추가합니다.
LSTM의 이러한 기능은 한 언어를 다른 언어로 번역할 때 모델이 특정 언어 내 및 언어 간 단어 간의 복잡한 상호 관계를 학습해야 하는 신경망 기계 번역과 같은 복잡한 자연어 처리 문제에서 매우 효과적으로 사용되었습니다.
학습된 시간적 의존성. 예상 출력과 가장 관련성이 높은 입력 관찰의 컨텍스트가 학습되며 동적으로 변경될 수 있습니다.
모델은 입력에서 출력으로의 매핑을 학습하고 입력 시퀀스에서 어떤 컨텍스트가 매핑에 유용한지 학습하며 필요에 따라 이 컨텍스트를 동적으로 변경할 수 있습니다.
프로젝트명: 시계열 데이터 EDA¶
- 5년간의 매장 품목별 판매 데이터가 주어지며, 10개 매장에서 50개 품목의 3개월 매출을 예측하라는 요청을 받습니다.
from IPython.core.display import display, HTML
display(HTML("<style>.container {width:90% !important;}</style>"))
% pip install chart-studio
% pip install --upgrade nbformat
import warnings
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from keras import optimizers
from keras.utils import plot_model
from keras.models import Sequential, Model
from keras.layers import Dense, LSTM, RepeatVector, TimeDistributed, Flatten, Conv1D, MaxPooling1D, UpSampling1D, Input
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
import chart_studio.plotly as py
import plotly.graph_objs as go
from plotly.offline import init_notebook_mode, iplot
%matplotlib inline
warnings.filterwarnings("ignore")
init_notebook_mode(connected=True)
# Set seeds to make the experiment more reproducible.
import tensorflow as tf
from numpy.random import seed
tf.random.set_seed(1)
seed(1)
데이터 로딩¶
train = pd.read_csv('./timeseriesData/train.csv')
test = pd.read_csv('./timeseriesData/test.csv')
train.describe()
store | item | sales | |
---|---|---|---|
count | 913000.000000 | 913000.000000 | 913000.000000 |
mean | 5.500000 | 25.500000 | 52.250287 |
std | 2.872283 | 14.430878 | 28.801144 |
min | 1.000000 | 1.000000 | 0.000000 |
25% | 3.000000 | 13.000000 | 30.000000 |
50% | 5.500000 | 25.500000 | 47.000000 |
75% | 8.000000 | 38.000000 | 70.000000 |
max | 10.000000 | 50.000000 | 231.000000 |
train.head()
date | store | item | sales | |
---|---|---|---|---|
0 | 2013-01-01 | 1 | 1 | 13 |
1 | 2013-01-02 | 1 | 1 | 11 |
2 | 2013-01-03 | 1 | 1 | 14 |
3 | 2013-01-04 | 1 | 1 | 13 |
4 | 2013-01-05 | 1 | 1 | 10 |
데이터셋 시간¶
train['date'] = pd.to_datetime(train['date'])
test['date'] = pd.to_datetime(test['date'])
print('Min date from train set: %s' % train['date'].min().date())
print('Max date from train set: %s' % train['date'].max().date())
Min date from train set: 2013-01-01 Max date from train set: 2017-12-31
훈련 세트의 마지막 날과 테스트 세트의 마지막 날 사이의 시간 간격은 아웃랙(예측해야 하는 일수)이 될 것입니다.
lag_size = (test['date'].max().date() - train['date'].max().date()).days
print('Max date from train set: %s' % train['date'].max().date())
print('Max date from test set: %s' % test['date'].max().date())
print('✅ Forecast lag size', lag_size)
Max date from train set: 2017-12-31 Max date from test set: 2018-03-31 ✅ Forecast lag size 90
EDA¶
- 먼저 시계열 데이터를 탐색하려면 먼저 일별 매출을 집계해야 합니다.
daily_sales = train.groupby('date', as_index=False)['sales'].sum()
store_daily_sales = train.groupby(['store', 'date'], as_index=False)['sales'].sum()
item_daily_sales = train.groupby(['item', 'date'], as_index=False)['sales'].sum()
전체 일일 판매량¶
daily_sales_sc = go.Scatter(x=daily_sales['date'], y=daily_sales['sales'])
layout = go.Layout(title='Daily sales', xaxis=dict(title='Date'), yaxis=dict(title='Sales'))
fig = go.Figure(data=[daily_sales_sc], layout=layout)
iplot(fig)
스토어별 일일 판매량¶
store_daily_sales_sc = []
for store in store_daily_sales['store'].unique():
current_store_daily_sales = store_daily_sales[(store_daily_sales['store'] == store)]
store_daily_sales_sc.append(go.Scatter(x=current_store_daily_sales['date'], y=current_store_daily_sales['sales'], name=('Store %s' % store)))
layout = go.Layout(title='Store daily sales', xaxis=dict(title='Date'), yaxis=dict(title='Sales'))
fig = go.Figure(data=store_daily_sales_sc, layout=layout)
iplot(fig)
품목별 일일 판매량¶
item_daily_sales_sc = []
for item in item_daily_sales['item'].unique():
current_item_daily_sales = item_daily_sales[(item_daily_sales['item'] == item)]
item_daily_sales_sc.append(go.Scatter(x=current_item_daily_sales['date'], y=current_item_daily_sales['sales'], name=('Item %s' % item)))
layout = go.Layout(title='Item daily sales', xaxis=dict(title='Date'), yaxis=dict(title='Sales'))
fig = go.Figure(data=item_daily_sales_sc, layout=layout)
iplot(fig)
최근 1년간의 데이터만 가져와 훈련 시간을 단축하는 하위 샘플 훈련 세트¶
train = train[(train['date'] >= '2017-01-01')]
Shift 메서드를 적용할 수 있도록 데이터 세트 재배열¶
shift메서드는 시계열 데이터의 데이터나 인덱스를 원하는 기간만큼 쉬프트 하는 메서드 입니다.
df.shift(periods=1, freq=None, axis=0, fill_value=NoDefault.no_default)
- periods : 이동할 기간입니다.
- freq : 입력 할 경우 인덱스가 이동하게 됩니다. Y, M, D, H, T, S 나 Timestamp, 'Infer'등이 올 수 있습니다.
- fill_value : shift로 인해 생긴 결측치를 대체할 값입니다.
train_gp = train.sort_values('date').groupby(['item', 'store', 'date'], as_index=False)
train_gp = train_gp.agg({'sales':['mean']})
train_gp.columns = ['item', 'store', 'date', 'sales']
train_gp.head()
item | store | date | sales | |
---|---|---|---|---|
0 | 1 | 1 | 2017-01-01 | 19.0 |
1 | 1 | 1 | 2017-01-02 | 15.0 |
2 | 1 | 1 | 2017-01-03 | 10.0 |
3 | 1 | 1 | 2017-01-04 | 16.0 |
4 | 1 | 1 | 2017-01-05 | 14.0 |
train.query("store == 1 & item == 1").head()
date | store | item | sales | |
---|---|---|---|---|
1461 | 2017-01-01 | 1 | 1 | 19 |
1462 | 2017-01-02 | 1 | 1 | 15 |
1463 | 2017-01-03 | 1 | 1 | 10 |
1464 | 2017-01-04 | 1 | 1 | 16 |
1465 | 2017-01-05 | 1 | 1 | 14 |
데이터를 시계열 문제로 변환¶
def series_to_supervised(data, window=1, lag=1, dropnan=True):
cols, names = list(), list()
# Input sequence (t-n, ... t-1)
for i in range(window, 0, -1):
cols.append(data.shift(i))
names += [('%s(t-%d)' % (col, i)) for col in data.columns]
# Current timestep (t=0)
cols.append(data)
names += [('%s(t)' % (col)) for col in data.columns]
# Target timestep (t=lag)
cols.append(data.shift(-lag))
names += [('%s(t+%d)' % (col, lag)) for col in data.columns]
# Put it all together
agg = pd.concat(cols, axis=1)
agg.columns = names
# Drop rows with NaN values
if dropnan:
agg.dropna(inplace=True)
return agg
현재 시간 간격과 지난 29일을 사용하여 90일 전을 예측합니다.¶
window = 29
lag = lag_size
series = series_to_supervised(train_gp.drop('date', axis=1), window=window, lag=lag)
series.head()
item(t-29) | store(t-29) | sales(t-29) | item(t-28) | store(t-28) | sales(t-28) | item(t-27) | store(t-27) | sales(t-27) | item(t-26) | ... | sales(t-2) | item(t-1) | store(t-1) | sales(t-1) | item(t) | store(t) | sales(t) | item(t+90) | store(t+90) | sales(t+90) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
29 | 1.0 | 1.0 | 19.0 | 1.0 | 1.0 | 15.0 | 1.0 | 1.0 | 10.0 | 1.0 | ... | 16.0 | 1.0 | 1.0 | 24.0 | 1 | 1 | 9.0 | 1.0 | 1.0 | 33.0 |
30 | 1.0 | 1.0 | 15.0 | 1.0 | 1.0 | 10.0 | 1.0 | 1.0 | 16.0 | 1.0 | ... | 24.0 | 1.0 | 1.0 | 9.0 | 1 | 1 | 17.0 | 1.0 | 1.0 | 15.0 |
31 | 1.0 | 1.0 | 10.0 | 1.0 | 1.0 | 16.0 | 1.0 | 1.0 | 14.0 | 1.0 | ... | 9.0 | 1.0 | 1.0 | 17.0 | 1 | 1 | 15.0 | 1.0 | 1.0 | 21.0 |
32 | 1.0 | 1.0 | 16.0 | 1.0 | 1.0 | 14.0 | 1.0 | 1.0 | 24.0 | 1.0 | ... | 17.0 | 1.0 | 1.0 | 15.0 | 1 | 1 | 17.0 | 1.0 | 1.0 | 29.0 |
33 | 1.0 | 1.0 | 14.0 | 1.0 | 1.0 | 24.0 | 1.0 | 1.0 | 14.0 | 1.0 | ... | 15.0 | 1.0 | 1.0 | 17.0 | 1 | 1 | 24.0 | 1.0 | 1.0 | 19.0 |
5 rows × 93 columns
이동된 열과 다른 항목 또는 스토어 값이 있는 행을 삭제합니다.¶
last_item = 'item(t-%d)' % window
last_store = 'store(t-%d)' % window
series = series[(series['store(t)'] == series[last_store])]
series = series[(series['item(t)'] == series[last_item])]
원치 않는 열 제거¶
columns_to_drop = [('%s(t+%d)' % (col, lag)) for col in ['item', 'store']]
for i in range(window, 0, -1):
columns_to_drop += [('%s(t-%d)' % (col, i)) for col in ['item', 'store']]
series.drop(columns_to_drop, axis=1, inplace=True)
series.drop(['item(t)', 'store(t)'], axis=1, inplace=True)
훈련/검증셋 분할¶
# Label
labels_col = 'sales(t+%d)' % lag_size
labels = series[labels_col]
series = series.drop(labels_col, axis=1)
X_train, X_valid, Y_train, Y_valid = train_test_split(series, labels.values, test_size=0.4, random_state=0)
print('Train set shape', X_train.shape)
print('Validation set shape', X_valid.shape)
X_train.head()
Train set shape (100746, 30) Validation set shape (67164, 30)
sales(t-29) | sales(t-28) | sales(t-27) | sales(t-26) | sales(t-25) | sales(t-24) | sales(t-23) | sales(t-22) | sales(t-21) | sales(t-20) | ... | sales(t-9) | sales(t-8) | sales(t-7) | sales(t-6) | sales(t-5) | sales(t-4) | sales(t-3) | sales(t-2) | sales(t-1) | sales(t) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
18801 | 97.0 | 111.0 | 90.0 | 115.0 | 123.0 | 70.0 | 99.0 | 74.0 | 107.0 | 108.0 | ... | 85.0 | 95.0 | 123.0 | 109.0 | 127.0 | 132.0 | 87.0 | 101.0 | 102.0 | 114.0 |
160385 | 38.0 | 43.0 | 43.0 | 55.0 | 47.0 | 51.0 | 38.0 | 41.0 | 37.0 | 59.0 | ... | 41.0 | 38.0 | 38.0 | 53.0 | 53.0 | 45.0 | 44.0 | 24.0 | 30.0 | 37.0 |
73123 | 55.0 | 45.0 | 41.0 | 46.0 | 47.0 | 36.0 | 30.0 | 46.0 | 41.0 | 42.0 | ... | 38.0 | 36.0 | 40.0 | 50.0 | 44.0 | 44.0 | 40.0 | 38.0 | 50.0 | 49.0 |
90428 | 139.0 | 157.0 | 85.0 | 99.0 | 136.0 | 110.0 | 121.0 | 123.0 | 147.0 | 91.0 | ... | 130.0 | 128.0 | 128.0 | 95.0 | 116.0 | 110.0 | 117.0 | 118.0 | 129.0 | 132.0 |
167151 | 86.0 | 58.0 | 88.0 | 87.0 | 114.0 | 113.0 | 64.0 | 76.0 | 87.0 | 81.0 | ... | 55.0 | 66.0 | 59.0 | 53.0 | 63.0 | 59.0 | 77.0 | 39.0 | 56.0 | 62.0 |
5 rows × 30 columns
시계열 예측을 위한 MLP¶
먼저 다층 퍼셉트론 모델 또는 MLP 모델을 사용하며, 여기서는 모델에 창 크기와 동일한 입력 특징을 갖습니다.
MLP 모델의 문제는 모델이 입력을 시퀀스 데이터로 간주하지 않는다는 것입니다. 즉, 모델에서는 입력을 받기만 하고 시퀀스 데이터로 취급하지 않기 때문에 모델이 가지고 있는 시퀀스 패턴을 가진 데이터를 보지 못하기 때문에 문제가 될 수 있습니다.
입력 모양 [샘플, 타임스텝].
epochs = 40
batch = 256
lr = 0.0003
adam = optimizers.Adam(lr)
WARNING:absl:At this time, the v2.11+ optimizer `tf.keras.optimizers.Adam` runs slowly on M1/M2 Macs, please use the legacy Keras optimizer instead, located at `tf.keras.optimizers.legacy.Adam`.
model_mlp = Sequential()
model_mlp.add(Dense(100, activation='relu', input_dim=X_train.shape[1]))
model_mlp.add(Dense(1))
model_mlp.compile(loss='mse', optimizer=adam)
model_mlp.summary()
WARNING:absl:There is a known slowdown when using v2.11+ Keras optimizers on M1/M2 Macs. Falling back to the legacy Keras optimizer, i.e., `tf.keras.optimizers.legacy.Adam`.
Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense (Dense) (None, 100) 3100 dense_1 (Dense) (None, 1) 101 ================================================================= Total params: 3201 (12.50 KB) Trainable params: 3201 (12.50 KB) Non-trainable params: 0 (0.00 Byte) _________________________________________________________________
mlp_history = model_mlp.fit(X_train.values, Y_train, validation_data=(X_valid.values, Y_valid), epochs=epochs, verbose=2)
Epoch 1/40 3149/3149 - 2s - loss: 396.3969 - val_loss: 379.5166 - 2s/epoch - 643us/step Epoch 2/40 3149/3149 - 2s - loss: 366.2606 - val_loss: 368.9050 - 2s/epoch - 536us/step Epoch 3/40 3149/3149 - 2s - loss: 359.3035 - val_loss: 375.8625 - 2s/epoch - 548us/step Epoch 4/40 3149/3149 - 2s - loss: 357.5632 - val_loss: 403.1906 - 2s/epoch - 583us/step Epoch 5/40 3149/3149 - 2s - loss: 356.1672 - val_loss: 355.8921 - 2s/epoch - 544us/step Epoch 6/40 3149/3149 - 2s - loss: 354.7909 - val_loss: 355.0562 - 2s/epoch - 534us/step Epoch 7/40 3149/3149 - 2s - loss: 353.3270 - val_loss: 359.3532 - 2s/epoch - 547us/step Epoch 8/40 3149/3149 - 2s - loss: 352.2565 - val_loss: 350.7974 - 2s/epoch - 589us/step Epoch 9/40 3149/3149 - 2s - loss: 352.2160 - val_loss: 352.4015 - 2s/epoch - 612us/step Epoch 10/40 3149/3149 - 2s - loss: 350.6200 - val_loss: 349.3686 - 2s/epoch - 598us/step Epoch 11/40 3149/3149 - 2s - loss: 350.1575 - val_loss: 348.0919 - 2s/epoch - 555us/step Epoch 12/40 3149/3149 - 2s - loss: 348.4353 - val_loss: 347.1646 - 2s/epoch - 605us/step Epoch 13/40 3149/3149 - 2s - loss: 349.7021 - val_loss: 349.6477 - 2s/epoch - 576us/step Epoch 14/40 3149/3149 - 2s - loss: 347.5685 - val_loss: 346.2853 - 2s/epoch - 610us/step Epoch 15/40 3149/3149 - 2s - loss: 346.8908 - val_loss: 345.6575 - 2s/epoch - 564us/step Epoch 16/40 3149/3149 - 2s - loss: 346.2986 - val_loss: 346.8796 - 2s/epoch - 572us/step Epoch 17/40 3149/3149 - 2s - loss: 346.1219 - val_loss: 347.3234 - 2s/epoch - 548us/step Epoch 18/40 3149/3149 - 2s - loss: 344.9705 - val_loss: 349.8490 - 2s/epoch - 538us/step Epoch 19/40 3149/3149 - 2s - loss: 345.0424 - val_loss: 346.3539 - 2s/epoch - 521us/step Epoch 20/40 3149/3149 - 2s - loss: 345.1784 - val_loss: 346.9681 - 2s/epoch - 530us/step Epoch 21/40 3149/3149 - 2s - loss: 343.8085 - val_loss: 344.3501 - 2s/epoch - 621us/step Epoch 22/40 3149/3149 - 2s - loss: 344.3694 - val_loss: 344.5008 - 2s/epoch - 551us/step Epoch 23/40 3149/3149 - 2s - loss: 343.0603 - val_loss: 352.8784 - 2s/epoch - 623us/step Epoch 24/40 3149/3149 - 2s - loss: 342.8095 - val_loss: 346.7376 - 2s/epoch - 543us/step Epoch 25/40 3149/3149 - 2s - loss: 342.5796 - val_loss: 342.9323 - 2s/epoch - 539us/step Epoch 26/40 3149/3149 - 2s - loss: 342.1869 - val_loss: 347.7767 - 2s/epoch - 552us/step Epoch 27/40 3149/3149 - 2s - loss: 342.2159 - val_loss: 342.7872 - 2s/epoch - 542us/step Epoch 28/40 3149/3149 - 2s - loss: 341.7807 - val_loss: 342.7688 - 2s/epoch - 545us/step Epoch 29/40 3149/3149 - 2s - loss: 341.6082 - val_loss: 343.0625 - 2s/epoch - 557us/step Epoch 30/40 3149/3149 - 2s - loss: 340.9452 - val_loss: 345.7379 - 2s/epoch - 597us/step Epoch 31/40 3149/3149 - 2s - loss: 341.0605 - val_loss: 348.1864 - 2s/epoch - 543us/step Epoch 32/40 3149/3149 - 2s - loss: 340.8973 - val_loss: 341.8463 - 2s/epoch - 560us/step Epoch 33/40 3149/3149 - 2s - loss: 340.2986 - val_loss: 342.3676 - 2s/epoch - 541us/step Epoch 34/40 3149/3149 - 2s - loss: 340.1338 - val_loss: 341.5905 - 2s/epoch - 529us/step Epoch 35/40 3149/3149 - 2s - loss: 340.3444 - val_loss: 344.4470 - 2s/epoch - 557us/step Epoch 36/40 3149/3149 - 2s - loss: 339.6569 - val_loss: 343.0800 - 2s/epoch - 551us/step Epoch 37/40 3149/3149 - 2s - loss: 339.4244 - val_loss: 341.0579 - 2s/epoch - 525us/step Epoch 38/40 3149/3149 - 2s - loss: 339.6766 - val_loss: 341.6023 - 2s/epoch - 550us/step Epoch 39/40 3149/3149 - 2s - loss: 339.1985 - val_loss: 341.3847 - 2s/epoch - 555us/step Epoch 40/40 3149/3149 - 2s - loss: 338.9035 - val_loss: 340.9991 - 2s/epoch - 546us/step
X_train_series = X_train.values.reshape((X_train.shape[0], X_train.shape[1], 1))
X_valid_series = X_valid.values.reshape((X_valid.shape[0], X_valid.shape[1], 1))
print('Train set shape', X_train_series.shape)
print('Validation set shape', X_valid_series.shape)
Train set shape (100746, 30, 1) Validation set shape (67164, 30, 1)
model_cnn = Sequential()
model_cnn.add(Conv1D(filters=64, kernel_size=2, activation='relu', input_shape=(X_train_series.shape[1], X_train_series.shape[2])))
model_cnn.add(MaxPooling1D(pool_size=2))
model_cnn.add(Flatten())
model_cnn.add(Dense(50, activation='relu'))
model_cnn.add(Dense(1))
model_cnn.compile(loss='mse', optimizer=adam)
model_cnn.summary()
WARNING:absl:There is a known slowdown when using v2.11+ Keras optimizers on M1/M2 Macs. Falling back to the legacy Keras optimizer, i.e., `tf.keras.optimizers.legacy.Adam`.
Model: "sequential_1" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv1d (Conv1D) (None, 29, 64) 192 max_pooling1d (MaxPooling1 (None, 14, 64) 0 D) flatten (Flatten) (None, 896) 0 dense_2 (Dense) (None, 50) 44850 dense_3 (Dense) (None, 1) 51 ================================================================= Total params: 45093 (176.14 KB) Trainable params: 45093 (176.14 KB) Non-trainable params: 0 (0.00 Byte) _________________________________________________________________
cnn_history = model_cnn.fit(X_train_series, Y_train, validation_data=(X_valid_series, Y_valid), epochs=epochs, verbose=2)
Epoch 1/40 3149/3149 - 4s - loss: 416.6276 - val_loss: 385.3966 - 4s/epoch - 1ms/step Epoch 2/40 3149/3149 - 4s - loss: 382.4027 - val_loss: 380.2587 - 4s/epoch - 1ms/step Epoch 3/40 3149/3149 - 4s - loss: 371.8884 - val_loss: 374.3435 - 4s/epoch - 1ms/step Epoch 4/40 3149/3149 - 4s - loss: 367.5677 - val_loss: 388.6271 - 4s/epoch - 1ms/step Epoch 5/40 3149/3149 - 4s - loss: 365.0448 - val_loss: 362.2592 - 4s/epoch - 1ms/step Epoch 6/40 3149/3149 - 4s - loss: 362.3233 - val_loss: 358.2687 - 4s/epoch - 1ms/step Epoch 7/40 3149/3149 - 4s - loss: 359.7003 - val_loss: 364.5050 - 4s/epoch - 1ms/step Epoch 8/40 3149/3149 - 4s - loss: 358.1824 - val_loss: 355.2060 - 4s/epoch - 1ms/step Epoch 9/40 3149/3149 - 4s - loss: 357.9132 - val_loss: 356.8325 - 4s/epoch - 1ms/step Epoch 10/40 3149/3149 - 4s - loss: 356.6407 - val_loss: 353.2965 - 4s/epoch - 1ms/step Epoch 11/40 3149/3149 - 4s - loss: 355.3461 - val_loss: 351.6753 - 4s/epoch - 1ms/step Epoch 12/40 3149/3149 - 4s - loss: 354.1398 - val_loss: 351.7066 - 4s/epoch - 1ms/step Epoch 13/40 3149/3149 - 4s - loss: 355.3559 - val_loss: 350.5958 - 4s/epoch - 1ms/step Epoch 14/40 3149/3149 - 3s - loss: 352.9973 - val_loss: 350.5712 - 3s/epoch - 1ms/step Epoch 15/40 3149/3149 - 4s - loss: 351.9606 - val_loss: 349.1543 - 4s/epoch - 1ms/step Epoch 16/40 3149/3149 - 4s - loss: 351.6832 - val_loss: 351.2996 - 4s/epoch - 1ms/step Epoch 17/40 3149/3149 - 3s - loss: 351.7888 - val_loss: 349.1966 - 3s/epoch - 1ms/step Epoch 18/40 3149/3149 - 4s - loss: 350.3259 - val_loss: 351.0319 - 4s/epoch - 1ms/step Epoch 19/40 3149/3149 - 4s - loss: 350.3320 - val_loss: 352.5304 - 4s/epoch - 1ms/step Epoch 20/40 3149/3149 - 3s - loss: 349.9321 - val_loss: 349.4299 - 3s/epoch - 1ms/step Epoch 21/40 3149/3149 - 4s - loss: 348.8243 - val_loss: 348.1661 - 4s/epoch - 1ms/step Epoch 22/40 3149/3149 - 4s - loss: 348.9481 - val_loss: 348.0063 - 4s/epoch - 1ms/step Epoch 23/40 3149/3149 - 4s - loss: 348.0279 - val_loss: 350.9103 - 4s/epoch - 1ms/step Epoch 24/40 3149/3149 - 4s - loss: 348.1477 - val_loss: 351.3934 - 4s/epoch - 1ms/step Epoch 25/40 3149/3149 - 4s - loss: 347.7791 - val_loss: 346.3423 - 4s/epoch - 1ms/step Epoch 26/40 3149/3149 - 4s - loss: 347.2347 - val_loss: 352.7809 - 4s/epoch - 1ms/step Epoch 27/40 3149/3149 - 4s - loss: 347.0481 - val_loss: 349.6030 - 4s/epoch - 1ms/step Epoch 28/40 3149/3149 - 4s - loss: 346.9179 - val_loss: 347.3602 - 4s/epoch - 1ms/step Epoch 29/40 3149/3149 - 4s - loss: 346.7733 - val_loss: 352.0360 - 4s/epoch - 1ms/step Epoch 30/40 3149/3149 - 4s - loss: 345.9154 - val_loss: 346.0894 - 4s/epoch - 1ms/step Epoch 31/40 3149/3149 - 4s - loss: 346.4319 - val_loss: 349.2456 - 4s/epoch - 1ms/step Epoch 32/40 3149/3149 - 4s - loss: 345.9860 - val_loss: 345.7122 - 4s/epoch - 1ms/step Epoch 33/40 3149/3149 - 4s - loss: 345.0620 - val_loss: 346.4684 - 4s/epoch - 1ms/step Epoch 34/40 3149/3149 - 4s - loss: 345.2938 - val_loss: 345.7900 - 4s/epoch - 1ms/step Epoch 35/40 3149/3149 - 4s - loss: 345.8746 - val_loss: 345.9126 - 4s/epoch - 1ms/step Epoch 36/40 3149/3149 - 4s - loss: 345.0094 - val_loss: 347.6612 - 4s/epoch - 1ms/step Epoch 37/40 3149/3149 - 4s - loss: 344.4051 - val_loss: 346.8896 - 4s/epoch - 1ms/step Epoch 38/40 3149/3149 - 4s - loss: 344.3102 - val_loss: 346.3592 - 4s/epoch - 1ms/step Epoch 39/40 3149/3149 - 4s - loss: 344.4929 - val_loss: 350.8293 - 4s/epoch - 1ms/step Epoch 40/40 3149/3149 - 4s - loss: 344.2085 - val_loss: 345.2132 - 4s/epoch - 1ms/step
시계열 예측을 위한 LSTM¶
이제 LSTM 모델은 입력 데이터를 실제로 시퀀스로 간주하므로 시퀀스 데이터(존재한다고 가정할 때)의 패턴, 특히 긴 시퀀스의 패턴을 다른 데이터보다 더 잘 학습할 수 있습니다.
입력 형태[샘플, 타임스텝, 특징].
model_lstm = Sequential()
model_lstm.add(LSTM(50, activation='relu', input_shape=(X_train_series.shape[1], X_train_series.shape[2])))
model_lstm.add(Dense(1))
model_lstm.compile(loss='mse', optimizer=adam)
model_lstm.summary()
WARNING:absl:There is a known slowdown when using v2.11+ Keras optimizers on M1/M2 Macs. Falling back to the legacy Keras optimizer, i.e., `tf.keras.optimizers.legacy.Adam`.
Model: "sequential_2" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= lstm (LSTM) (None, 50) 10400 dense_4 (Dense) (None, 1) 51 ================================================================= Total params: 10451 (40.82 KB) Trainable params: 10451 (40.82 KB) Non-trainable params: 0 (0.00 Byte) _________________________________________________________________
lstm_history = model_lstm.fit(X_train_series, Y_train, validation_data=(X_valid_series, Y_valid), epochs=epochs, verbose=2)
Epoch 1/40 3149/3149 - 18s - loss: 554.4108 - val_loss: 396.6067 - 18s/epoch - 6ms/step Epoch 2/40 3149/3149 - 17s - loss: 390.2535 - val_loss: 378.9348 - 17s/epoch - 5ms/step Epoch 3/40 3149/3149 - 17s - loss: 5158.5996 - val_loss: 1182.8748 - 17s/epoch - 5ms/step Epoch 4/40 3149/3149 - 17s - loss: 797.6190 - val_loss: 688.6217 - 17s/epoch - 6ms/step Epoch 5/40 3149/3149 - 18s - loss: 615.0568 - val_loss: 518.8363 - 18s/epoch - 6ms/step Epoch 6/40 3149/3149 - 19s - loss: 509.6998 - val_loss: 476.5875 - 19s/epoch - 6ms/step Epoch 7/40 3149/3149 - 17s - loss: 720.3445 - val_loss: 459.1210 - 17s/epoch - 6ms/step Epoch 8/40 3149/3149 - 17s - loss: 431.6709 - val_loss: 418.8097 - 17s/epoch - 5ms/step Epoch 9/40 3149/3149 - 17s - loss: 411.1090 - val_loss: 392.1525 - 17s/epoch - 5ms/step Epoch 10/40 3149/3149 - 17s - loss: 396.3724 - val_loss: 377.1552 - 17s/epoch - 5ms/step Epoch 11/40 3149/3149 - 18s - loss: 385.8648 - val_loss: 369.6293 - 18s/epoch - 6ms/step Epoch 12/40 3149/3149 - 18s - loss: 426.6447 - val_loss: 420.7054 - 18s/epoch - 6ms/step Epoch 13/40 3149/3149 - 18s - loss: 404.5239 - val_loss: 401.2089 - 18s/epoch - 6ms/step Epoch 14/40 3149/3149 - 17s - loss: 389.9123 - val_loss: 373.9110 - 17s/epoch - 5ms/step Epoch 15/40 3149/3149 - 17s - loss: 374.9588 - val_loss: 361.7022 - 17s/epoch - 5ms/step Epoch 16/40 3149/3149 - 18s - loss: 370.0253 - val_loss: 365.5591 - 18s/epoch - 6ms/step Epoch 17/40 3149/3149 - 17s - loss: 362.0866 - val_loss: 353.2251 - 17s/epoch - 5ms/step Epoch 18/40 3149/3149 - 17s - loss: 505.5952 - val_loss: 452.5145 - 17s/epoch - 5ms/step Epoch 19/40 3149/3149 - 19s - loss: 444.0021 - val_loss: 427.2990 - 19s/epoch - 6ms/step Epoch 20/40 3149/3149 - 17s - loss: 447.1860 - val_loss: 450.2357 - 17s/epoch - 5ms/step Epoch 21/40 3149/3149 - 17s - loss: 399.5898 - val_loss: 379.0370 - 17s/epoch - 5ms/step Epoch 22/40 3149/3149 - 17s - loss: 371.7841 - val_loss: 360.4494 - 17s/epoch - 5ms/step Epoch 23/40 3149/3149 - 17s - loss: 360.5386 - val_loss: 353.1322 - 17s/epoch - 5ms/step Epoch 24/40 3149/3149 - 16s - loss: 357.3221 - val_loss: 359.2216 - 16s/epoch - 5ms/step Epoch 25/40 3149/3149 - 17s - loss: 356.6743 - val_loss: 348.9269 - 17s/epoch - 5ms/step Epoch 26/40 3149/3149 - 16s - loss: 353.0755 - val_loss: 353.7444 - 16s/epoch - 5ms/step Epoch 27/40 3149/3149 - 17s - loss: 352.6855 - val_loss: 349.9156 - 17s/epoch - 5ms/step Epoch 28/40 3149/3149 - 17s - loss: 2541.1145 - val_loss: 1453.3063 - 17s/epoch - 5ms/step Epoch 29/40 3149/3149 - 17s - loss: 737.7278 - val_loss: 562.4361 - 17s/epoch - 5ms/step Epoch 30/40 3149/3149 - 17s - loss: 525.0943 - val_loss: 529.4332 - 17s/epoch - 5ms/step Epoch 31/40 3149/3149 - 16s - loss: 504.4711 - val_loss: 482.4516 - 16s/epoch - 5ms/step Epoch 32/40 3149/3149 - 16s - loss: 482.7142 - val_loss: 467.3408 - 16s/epoch - 5ms/step Epoch 33/40 3149/3149 - 17s - loss: 473.2296 - val_loss: 538.8206 - 17s/epoch - 5ms/step Epoch 34/40 3149/3149 - 17s - loss: 475.2652 - val_loss: 434.5337 - 17s/epoch - 5ms/step Epoch 35/40 3149/3149 - 17s - loss: 467.6940 - val_loss: 429.9221 - 17s/epoch - 5ms/step Epoch 36/40 3149/3149 - 16s - loss: 7011.8911 - val_loss: 489.4835 - 16s/epoch - 5ms/step Epoch 37/40 3149/3149 - 16s - loss: 439.2045 - val_loss: 403.6780 - 16s/epoch - 5ms/step Epoch 38/40 3149/3149 - 16s - loss: 390.4368 - val_loss: 383.6205 - 16s/epoch - 5ms/step Epoch 39/40 3149/3149 - 17s - loss: 380.0942 - val_loss: 376.0169 - 17s/epoch - 5ms/step Epoch 40/40 3149/3149 - 17s - loss: 377.5092 - val_loss: 372.9893 - 17s/epoch - 5ms/step
시계열 예측을 위한 CNN-LSTM¶
- 입력 형태[샘플, 시퀀스, 시간 간격, 특징]를 입력합니다.
기사에서 모델 설명
"이 모델의 장점은 매우 긴 입력 시퀀스를 지원할 수 있다는 점이며, 이 모델은 CNN 모델에서 블록 또는 시퀀스로 읽은 다음 LSTM 모델에서 함께 조합할 수 있습니다."
"하이브리드 CNN-LSTM 모델을 사용할 때는 각 샘플을 더 많은 하위 시퀀스로 나눕니다. CNN 모델은 각 하위 시퀀스를 해석하고 LSTM은 각 시퀀스의 해석을 종합합니다. 따라서 각 샘플을 시퀀스당 2번씩 2개의 시퀀스로 분할할 것입니다."
"CNN은 하나의 피처로 시퀀스당 2개의 타임스텝을 예상하도록 정의됩니다. 그런 다음 전체 CNN 모델이 샘플의 각 시퀀스에 적용될 수 있도록 TimeDistributed 래퍼 레이어로 래핑됩니다. 그런 다음 모델이 예측을 출력하기 전에 LSTM 레이어에서 결과를 해석합니다."
데이터 전처리¶
- [샘플, 타임스텝, 피처]를 [샘플, 시퀀스, 타임스텝, 피처]로 재구성합니다.
subsequences = 2
timesteps = X_train_series.shape[1]//subsequences
X_train_series_sub = X_train_series.reshape((X_train_series.shape[0], subsequences, timesteps, 1))
X_valid_series_sub = X_valid_series.reshape((X_valid_series.shape[0], subsequences, timesteps, 1))
print('Train set shape', X_train_series_sub.shape)
print('Validation set shape', X_valid_series_sub.shape)
Train set shape (100746, 2, 15, 1) Validation set shape (67164, 2, 15, 1)
model_cnn_lstm = Sequential()
model_cnn_lstm.add(TimeDistributed(Conv1D(filters=64, kernel_size=1, activation='relu'), input_shape=(None, X_train_series_sub.shape[2], X_train_series_sub.shape[3])))
model_cnn_lstm.add(TimeDistributed(MaxPooling1D(pool_size=2)))
model_cnn_lstm.add(TimeDistributed(Flatten()))
model_cnn_lstm.add(LSTM(50, activation='relu'))
model_cnn_lstm.add(Dense(1))
model_cnn_lstm.compile(loss='mse', optimizer=adam)
WARNING:absl:There is a known slowdown when using v2.11+ Keras optimizers on M1/M2 Macs. Falling back to the legacy Keras optimizer, i.e., `tf.keras.optimizers.legacy.Adam`.
cnn_lstm_history = model_cnn_lstm.fit(X_train_series_sub,
Y_train,
validation_data=(X_valid_series_sub, Y_valid),
epochs=epochs,
verbose=2)
Epoch 1/40 3149/3149 - 9s - loss: 423.9758 - val_loss: 388.7557 - 9s/epoch - 3ms/step Epoch 2/40 3149/3149 - 9s - loss: 404.4939 - val_loss: 394.2262 - 9s/epoch - 3ms/step Epoch 3/40 3149/3149 - 9s - loss: 400.9376 - val_loss: 404.3313 - 9s/epoch - 3ms/step Epoch 4/40 3149/3149 - 8s - loss: 395.4359 - val_loss: 393.6498 - 8s/epoch - 2ms/step Epoch 5/40 3149/3149 - 8s - loss: 395.1267 - val_loss: 392.9363 - 8s/epoch - 2ms/step Epoch 6/40 3149/3149 - 7s - loss: 391.8293 - val_loss: 380.2869 - 7s/epoch - 2ms/step Epoch 7/40 3149/3149 - 8s - loss: 389.2654 - val_loss: 423.1865 - 8s/epoch - 2ms/step Epoch 8/40 3149/3149 - 8s - loss: 387.0706 - val_loss: 379.3754 - 8s/epoch - 3ms/step Epoch 9/40 3149/3149 - 7s - loss: 384.2307 - val_loss: 384.3167 - 7s/epoch - 2ms/step Epoch 10/40 3149/3149 - 7s - loss: 383.1464 - val_loss: 386.0833 - 7s/epoch - 2ms/step Epoch 11/40 3149/3149 - 7s - loss: 381.5407 - val_loss: 385.8257 - 7s/epoch - 2ms/step Epoch 12/40 3149/3149 - 8s - loss: 379.5307 - val_loss: 374.0330 - 8s/epoch - 3ms/step Epoch 13/40 3149/3149 - 8s - loss: 379.8225 - val_loss: 373.9783 - 8s/epoch - 3ms/step Epoch 14/40 3149/3149 - 8s - loss: 377.9553 - val_loss: 371.0802 - 8s/epoch - 3ms/step Epoch 15/40 3149/3149 - 8s - loss: 375.9122 - val_loss: 372.0158 - 8s/epoch - 2ms/step Epoch 16/40 3149/3149 - 8s - loss: 374.7285 - val_loss: 369.0298 - 8s/epoch - 2ms/step Epoch 17/40 3149/3149 - 9s - loss: 373.9496 - val_loss: 373.5210 - 9s/epoch - 3ms/step Epoch 18/40 3149/3149 - 8s - loss: 371.9259 - val_loss: 366.3802 - 8s/epoch - 3ms/step Epoch 19/40 3149/3149 - 8s - loss: 371.0768 - val_loss: 365.6390 - 8s/epoch - 3ms/step Epoch 20/40 3149/3149 - 8s - loss: 369.1563 - val_loss: 362.7383 - 8s/epoch - 3ms/step Epoch 21/40 3149/3149 - 8s - loss: 367.4380 - val_loss: 361.6700 - 8s/epoch - 3ms/step Epoch 22/40 3149/3149 - 8s - loss: 366.9162 - val_loss: 361.1642 - 8s/epoch - 3ms/step Epoch 23/40 3149/3149 - 8s - loss: 364.5830 - val_loss: 361.8106 - 8s/epoch - 2ms/step Epoch 24/40 3149/3149 - 10s - loss: 362.9964 - val_loss: 360.8484 - 10s/epoch - 3ms/step Epoch 25/40 3149/3149 - 8s - loss: 362.1571 - val_loss: 357.3286 - 8s/epoch - 3ms/step Epoch 26/40 3149/3149 - 8s - loss: 360.8181 - val_loss: 362.7213 - 8s/epoch - 3ms/step Epoch 27/40 3149/3149 - 8s - loss: 359.8800 - val_loss: 354.7077 - 8s/epoch - 2ms/step Epoch 28/40 3149/3149 - 8s - loss: 358.6018 - val_loss: 355.5657 - 8s/epoch - 2ms/step Epoch 29/40 3149/3149 - 7s - loss: 357.9713 - val_loss: 354.9198 - 7s/epoch - 2ms/step Epoch 30/40 3149/3149 - 7s - loss: 356.6038 - val_loss: 365.0621 - 7s/epoch - 2ms/step Epoch 31/40 3149/3149 - 8s - loss: 356.0158 - val_loss: 359.3351 - 8s/epoch - 3ms/step Epoch 32/40 3149/3149 - 9s - loss: 355.1962 - val_loss: 350.3469 - 9s/epoch - 3ms/step Epoch 33/40 3149/3149 - 9s - loss: 354.1322 - val_loss: 351.0125 - 9s/epoch - 3ms/step Epoch 34/40 3149/3149 - 8s - loss: 354.1085 - val_loss: 350.5111 - 8s/epoch - 3ms/step Epoch 35/40 3149/3149 - 7s - loss: 353.3626 - val_loss: 354.5269 - 7s/epoch - 2ms/step Epoch 36/40 3149/3149 - 7s - loss: 352.3337 - val_loss: 350.4304 - 7s/epoch - 2ms/step Epoch 37/40 3149/3149 - 8s - loss: 351.7551 - val_loss: 348.1240 - 8s/epoch - 2ms/step Epoch 38/40 3149/3149 - 8s - loss: 350.9341 - val_loss: 349.1485 - 8s/epoch - 3ms/step Epoch 39/40 3149/3149 - 7s - loss: 350.6075 - val_loss: 348.2231 - 7s/epoch - 2ms/step Epoch 40/40 3149/3149 - 7s - loss: 349.8927 - val_loss: 350.8935 - 7s/epoch - 2ms/step
모델들 비교하기¶
fig, axes = plt.subplots(2, 2, sharex=True, sharey=True,figsize=(22,12))
ax1, ax2 = axes[0]
ax3, ax4 = axes[1]
ax1.plot(mlp_history.history['loss'], label='Train loss')
ax1.plot(mlp_history.history['val_loss'], label='Validation loss')
ax1.legend(loc='best')
ax1.set_title('MLP')
ax1.set_xlabel('Epochs')
ax1.set_ylabel('MSE')
ax2.plot(cnn_history.history['loss'], label='Train loss')
ax2.plot(cnn_history.history['val_loss'], label='Validation loss')
ax2.legend(loc='best')
ax2.set_title('CNN')
ax2.set_xlabel('Epochs')
ax2.set_ylabel('MSE')
ax3.plot(lstm_history.history['loss'], label='Train loss')
ax3.plot(lstm_history.history['val_loss'], label='Validation loss')
ax3.legend(loc='best')
ax3.set_title('LSTM')
ax3.set_xlabel('Epochs')
ax3.set_ylabel('MSE')
ax4.plot(cnn_lstm_history.history['loss'], label='Train loss')
ax4.plot(cnn_lstm_history.history['val_loss'], label='Validation loss')
ax4.legend(loc='best')
ax4.set_title('CNN-LSTM')
ax4.set_xlabel('Epochs')
ax4.set_ylabel('MSE')
plt.show()
훈련 및 검증에 대한 MLP¶
mlp_train_pred = model_mlp.predict(X_train.values)
mlp_valid_pred = model_mlp.predict(X_valid.values)
print('Train rmse:', np.sqrt(mean_squared_error(Y_train, mlp_train_pred)))
print('Validation rmse:', np.sqrt(mean_squared_error(Y_valid, mlp_valid_pred)))
3149/3149 [==============================] - 1s 263us/step 2099/2099 [==============================] - 1s 255us/step Train rmse: 18.336463865310854 Validation rmse: 18.466149413260833
CNN을 통한 훈련 및 검증¶
cnn_train_pred = model_cnn.predict(X_train_series)
cnn_valid_pred = model_cnn.predict(X_valid_series)
print('Train rmse:', np.sqrt(mean_squared_error(Y_train, cnn_train_pred)))
print('Validation rmse:', np.sqrt(mean_squared_error(Y_valid, cnn_valid_pred)))
3149/3149 [==============================] - 1s 425us/step 2099/2099 [==============================] - 1s 450us/step Train rmse: 18.440303147938092 Validation rmse: 18.579907869706126
훈련 및 검증에 사용되는 LSTM¶
lstm_train_pred = model_lstm.predict(X_train_series)
lstm_valid_pred = model_cnn.predict(X_valid_series)
print('Train rmse:', np.sqrt(mean_squared_error(Y_train, lstm_train_pred)))
print('Validation rmse:', np.sqrt(mean_squared_error(Y_valid, lstm_valid_pred)))
3149/3149 [==============================] - 4s 1ms/step 2099/2099 [==============================] - 1s 421us/step Train rmse: 19.319730447059445 Validation rmse: 18.579907869706126
결론¶
여기에서 시계열 문제에 대한 몇 가지 접근 방식, 개발 방법 및 차이점을 볼 수 있으며, 이것은 훌륭한 성능을 갖기위한 것이 아니므로 더 나은 결과를 원한다면 몇 가지 다른 하이퍼 매개 변수, 특히 창 크기와 네트워크 토폴로지를 시도해보고 결과를 알려 주시기 바랍니다.
여기서 몇 가지를 배웠기를 바라며, 피드백을 남겨 주시고 마음에 드는 내용이 있다면 제가 소스로 사용한 글을 꼭 확인하시기 바랍니다.
LSTM을 자동 인코더로 사용하고 시계열을 나타내는 새로운 기능을 만드는 방법을 확인하려면 다른 커널인 딥 러닝 및 LSTM 자동 인코더를 사용한 시계열 예측을 살펴보시기 바랍니다.
출처 : https://www.kaggle.com/code/dimitreoliveira/deep-learning-for-time-series-forecasting
'Data Analytics > Machine learning(ML) study' 카테고리의 다른 글
초보를 위한 뉴스기사 분류 비지도 모델 (kmeans) (1) | 2022.01.02 |
---|---|
보스턴주택가격 데이터 scikit-learn에서 없어진 데이터 (0) | 2022.01.02 |
LightGBM의 early_stopping_rounds 사용하기 (0) | 2022.01.01 |
- Total
- Today
- Yesterday
- ChatModel
- 맥북 몽고DB 실행
- 파이썬
- 파이썬 리스트 연산
- GPT4
- python 스크래핑 기초
- python 크롤러 기초
- Mac MongoDB install
- 보스턴주택가격
- Python
- 맥북 몽고DB 설치
- mac mongodb 설치
- 판매량예측
- wowork
- 위워크후기
- 알바천국 크롤러
- 파이썬 스크래핑
- 위워크서울스퀘어
- gpt3.5
- early_stopping_rounds
- load_boston
- 맥OS 몽고DB 설치
- 알바천국 스크래핑
- 데이터분석
- python crawler
- 형태소분석
- lightgbm early stopping
- 보스턴집가격
- 위워크서울역
- 브랜딩기획
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |