일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- time wait port kill
- conda base 기본 설정
- conda base 활성화
- 실행중인 포트 죽이기
- 려려
- 티스토리챌린지
- 오블완
- 3000 port kill
- window netstat time wait 제거
- conda 가상환경 설정 오류
- conda 기초 설정
- Today
- Total
모도리는 공부중
21.03.11. 딥러닝 - 시계열 RNN 본문
21.03.11. 딥러닝 - 시계열 RNN
공부하는 모도리 2021. 3. 11. 18:09저번시간 숙제
1. 시퀀스 길이 맞추기
2. 모델링
- LSTM
- Dropout
- Embedding
선생님 풀이 갑니다.
..... 잘.. 자버렸다.. ;;;;;
에너지 데이터 예측하기(시계열, RNN)
시간 흐름에 따라 발생하는 에너지 데이터를 예측해보자.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
data = pd.read_csv('data/energy.csv')
data.head()
data.tail()
data.shape
out : (26304, 3)
2만 6천개의 데이터가 있음을 확인 완료.
시계열 데이터 파싱
# parse_dates : timestamp열을 그냥 글자 타입에서 date 날짜 타입으로 변경
# index_col : 특정 열을 인덱스로 지정
energy = pd.read_csv('data/energy.csv',
parse_dates=['timestamp'],
index_col='timestamp')
energy.info()
energy.head()
1. load 데이터를 이용해서 다음 1시간의 load 데이터를 예측해보자.
del energy['temp'] # 온도 데이터 삭제
# 어떤 패턴을 가지고 있는지 시각화 - matplotlib 사용
plt.figure(figsize=(10,5)) # 가로, 세로
plt.plot(energy)
plt.show()
여름과 겨울에 패턴이 주기적으로 올라갔다 내려가는 모습을 보이고 있다.
RNN을 통해 학습해나가는 모델링을 진행하자.
- 데이터 스케일링
- 데이터 셋 분리 (train, validation, test)
- RNN 학습을 위한 데이터 shape으로 변경 (samples, time steps, features)
데이터셋을 분리할 때 사진은 무작위 샘플링을 진행한다. 하지만 시간은 무작위로 진행해버리면 시간의 흐름이 망가지게 되므로 시계열데이터를 다룰 때는 데이터셋 분리를 뚝뚝 끊어내는 방식으로 진행을 한다.
MinMax 스케일링
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
energy.head()
# 현재 scaler에는 load 자료밖에 없다.
energy['load'] = scaler.fit_transform(energy)
# 원래 무슨값이었든간에 1과 0 사이값을 찾아서 단위를 바꿔버리는 작업 진행
energy
# 최적화된 값 확인
데이터 셋을 RNN을 위한 형태로 변경
- 데이터셋 분리 전에 RNN학습을 위한 shape로 변경을 먼저 진행한다.
- 중복되는 코드를 여러번 입력하는 과정을 단축시키기 위한 순서 변경
energy_shifted = energy.copy()
energy_shifted
# 다음 한 시간 예측을 위해 정답 데이터를 먼저 추가
# shift() : load 데이터를 한 칸씩 위로(-1) 밀어낸다.
# - 위는 -, 아래는 +.
# - 시간 단위이므로 freq='H'
energy_shifted['y_t+1'] = energy_shifted['load'].shift(-1, freq='H')
energy_shifted
과거 사용량을 보며 몇 번이나 쓰게 할건지 작업한다. 예를 들어 과거 10시간을 토대로 예측하게 할 수 있다. 지금 우리는 과거 5시간을 토대로 예측하는 시스템을 만든다.
energy_shifted['load_t-5'] = energy_shifted['load'].shift(5, freq='H')
energy_shifted
과거 5번의 데이터는 없으므로 load_t-5의 0~4행은 NaN으로 비어있다.
energy_shifted['load_t-4'] = energy_shifted['load'].shift(4, freq='H')
energy_shifted['load_t-3'] = energy_shifted['load'].shift(3, freq='H')
energy_shifted['load_t-2'] = energy_shifted['load'].shift(2, freq='H')
energy_shifted['load_t-1'] = energy_shifted['load'].shift(1, freq='H')
energy_shifted['load_t-0'] = energy_shifted['load'].shift(0, freq='H') # 0은 현재를 의미
energy_shifted
2012-01-01 00:00:00 ~ 2012-01-01 04:00:00 의 시간은 NaN 데이터가 있어서 활용할 수 없으므로 데이터를 지워준다.
energy_shifted.dropna(inplace=True)
print(energy_shifted.shape)
energy_shifted
out :
데이터 셋 분리
- 그림에 없는 부분은 전부 train으로 사용한다.
# 이제 데이터 셋 분리를 위한 날짜를 지정한다.
validation_start = '2014-09-01 00:00:00'
test_start = '2014-11-01 00:00:00'
# 날짜로 파싱했으므로 날짜 연산은 충분히 가능하다.
train = energy_shifted[energy_shifted.index < validation_start] # val보다 큰 경우
val = energy_shifted[(energy_shifted.index >= validation_start) &
(energy_shifted.index < test_start)]
test = energy_shifted[energy_shifted.index >= test_start] # test보다 작은 경우
train.shape, val.shape, test.shape
out : ((23371, 8), (1464, 8), (1463, 8))
plt.figure(figsize=(10,5))
plt.plot(train['load'])
plt.plot(val['load'])
plt.plot(test['load'])
plt.show()
# 문제와 답
# train.loc[행, 열]
# - loc 없이 하면 컬럼만 색인
X_train = train.loc[:, 'load_t-5':'load_t-0']
y_train = train['y_t+1']
X_val = val.loc[:, 'load_t-5':'load_t-0']
y_val = val['y_t+1']
X_test = test.loc[:, 'load_t-5':'load_t-0']
y_test = test['y_t+1']
print(X_train.shape, y_train.shape)
print(X_val.shape, y_val.shape)
print(X_test.shape, y_test.shape)
out :
(23371, 6) (23372,)
(1464, 6) (1464,)
(1463, 6) (1463,)
feature값은 1이며 현재 생략되어 있다. 이 생략된 feature값을 reshape를 통해 나타낸다.
# 이 셀을 두 번 실행시키면 values가 없다고 뜬다. 그럴 때는 위부터 다시 실행하고 와라.
X_train = X_train.values.reshape(23371,6,1)
X_val = X_val.values.reshape(1464,6,1)
X_test = X_test.values.reshape(1463,6,1)
모델링 진행
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, GRU
# LSTM은 내부 연산이 많이 들어간다.
# RNN계열의 GRU를 이용해보자.
model = Sequential()
# time_steps는 과거 6개의 데이터를 토대로 미래를 맞춘다.
# features는 에너지 사용량 하나만 쓰므로 1개이다.
model.add(GRU(32, input_shape=(6, 1)))
model.add(Dense(1))
model.compile(loss='mse', optimizer='Adam')
history = model.fit(X_train, y_train, validation_data=(X_val, y_val), epochs=20)
Train on 23371 samples, validate on 1464 samples Epoch 1/20 23371/23371 [==============================] - 2s 75us/sample - loss: 0.0014 - val_loss: 9.5257e-04 Epoch 2/20 23371/23371 [==============================] - 2s 75us/sample - loss: 9.6280e-04 - val_loss: 7.4761e-04 Epoch 3/20 23371/23371 [==============================] - 2s 80us/sample - loss: 7.4246e-04 - val_loss: 5.4264e-04 Epoch 4/20 23371/23371 [==============================] - 2s 72us/sample - loss: 6.1394e-04 - val_loss: 5.0589e-04 Epoch 5/20 23371/23371 [==============================] - 2s 72us/sample - loss: 5.8653e-04 - val_loss: 5.0239e-04 Epoch 6/20 23371/23371 [==============================] - 2s 82us/sample - loss: 5.7243e-04 - val_loss: 5.7241e-04 Epoch 7/20 23371/23371 [==============================] - 2s 77us/sample - loss: 5.7133e-04 - val_loss: 5.5243e-04 Epoch 8/20 23371/23371 [==============================] - 2s 72us/sample - loss: 5.7570e-04 - val_loss: 5.3266e-04 Epoch 9/20 23371/23371 [==============================] - 2s 78us/sample - loss: 5.6388e-04 - val_loss: 4.9545e-04 Epoch 10/20 23371/23371 [==============================] - 2s 74us/sample - loss: 5.6693e-04 - val_loss: 5.4547e-04 Epoch 11/20 23371/23371 [==============================] - 2s 74us/sample - loss: 5.5968e-04 - val_loss: 4.9566e-04 Epoch 12/20 23371/23371 [==============================] - 2s 74us/sample - loss: 5.5062e-04 - val_loss: 4.8851e-04 Epoch 13/20 23371/23371 [==============================] - 2s 82us/sample - loss: 5.5253e-04 - val_loss: 4.8189e-04 Epoch 14/20 23371/23371 [==============================] - 2s 76us/sample - loss: 5.3797e-04 - val_loss: 4.7079e-04 Epoch 15/20 23371/23371 [==============================] - 2s 79us/sample - loss: 5.3923e-04 - val_loss: 4.6248e-04 Epoch 16/20 23371/23371 [==============================] - 2s 78us/sample - loss: 5.2006e-04 - val_loss: 4.6022e-04 Epoch 17/20 23371/23371 [==============================] - 2s 79us/sample - loss: 5.1791e-04 - val_loss: 4.3717e-04 Epoch 18/20 23371/23371 [==============================] - 2s 79us/sample - loss: 5.0288e-04 - val_loss: 4.1597e-04 Epoch 19/20 23371/23371 [==============================] - 2s 86us/sample - loss: 4.8905e-04 - val_loss: 3.9519e-04 Epoch 20/20 23371/23371 [==============================] - 2s 78us/sample - loss: 4.8019e-04 - val_loss: 3.7490e-04 |
plt.figure(figsize=(15,5))
plt.plot(history.history['loss'], label=['loss'])
plt.plot(history.history['val_loss'], label=['val_loss'])
plt.legend()
plt.show()
결과 시각화
result = test[['y_t+1']]
result
# 모델이 예측한 결과를 컬럼으로 새로 추가한다
result['predict'] = model.predict(X_test)
result
# scaler 적용 전 원래 단위로 변경
inverse_result = scaler.inverse_transform(result)
inverse_result
# val값과 test값이 얼마나 비슷하게 그려지는지 확인
plt.figure(figsize=(30,5))
plt.plot(inverse_result[:,0], label='actual')
plt.plot(inverse_result[:,1], label='predict')
plt.legend()
plt.show()
2. 과거 load와 temp를 활용해 다음 한 시간의 load를 예측해보자.
- 온도와 사용량을 같이 고려하며 예측하는 모델링
energy = pd.read_csv('data/energy.csv',
parse_dates=['timestamp'],
index_col=['timestamp'])
energy.head()
데이터 스케일링
load_scaler = MinMaxScaler()
temp_scaler = MinMaxScaler()
energy['load'] = load_scaler.fit_transform(energy[['load']])
energy['temp'] = temp_scaler.fit_transform(energy[['temp']])
energy.head()
energy_shifted = energy.copy()
energy_shifted['y_t+1'] = energy_shifted['load'].shift(-1, freq='H')
energy_shifted
# 과거 6개의 시간을 shift
energy_shifted['load_t-5'] = energy_shifted['load'].shift(5, freq='H')
energy_shifted['temp_t-5'] = energy_shifted['temp'].shift(5, freq='H')
energy_shifted['load_t-4'] = energy_shifted['load'].shift(4, freq='H')
energy_shifted['temp_t-4'] = energy_shifted['temp'].shift(4, freq='H')
energy_shifted['load_t-3'] = energy_shifted['load'].shift(3, freq='H')
energy_shifted['temp_t-3'] = energy_shifted['temp'].shift(3, freq='H')
energy_shifted['load_t-2'] = energy_shifted['load'].shift(2, freq='H')
energy_shifted['temp_t-2'] = energy_shifted['temp'].shift(2, freq='H')
energy_shifted['load_t-1'] = energy_shifted['load'].shift(1, freq='H')
energy_shifted['temp_t-1'] = energy_shifted['temp'].shift(1, freq='H')
energy_shifted['load_t-0'] = energy_shifted['load'].shift(0, freq='H')
energy_shifted['temp_t-0'] = energy_shifted['temp'].shift(0, freq='H')
energy_shifted
energy_shifted.dropna(inplace=True)
데이터셋 나누기
train = energy_shifted[energy_shifted.index < validation_start] # val보다 큰 경우
val = energy_shifted[(energy_shifted.index >= validation_start) &
(energy_shifted.index < test_start)]
test = energy_shifted[energy_shifted.index >= test_start] # test보다 작은 경우
train.shape, val.shape, test.shape
out : ((23371, 15), (1464, 15), (1463, 15))
# 문제와 답
# train.loc[행, 열]
# - loc 없이 하면 컬럼만 색인
X_train = train.loc[:, 'load_t-5':'temp_t-0']
y_train = train['y_t+1']
X_val = val.loc[:, 'load_t-5':'temp_t-0']
y_val = val['y_t+1']
X_test = test.loc[:, 'load_t-5':'temp_t-0']
y_test = test['y_t+1']
# 총 6번의 순환 동안 2개씩 입력이 들어가야 한다.
X_train = X_train.values.reshape(23371,6,2)
X_val = X_val.values.reshape(1464,6,2)
X_test = X_test.values.reshape(1463,6,2)
모델링 및 시각화
..........하하...
'K-디지털 빅데이터 분석서비스 개발자과정 20.11.02~21.04.12 > PYTHON(웹크롤링, 머신·딥러닝)' 카테고리의 다른 글
21.03.09. 딥러닝 - RNN, LSTM, 단어 임베딩 (0) | 2021.03.09 |
---|---|
21.03.08. 딥러닝 - RNN 단어 철자 예측 및 뉴스기사 데이터 실습 (0) | 2021.03.08 |
21.03.05. 딥러닝 - 동물 이미지 인식, 패션 이미지 분류 (0) | 2021.03.05 |
21.03.04. 딥러닝 - (0) | 2021.03.04 |
21.03.03. 딥러닝 - 숫자손글씨 인식 마지막, 개고양이 인식 (1) | 2021.03.03 |