# sin 곡선 예측 LSTM 모델
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Dense, LSTM
# time step만큼 시퀀스 데이터 분리
def split_sequence(sequence, step):
x, y = list(), list()
for i in range(len(sequence)):
end_idx = i + step
if end_idx > len(sequence) - 1:
break
seq_x, seq_y = sequence[i:end_idx], sequence[end_idx]
x.append(seq_x)
y.append(seq_y)
return np.array(x), np.array(y)
# sin 함수 학습 데이터
x = [i for i in np.arange(start=-10, stop=10, step=0.1)]
train_y = [np.sin(i) for i in x]
# 하이퍼파라미터
n_timesteps = 15
n_features = 1
# 시퀀스 나누기
# train_x.shape => (samples, timesteps)
# train_y.shape => (samples)
train_x, train_y = split_sequence(train_y, step=n_timesteps)
print("shape x:{} / y:{}".format(train_x.shape, train_y.shape))
# LSTM 입력 벡터 크기를 맞추기 위해 벡터 차원 크기 변경
# reshape from [samples, timesteps] into [samples, timesteps, features]
train_x = train_x.reshape(train_x.shape[0], train_x.shape[1], n_features)
print("train_x.shape = {}".format(train_x.shape))
print("train_y.shape = {}".format(train_y.shape))
# LSTM 모델 정의
model = Sequential()
# units : 전체 뉴런 수
model.add(LSTM(units=10, return_sequences=False, input_shape=(n_timesteps, n_features)))
model.add(Dense(1))
model.summary()
model.compile(optimizer='adam', loss='mse')
# 모델 학습
np.random.seed(0)
from tensorflow.keras.callbacks import EarlyStopping
early_stopping = EarlyStopping(monitor='loss', patience=5, mode='auto')
history = model.fit(train_x, train_y, epochs=1000, callbacks=[early_stopping])
# loss 그래프 생성
plt.plot(history.history['loss'], label="loss")
plt.legend(loc="upper right")
plt.show()
# 테스트 데이터셋 생성
test_x = np.arange(10, 20, 0.1)
calc_y = np.cos(test_x) # 테스트 정답 데이터
# LSTM 모델 예측 및 로그 저장
# test_y 리스트에 순자적으로 저장
test_y = calc_y[:n_timesteps]
for i in range(len(test_x) - n_timesteps):
net_input = test_y[i : i + n_timesteps]
net_input = net_input.reshape((1, n_timesteps, n_features))
train_y = model.predict(net_input, verbose=0)
print(test_y.shape, train_y.shape, i, i + n_timesteps)
test_y = np.append(test_y, train_y)
# 예측 결과 그래프 그리기
plt.plot(test_x, calc_y, label="ground truth", color="orange")
plt.plot(test_x, test_y, label="predicitons", color="blue")
plt.legend(loc='upper left')
plt.ylim(-2, 2)
plt.show()