For this task you will need to train a neural network to predict sunspot activity using the Sunspots.csv provided.
Your neural network is expected to have an MAE of at least 20, with top marks going to one with an MAE of around 15.
At the bottom is provided some testing code should you want to check before uploading which measures the MAE for you.
Strongly recommend you test your model with this to be able to see how it performs.
Sequence(์ํ์ค)
Sunspots.csv๋ฅผ ์ฌ์ฉํ์ฌ ํ์ ํ์ ํ๋(sunspot)์ ์์ธกํ๋ ์ธ๊ณต์ ๊ฒฝ๋ง์ ๋ง๋ญ๋๋ค.
MAE ์ค์ฐจ ๊ธฐ์ค์ผ๋ก ์ต์ 20์ดํ๋ก ์์ธกํ ๊ฒ์ ๊ถ์ฅํ๋ฉฐ, ํ ๋ญํน์ ๋ค๋ ค๋ฉด MAE 15 ๊ทผ์ฒ์ ๋๋ฌํด์ผํฉ๋๋ค.
์๋ ์ฃผ์ด์ง ์ํ์ฝ๋๋ ๋น์ ์ ๋ชจ๋ธ์ ํ ์คํธ ํ๋ ์ฉ๋๋ก ํ์ฉํ ์ ์์ต๋๋ค.
ํ์ํ ๋ชจ๋์ import ํฉ๋๋ค.
import csv
import tensorflow as tf
import numpy as np
import urllib
from tensorflow.keras.layers import Dense, LSTM, Lambda, Conv1D
from tensorflow.keras.models import Sequential
from tensorflow.keras.callbacks import ModelCheckpoint
from tensorflow.keras.optimizers import SGD
from tensorflow.keras.losses import Huber
url = 'https://storage.googleapis.com/download.tensorflow.org/data/Sunspots.csv'
urllib.request.urlretrieve(url, 'sunspots.csv')
csv.reader() ํจ์๋ฅผ ํ์ฉํฉ๋๋ค.
with open('sunspots.csv') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
next(reader)
i = 0
for row in reader:
print(row)
i+=1
if i > 10:
break
๋น list๋ฅผ ๋ง๋ค์ด ์ค๋๋ค. (sunspots, time_step)
sunspots = []
time_step = []
time_step
์๋ index ๊ฐ์, sunspots
์๋ sunspots์ ์ ๋ณด๋ฅผ ๋ฃ์ด ์ค๋๋ค.
with open('sunspots.csv') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
# ์ฒซ ์ค์ header์ด๋ฏ๋ก skip ํฉ๋๋ค.
next(reader)
for row in reader:
sunspots.append(float(row[2]))
time_step.append(int(row[0]))
sunspots์ time_step์ numpy array
๋ก ๋ณํํฉ๋๋ค.
series = np.array(sunspots)
time = np.array(time_step)
series.shape, time.shape
import matplotlib.pyplot as plt
plt.figure(figsize=(16, 8))
plt.plot(time, series)
plt.xlabel("Time")
plt.ylabel("Value")
plt.grid(True)
3000 ์ธ๋ฑ์ค๋ฅผ ๊ธฐ์ค์ผ๋ก Train / Validation Set๋ฅผ ๋ถํ ํฉ๋๋ค.
split_time = 3000
time_train = time[:split_time]
time_valid = time[split_time:]
x_train = series[:split_time]
x_valid = series[split_time:]
# ์๋์ฐ ์ฌ์ด์ฆ
window_size=30
# ๋ฐฐ์น ์ฌ์ด์ฆ
batch_size = 32
# ์
ํ ์ฌ์ด์ฆ
shuffle_size = 1000
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 + 1))
ds = ds.shuffle(shuffle_buffer)
ds = ds.map(lambda w: (w[:-1], w[1:]))
return ds.batch(batch_size).prefetch(1)
train_set
์ validation_set
๋ฅผ ๋ง๋ญ๋๋ค.
train_set = windowed_dataset(x_train,
window_size=window_size,
batch_size=batch_size,
shuffle_buffer=shuffle_size)
validation_set = windowed_dataset(x_valid,
window_size=window_size,
batch_size=batch_size,
shuffle_buffer=shuffle_size)
from IPython.display import Image
Image('https://i.stack.imgur.com/NmYZJ.png')
model = Sequential([
tf.keras.layers.Conv1D(60, kernel_size=5,
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)
])
model.summary()
Optimizer๋ SGD(Stochastic Gradient Descent) ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
optimizer = SGD(lr=1e-5, momentum=0.9)
Huber Loss: MSE์ MAE๋ฅผ ์ ์ถฉํ ํ๋ฒ ์์ค(Huber loss)
loss= Huber()
model.compile()์ ์ฐ๋ฆฌ๊ฐ ํ๋ํ optimizer์ loss๋ฅผ ํ์ฉํฉ๋๋ค.
model.compile(loss=loss,
optimizer=optimizer,
metrics=["mae"])
val_loss
๊ธฐ์ค์ผ๋ก epoch ๋ง๋ค ์ต์ ์ ๋ชจ๋ธ์ ์ ์ฅํ๊ธฐ ์ํ์ฌ, ModelCheckpoint๋ฅผ ๋ง๋ญ๋๋ค.
checkpoint_path
๋ ๋ชจ๋ธ์ด ์ ์ฅ๋ ํ์ผ ๋ช
์ ์ค์ ํฉ๋๋ค.ModelCheckpoint
์ ์ ์ธํ๊ณ , ์ ์ ํ ์ต์
๊ฐ์ ์ง์ ํฉ๋๋ค.checkpoint_path = 'tmp_checkpoint.ckpt'
checkpoint = ModelCheckpoint(checkpoint_path,
save_weights_only=True,
save_best_only=True,
monitor='val_mae',
verbose=1)
epochs=100
history = model.fit(train_set,
validation_data=(validation_set),
epochs=epochs,
callbacks=[checkpoint],
)
ํ์ต์ด ์๋ฃ๋ ํ์๋ ๋ฐ๋์ load_weights
๋ฅผ ํด์ฃผ์ด์ผ ํฉ๋๋ค.
๊ทธ๋ ์ง ์์ผ๋ฉด, ์ด์ฌํ ModelCheckpoint๋ฅผ ๋ง๋ ์๋ฏธ๊ฐ ์์ต๋๋ค.
# checkpoint ๋ฅผ ์ ์ฅํ ํ์ผ๋ช
์ ์
๋ ฅํฉ๋๋ค.
model.load_weights(checkpoint_path)
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 9))
plt.plot(np.arange(1, epochs+1), history.history['loss'])
plt.plot(np.arange(1, epochs+1), history.history['val_loss'])
plt.title('Loss / Val Loss', fontsize=20)
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend(['loss', 'val_loss'], fontsize=15)
plt.show()
plt.figure(figsize=(12, 9))
plt.plot(np.arange(1, epochs+1), history.history['mae'])
plt.plot(np.arange(1, epochs+1), history.history['val_mae'])
plt.title('MAE / Val MAE', fontsize=20)
plt.xlabel('Epochs')
plt.ylabel('MAE')
plt.legend(['mae', 'val_mae'], fontsize=15)
plt.show()