Machine Learning/Tensorflow

Tensorflow 자격증 대비 - 시계열 데이터 분석 (태양의 흑점 조사)

jinmc 2022. 3. 5. 14:36
반응형

다음은 Coursera의 텐서플로우 자격증 코스에서 나온 태양의 흑점 데이터 분석과 딥러닝을 통한 모델 생성 및 prediction입니다.

 

1. 데이터 받기

 

# tensorflow 버전 확인
import tensorflow as tf
print(tf.__version__)

# plot 함수
import numpy as np
import matplotlib.pyplot as plt
def plot_series(time, series, format="-", start=0, end=None):
    plt.plot(time[start:end], series[start:end], format)
    plt.xlabel("Time")
    plt.ylabel("Value")
    plt.grid(True)
    
# csv 파일 받기
!wget --no-check-certificate \
    https://raw.githubusercontent.com/jbrownlee/Datasets/master/daily-min-temperatures.csv \
    -O /tmp/daily-min-temperatures.csv
    
# csv 파일에서 불러온 후 numpy array 에 넣고 plot에 그리기
import csv
time_step = []
temps = []

with open('/tmp/daily-min-temperatures.csv') as csvfile:
  cnt = 0
  csv_reader = csv.reader(csvfile, delimiter=',')
  next(csv_reader)
  for row in csv_reader:
    temps.append(float(row[1]))
    time_step.append(row[0])
    cnt += 1
  
# YOUR CODE HERE. READ TEMPERATURES INTO TEMPS
# HAVE TIME STEPS BE A SIMPLE ARRAY OF 1, 2, 3, 4 etc

series = np.array(temps)
time = np.array(time_step)
plt.figure(figsize=(10, 6))
plot_series(time, series)

 

2. 데이터 쪼개기

 

여기서 expand_dims는 dimension을 늘려주는 함수입니다. 

axis=-1 인자를 넣었기 때문에 마지막 dimension에 들어갑니다. 예를 들어, (28, 28) 이면, (28, 28, 1) 이런 식이 됩니다.

window function은 [1,2,3,4,5] 를 [1,2,3], [2,3,4], [3,4,5] 이런 식으로 나눠주는 function입니다.

drop_remainder를 하지 않으면 마지막 3개가 아닌 인자들이 들어가기 때문에 하지 않았습니다.

flat_map의 경우 batch function과 더불어 5개의 item을 3개, 2개로 나눠주는 역할을 합니다.

shuffle 함수는 말 그대로 섞어주는 역할을 하고,

마지막 map함수는 마지막을 제외한 값들과 마지막 값을 분리해주는 역할을 합니다.

즉, input과 label을 분리해주는 역할을 합니다.

아래 함수에서 w[1:]은 값이 두 개이기 때문에 가능한 syntax 입니다.

prefetch같은 경우에는 처음 가져온 후에 다음은 준비하는 performance에 영향을 주는 function이라고 합니다.

 

def windowed_dataset(series, window_size, batch_size, shuffle_buffer):
  series = tf.expand_dims(series, axis=-1)
  ds = tf.data.Dataset.from_tensor_slices(series)
  ds = ds.window(window_size + 1, shift=1, drop_remainder=True)
  ds = ds.flat_map(lambda w: w.batch(window_size))
  ds = ds.shuffle(shuffle_buffer)
  ds = ds.map(lambda w: (w[:-1], w[1:]))
  return ds.batch(batch_size).prefetch(1)

즉, 이 함수의 목적은 training, validating하는 데이터를 만드는 겁니다.

 

 

3. 모델이 주어졌을때 predict하는 function 만들기

 

전 함수랑 비슷하지만, label이 없기 때문에, expand_dims를 하지 않아도 되고, 

batch size를 32로 했습니다.

def model_forecast(model, series, window_size):
    # YOUR CODE HERE
    ds = tf.data.Dataset.from_tensor_slices(series)
    ds = ds.window(window_size, shift=1, drop_remainder=True)
    ds = ds.flat_map(lambda w: w.batch(window_size))
    ds = ds.batch(32).prefetch(1)
    forecast = model.predict(ds)
    return forecast

 

4. model Structure 구성 및 parameter들 지정, training set 구성, optimizer setting, mae 설정

 

tf.keras.backend.clear_session()
tf.random.set_seed(51)
np.random.seed(51)
window_size = 64
batch_size = 256
train_set = windowed_dataset(x_train, window_size, batch_size, shuffle_buffer_size)
print(train_set)
print(x_train.shape)

model = tf.keras.models.Sequential([
# YOUR CODE HERE
  tf.keras.layers.Conv1D(filters=32, kernel_size=5,
                      strides=1, padding="causal",
                      activation="relu",
                      input_shape=[None, 1]),
  tf.keras.layers.LSTM(64, return_sequences=True),
  tf.keras.layers.LSTM(64, return_sequences=True),
  tf.keras.layers.Dense(30, activation="relu"),
  tf.keras.layers.Dense(10, activation="relu"),
  tf.keras.layers.Dense(1),
  tf.keras.layers.Lambda(lambda x: x * 400)
])

lr_schedule = tf.keras.callbacks.LearningRateScheduler(
    lambda epoch: 1e-8 * 10**(epoch / 20))
optimizer = tf.keras.optimizers.SGD(learning_rate=1e-8, momentum=0.9)
model.compile(loss=tf.keras.losses.Huber(),
              optimizer=optimizer,
              metrics=["mae"])
history = model.fit(train_set, epochs=100, callbacks=[lr_schedule])

 

5. plot을 그려봅시다

plt.semilogx(history.history["lr"], history.history["loss"])
plt.axis([1e-8, 1e-4, 0, 60])

다음과 같이 나옵니다

 

6. 다른 Model Structure를 구성해서 학습하고 결과를 봅시다

Learning Rate, Epoch도 다르게 주었습니다.

tf.keras.backend.clear_session()
tf.random.set_seed(51)
np.random.seed(51)
train_set = windowed_dataset(x_train, window_size=60, batch_size=100, shuffle_buffer=shuffle_buffer_size)
model = tf.keras.models.Sequential([
# YOUR CODE HERE
  tf.keras.layers.Conv1D(filters=60, kernel_size=5,
                      strides=1, padding="causal",
                      activation="relu",
                      input_shape=[None, 1]),
  tf.keras.layers.LSTM(60, return_sequences=True),
  tf.keras.layers.LSTM(60, return_sequences=True),
  tf.keras.layers.Dense(30, activation="relu"),
  tf.keras.layers.Dense(10, activation="relu"),
  tf.keras.layers.Dense(1),
  tf.keras.layers.Lambda(lambda x: x * 400)
])


optimizer = tf.keras.optimizers.SGD(learning_rate=1e-5, momentum=0.9)# YOUR CODE HERE, momentum=0.9)
model.compile(loss=tf.keras.losses.Huber(),
              optimizer=optimizer,
              metrics=["mae"])
history = model.fit(train_set, epochs=150, callbacks=[lr_schedule])

7. 결과를 봅시다

 

rnn_forecast = model_forecast(model, series[..., np.newaxis], window_size)
rnn_forecast = rnn_forecast[split_time - window_size:-1, -1, 0]

 

plt.figure(figsize=(10, 6))
plot_series(time_valid, x_valid)
plot_series(time_valid, rnn_forecast)

MAE도 봅시다

tf.keras.metrics.mean_absolute_error(x_valid, rnn_forecast).numpy()
print(rnn_forecast)

 

 

ref : (https://teddylee777.github.io/tensorflow/dataset-batch-window

반응형