- 독일의 Max Planck Institute for Biogeochemistry에서 관측한 날씨 데이터셋
- 2003년 이후 10분 간격으로 관측된 온도, 대기압, 습도와 같은 14종류의 다양한 관측치를 포함
- 한 시간 동안 6개, 하루에 144개의 관측치를 포함
import tensorflow as tf
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import os
import pandas as pd
mpl.rcParams['figure.figsize'] = (8, 6)
mpl.rcParams['axes.grid'] = False
# 인터넷 상의 orgin에 위치해 있는 파일을 fname 이름으로 다운로드 받는다.
zip_path = tf.keras.utils.get_file(
origin='https://storage.googleapis.com/tensorflow/tf-keras-datasets/jena_climate_2009_2016.csv.zip',
fname='jena_climate_2009_2016.csv.zip',
extract=True)
# splitext: 파일 확장자 분리
csv_path, _ = os.path.splitext(zip_path)
print(csv_path)
TRAIN_SPLIT = 300000
EVALUATION_INTERVAL = 200
EPOCHS = 10
tf.random.set_seed(13)
df = pd.read_csv(csv_path)
print(df.shape)
print(df.head())
print(df.columns)
- 14개의 특성값 중 3개(기압, 온도, 공기 밀도)만 특성값으로 추출
features_considered = ['p (mbar)', 'T (degC)', 'rho (g/m**3)']
features = df[features_considered]
features.index = df['Date Time']
print(features.head())
dataset = features.values
data_mean = dataset[:TRAIN_SPLIT].mean(axis=0)
data_std = dataset[:TRAIN_SPLIT].std(axis=0)
dataset = (dataset-data_mean)/data_std
print(dataset.shape)
print(dataset)
# dataset: 학습 데이터 셋
# target: 종속변수
# start_index: 시작 인덱스
# end_index: 끝 인덱스
# history_size: 과거 데이터의 크기
# target_size: 예측해야 할 레이블의 크기(즉, 얼마 동안의 미래를 예측할지를 의미)
# step: 샘플링 간격
# single_step: 주어진 과거의 자료로부터 하나의 포인트를 예측할지 결정
def multivariate_data(dataset, target, start_index, end_index, history_size, target_size, step, single_step=False):
data = []
labels = []
start_index = start_index + history_size
# end_index를 지정하지 않으면(즉, 데이터셋의 끝까지 추출) end_index는 예측하고자하는 미래 시간만큼을 차감(데이터셋 내에 미래시간이 없기 때문에)
if end_index is None:
end_index = len(dataset) - target_size
for i in range(start_index, end_index):
# ex) 1st data indices: [0,6,12,18,...714, 720] (step값 만큼 추출 데이터 건너 뜀)
indices = range(i - history_size, i, step)
data.append(dataset[indices])
if single_step:
labels.append(target[i+target_size])
else:
labels.append(target[i:i + target_size])
return np.array(data), np.array(labels)
def plot_train_history(history, title):
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(len(loss))
plt.figure()
plt.plot(epochs, loss, 'b', label='Training loss')
plt.plot(epochs, val_loss, 'r', label='Validation loss')
plt.title(title)
plt.legend()
plt.show()
- 주어진 과거의 자료로부터 미래의 단일 지점을 예측
past_history = 720 # 지난 5일간의 데이터 (720 = 5일 * 6개(한시간 관측 개수) * 24시간(하루))
future_target = 72 # 12시간 이 후 온도 예측 (6개*12시간)
STEP = 6 # 60분 내에 기온의 급격한 변화가 예상되지 않으므로 샘플링은 1시간마다 수행
x_train_single, y_train_single = multivariate_data(dataset, dataset[:, 1], 0, TRAIN_SPLIT, past_history, future_target, STEP, single_step=True)
x_val_single, y_val_single = multivariate_data(dataset, dataset[:, 1], TRAIN_SPLIT, None, past_history, future_target, STEP, single_step=True)
# 720개의 과거 데이터를 6단계로 추출하여 120개의 레코드 생성
# 120: 5일 * 24시간
# 3: 3개의 특성
print(x_train_single.shape)
print(y_train_single.shape)
print(f'Single window of past history : {x_train_single[0].shape}')
print(x_train_single[0])
[참고] from_tensor_slices() 함수의 이해 - tf.data는 데이터 입력 파이프 라인 빌드를 위한 텐서플로우의 서브패키지이다. 로컬 파일이나 메모리에 올려져 있는 데이터를 모델에 집어넣기 적합한 텐서로 변환하는 작업을 한다. - from_tensor_slices()는 주어진 텐서들을 첫 번째 차원을 따라 슬라이스한다. - 모든 입력 텐서는 첫번째 차원과 같은 크기를 가져야한다. |
- cache()는 데이터셋을 캐시, 즉 메모리 또는 파일에 보관한다. 따라서 두번째 이터레이션부터는 캐시된 데이터를 사용한다. - shuffle()는 데이터셋을 임의로 섞어준다. BUFFER_SIZE개로 이루어진 버퍼로부터 임의로 샘플을 뽑고, 뽑은 샘플은 다른 샘플로 대체한다. 완벽한 셔플을 위해서 전체 데이터셋의 크기에 비해 크거나 같은 버퍼 크기가 요구된다. - batch()는 데이터셋의 항목들을 하나의 배치로 묶어준다. - 배치 작업이 이루어진 후 데이터의 구성 |
BATCH_SIZE = 256
BUFFER_SIZE = 10000
train_data_single = tf.data.Dataset.from_tensor_slices((x_train_single, y_train_single))
train_data_single = train_data_single.cache().shuffle(BUFFER_SIZE).batch(BATCH_SIZE).repeat()
val_data_single = tf.data.Dataset.from_tensor_slices((x_val_single, y_val_single))
val_data_single = val_data_single.batch(BATCH_SIZE).repeat()
for i in train_data_single:
print(i)
single_step_model = tf.keras.models.Sequential()
# x_train_single.shape: (299280, 120, 3)
single_step_model.add(tf.keras.layers.LSTM(32, input_shape=x_train_single.shape[-2:]))
single_step_model.add(tf.keras.layers.Dense(1))
single_step_model.compile(optimizer=tf.keras.optimizers.RMSprop(), loss='mae')
# (256, 1): Time Step을 만들 때 BATCH_SIZE를 256개로 지정. 즉, 256개의 타임 스텝에 대해 12시간 뒤의 단일 포인트에 대한 예측 값
for x, y in val_data_single.take(1):
print(single_step_model.predict(x).shape)
# 200 단계 훈련, 50 단계 검증, 10회 반복
single_step_history = single_step_model.fit(train_data_single, epochs=EPOCHS, steps_per_epoch=EVALUATION_INTERVAL, validation_data=val_data_single, validation_steps=50)
plot_train_history(single_step_history,
'Single Step Training and Validation Loss')
# 그래프의 x축 좌표 값 생성
def create_time_steps(length):
return list(range(-length, 0))
# plot_data: [5일간 기온 데이터, 12시간 후 기온 데이터, 예측 값]
# delta: 미래 예측 지점
# title: 그래프 제목
def show_plot(plot_data, delta, title):
labels = ['History', 'True Future', 'Model Prediction']
marker = ['.-', 'rx', 'go']
time_steps = create_time_steps(plot_data[0].shape[0])
if delta:
future = delta
else:
future = 0
plt.title(title)
for i, x in enumerate(plot_data):
if i:
plt.plot(future, plot_data[i], marker[i], markersize=10, label=labels[i])
else:
plt.plot(time_steps, plot_data[i].flatten(), marker[i], label=labels[i])
plt.legend()
plt.axis('auto')
plt.xlim([time_steps[0], (future+5)*2])
plt.xlabel('Time-Step')
return plt
# 검증 데이터 중 3개의 데이터를 가져와 256개로 묶인(batch)데이터 중 0번째 타임 스텝 데이의 12시간 후 단일 지점의 예측 값과 실제 값 확인
for x, y in val_data_single.take(3):
plot = show_plot([x[0][:, 1].numpy(), y[0].numpy(),
single_step_model.predict(x)[0]], 12,
'Single Step Prediction')
plot.show()
- 과거 히스토리가 주어지면 미래의 값 범위를 예측
- Multi Step Model은 미래의 시퀀스를 예측한다.
past_history = 720 # 지난 5일간의 데이터 (720 = 5일 * 144개, 144 = 6개 * 24시간)
future_target = 72 # 12시간 이 후 온도 예측 (60분*12)
STEP = 6 # 60분 내에 기온의 급격한 변화가 예상되지 않으므로 샘플링은 1시간마다 수행
x_train_multi, y_train_multi = multivariate_data(dataset, dataset[:, 1], 0, TRAIN_SPLIT, past_history, future_target, STEP)
x_val_multi, y_val_multi = multivariate_data(dataset, dataset[:, 1], TRAIN_SPLIT, None, past_history, future_target, STEP)
# 720개의 과거 데이터를 6단계로 추출하여 120개의 레코드 생성
# 120: 5일 * 24시간
# 3: 3개의 특성
print(x_train_single.shape)
print('Single window of past history : {}'.format(x_train_multi[0].shape))
print('\n Target temperature to predict : {}'.format(y_train_multi[0].shape))
BATCH_SIZE = 256
BUFFER_SIZE = 10000
train_data_multi = tf.data.Dataset.from_tensor_slices((x_train_multi, y_train_multi))
train_data_multi = train_data_multi.cache().shuffle(BUFFER_SIZE).batch(BATCH_SIZE).repeat()
val_data_multi = tf.data.Dataset.from_tensor_slices((x_val_multi, y_val_multi))
val_data_multi = val_data_multi.batch(BATCH_SIZE).repeat()
multi_step_model = tf.keras.models.Sequential()
multi_step_model.add(tf.keras.layers.LSTM(32, return_sequences=True, input_shape=x_train_multi.shape[-2:]))
# 싱글 스텝 예측보다는 복잡하기 때문에 LSTM을 두 개의 층으로 구성
multi_step_model.add(tf.keras.layers.LSTM(16, activation='relu'))
multi_step_model.add(tf.keras.layers.Dense(72))
multi_step_model.compile(optimizer=tf.keras.optimizers.RMSprop(clipvalue=1.0), loss='mae')
# (256, 72): Time Step을 만들 때 BATCH_SIZE를 256개로 지정. 즉, 256개의 타임 스텝에 대해 12시간(6*12) 뒤의 멀티 포인트에 대한 예측 값
for x, y in val_data_multi.take(1):
print(multi_step_model.predict(x).shape)
# 200 단계 훈련, 50 단계 검증, 10회 반복
multi_step_history = multi_step_model.fit(train_data_multi, epochs=EPOCHS, steps_per_epoch=EVALUATION_INTERVAL, validation_data=val_data_multi, validation_steps=50)
plot_train_history(multi_step_history,
'Multi Step Training and Validation Loss')
# 그래프의 x축 좌표 값 생성
def create_time_steps(length):
return list(range(-length, 0))
def multi_step_plot(history, true_future, prediction):
plt.figure(figsize=(12, 6))
num_in = create_time_steps(len(history))
num_out = len(true_future)
# history[:, 1] : 3개의 독립변 수 중 2번째 컬럼이 기온 데이터
plt.plot(num_in, np.array(history[:,1]), label='History')
plt.plot(np.arange(num_out)/STEP, np.array(true_future), 'bo', label='True Future')
if prediction.any():
plt.plot(np.arange(num_out)/STEP, np.array(prediction), 'ro', label='Predicted Future')
plt.legend()
plt.show()
for x, y in val_data_multi.take(3):
multi_step_plot(x[0], y[0], multi_step_model.predict(x)[0])
06. RNN을 이용한 스팸 메일 분류 (0) | 2023.12.28 |
---|---|
04. LSTM을 이용한 항공기 탑승객 수요 예측 (1) | 2023.12.21 |
03. LSTM(Long Short-Term Memory) (0) | 2023.12.21 |
댓글 영역