2주차
window 사이즈 만한 값들을 input x, 그 다음 값을 label y로 세팅
- 위 예시에서는 30 features
<데이터 생성하기>
dataset = tf.data.Dataset.range(10)
for val in dataset:
print(val.numpy())
windowing 해보기
dataset = tf.data.Dataset.range(10)
dataset = dataset.window(5, shift=1)
for window_dataset in dataset:
for val in window_dataset:
print(val.numpy(), end=" ")
print()
- window 사이즈, 그리고 매번 얼마나 shift할지
dataset = tf.data.Dataset.range(10)
dataset = dataset.window(5, shift=1, drop_remainder=True)
for window_dataset in dataset:
for val in window_dataset:
print(val.numpy(), end=" ")
print()
drop_remainder 설정하면
위 데이터를 numpy list로 넣어보자
dataset = tf.data.Dataset.range(10)
dataset = dataset.window(5, shift=1, drop_remainder=True)
dataset = dataset.flat_map(lambda window: window.batch(5))
for window in dataset:
print(window.numpy())
split dataset + shuffle + batch
dataset = tf.data.Dataset.range(10)
dataset = dataset.window(5, shift=1, drop_remainder=True)
dataset = dataset.flat_map(lambda window: window.batch(5))
dataset = dataset.map(lambda window: (window[:-1], window[-1]))
dataset = datset.shuffle(buffer_size=10)
dataset = dataset.batch(2).prefetch(1)
for x, y in dataset:
print("x = ", x.numpy())
print("y = ", y.numpy())
아이템이 두개 씩 든 세 개의 배치 생성됨
위처럼 생성한 데이터를 NN에 넣기
def windowed_dataset(series, window_size, batch_size, shuffle_buffer):
dataset = tf.data.Dataset.from_tensor_slices(series)
dataset = dataset.window(window_size+1, shift=1, drop_remainder=True)
dataset = dataset.flat_map(lambda window: window.batch(window_size+1))
dataset = dataset.shuffle(shuffle_buffer).map(lambda window: (window[:-1], window[-1]))
datawet = dataset.batch(batch_size).prefetch(1)
return dataset
split dataset for simple linear regression
split_time = 1000
time_train = time[:split_time]
x_train = series[:split_time]
time_valid = time[split_time:]
x_valid = series[split_time:]
window_size = 20
batch_size = 32
shuffle_buffer_size = 1000
dataset = windowed_dataset(series, window_size, batch_size, shuffle_buffer_size)
l0 = tf.keras.layers.Dense(1, input_shape=[window_size])
model = tf.keras.models.Sequential([l0])
model.compile(loss='mse', optimizer=tf.keras.optimizers.SGD(learning_rate=1e-6, momentum=0.9))
model.fit(dataset, epochs=100, verbose=0)
학습 후 weight 를 확인해보면
print("Layer weights {}".format(l0.get_weights()))
모든 point에 대해서 prediction한다고 하면
forecast = []
for time in range(len(series) - window_size):
forecast.append(model.predict(series[time:time + window_size][np.newaxis]))
forecast = forecast[split_time - window_size :]
results = np.array(forecast)[:, 0, 0]
tf.keras.metrics.mean_absolute_error(x_valid, results).numpy()
<DNN으로 정확도 높이기>
dataset = windowed_dataset(x_train, window_size, batch_size, shuffle_buffer_size)
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(10, input_shape=[window_shape], activation='relu'),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1)
])
model.compile(loss='mse', optimizer=tf.keras.optimizers.SGD(learning_rate=1e-6, momentum=0.9))
model.fit(dataset, epochs=100, verbose=0)
<learning rate scheduler 추가>
dataset = windowed_dataset(x_train, window_size, batch_size, shuffle_buffer_size)
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(10, input_shape=[window_shape], activation='relu'),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1)
])
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='mse', optimizer=optimizer)
history = model.fit(dataset, epochs=100, callbacks=[lr_schedule])
- 각 epoch가 끝날 때마다 호출되는 기능
- epoch 수에 따라 learning rate 를 수정
<시각화하기> - learning rate와 loss
lrs = 1e-8 * (10**(np.arange(100)/20))
plt.semilogx(lrs, history.history['loss'])
x : learning rate / y : epoch
위 그래프에서 안정적이었던 구간 선택 --> 7e - 6
dataset = windowed_dataset(x_train, window_size, batch_size, shuffle_buffer_size)
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(10, input_shape=[window_shape], activation='relu'),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1)
])
model.compile(loss='mse', optimizer=tf.keras.optimizers.SGD(learning_rate=7e-6, momentum=0.9))
model.fit(dataset, epochs=500, verbose=0)
3주차
RNN
inputs are 3-dimensional
window size : 30 time stpes
batch size : 4
--> shape : 4 x 30 x 1
memory cell 의 각 input shape : 4 x 1
만약 memory cell 이 3개 unit 으로 구성되어 있다면
각 output shape : 4 x 3
--> 전체 output shape : 4 x 30 x 3
- 4 : batch size
- 30 : time steps
- 3 : units
만약 output으로 각 batch에 대한 single 값 -> 하나의 vector 를 받고 싶다면? (seq2vec RNN)
-> 다른 output sequence 무시하고 마지막 output만 받아오면 됨
- keras에서 이것은 default behaviour 이므로, 만약 sequence output을 받고 싶다면 return_sequences=True 세팅
- 다른 레이어 위에 RNN 쌓을 때 return_sequence 세팅해야 함
model = keras.models.Sequential([
keras.layers.SimpleRNN(20, return_sequences=True, input_shape=[None, 1]),
keras.layers.SimpleRNN(20),
keras.layers.Dense(1)
])
- 첫번째 RNN은 sequence를 output으로 다음 레이어에 전달함
- input_shape = [None, 1]
- tensorflow에서 첫번째는 batch size - 어떤 사이즈가 될 수 있으므로 define할 필요 없음
- 다음 차원은 the number of time steps - 어떤 길이의 sequence든 RNN이 받을 수 있으므로 None으로 설정
- 마지막 차원은 1 - because we are using a univariate time series
model = keras.models.Sequential([
keras.layers.SimpleRNN(20, return_sequences=True, input_shape=[None, 1]),
keras.layers.SimpleRNN(20, return_sequences=True),
keras.layers.Dense(1)
])
만약 둘다 return_sequence 세팅하면?
그 다음 Dense layer는 sequence를 입력받게 됨
(동일한 dense layer가 time step마다 재사용되고 있는 것임)
<lambda layer 사용하기>
model = keras.models.Sequential([
keras.layers.Lamdba(lambda x: tf.expand_dims(x, axis=-1), input_shape=[None])
keras.layers.SimpleRNN(20, return_sequences=True),
keras.layers.SimpleRNN(20),
keras.layers.Dense(1)
keras.layers.Lambda(lambda x: x * 100.0)
])
- 첫번째 lamdba layer
- windowed_dataset 함수가 출력하는 것은 batch size x time steps 의 2차원 데이터
- 하지만 RNN은 3차원 입력을 기대한다 (세번째 차원 series dimensionality)
- lambda 레이어를 써서, array 를 한 차원 더 늘려준다
- input_shape = [None] : 어떤 길이의 시퀀스라도 받을 수 있음
- 두번째 lambda layer
- output을 100배 scale up
- RNN에서 사용하는 기본 activation은 tanh함수(-1~1)를 사용하므로
train_set = windowed_dataset(x_train, window_size, batch_size=128, shuffle_buffer=shuffle_buffer_size)
model = tf.keras.models.Sequential([
tf.keras.layers.Lambda(lamdba x: tf.expand_dims(x, axis=-1), input_shape=[None]),
tf.keras.layers.SimpleRNN(40, return_sequences=True),
tf.keras.layers.SimpleRNN(40),
tf.keras.layers.Dense(1),
tf.keras.layers.Lambda(lamdba x: x * 100.0)
])
lr_schedule = tf.keras.callbacks.LearningRateScheduler(lamdba 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])
*Huber loss : outlier에 덜 민감
100 epoch 정도 돌려보았을 때 최적의 learning rate 찾을 수 있음
optimizer = tf.keras.optimizers.SGD(learning_rate=5e-6, momentum=0.9)
model.compile(loss=tf.keras.losses.Huber(),
optimizer=optimizer,
metrics=['mae'])
history = model.fit(train_set, epochs=100)
epoch 400 이하로 훈련시키는 것이 좋음
<LSTM>
LSTM 은 cell state를 추가해서 학습하는 동안 state 유지
tf.keras.backend.clear_session()
dataset = windowed_dataset(x_train, window_size, batch_size, shuffle_buffer_size)
model = tf.keras.models.Sequential([
tf.keras.layers.Lambda(lambda x: tf.expand_dim(x, axis=-1), input_shape=[None]),
tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32, return_sequences=True)),
tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32)),
tf.keras.layers.Dense(1),
tf.keras.layers.Lambda(lambda x: x * 100.0)
])
model.compile(loss='mse', optimizer=tf.keras.optimizers.SGD(learning_rate=1e-6, momentum=0.9))
model.fit(dataset, epochs=100, verbose=0)
- tf.keras.backend.clear_session() : internal variables 클리어
과제
def create_uncompiled_model():
### START CODE HERE
model = tf.keras.models.Sequential([
tf.keras.layers.Lambda(lambda x: tf.expand_dims(x, axis=-1), input_shape=[None]),
tf.keras.layers.SimpleRNN(40, return_sequences=True),
tf.keras.layers.SimpleRNN(40),
tf.keras.layers.Dense(1),
tf.keras.layers.Lambda(lambda x : x * 100.0)
])
### END CODE HERE
return model
# Test your uncompiled model
uncompiled_model = create_uncompiled_model()
try:
uncompiled_model.predict(dataset)
except:
print("Your current architecture is incompatible with the windowed dataset, try adjusting it.")
else:
print("Your current architecture is compatible with the windowed dataset! :)")
def adjust_learning_rate():
model = create_uncompiled_model()
lr_schedule = tf.keras.callbacks.LearningRateScheduler(lambda epoch: 1e-6 * 10**(epoch / 20))
### START CODE HERE
# Select your optimizer
optimizer = tf.keras.optimizers.SGD(learning_rate=1e-6, momentum=0.9)
# Compile the model passing in the appropriate loss
model.compile(loss=tf.keras.losses.Huber(),
optimizer=optimizer,
metrics=["mae"])
### END CODE HERE
history = model.fit(dataset, epochs=100, callbacks=[lr_schedule])
return history
lr_history = adjust_learning_rate()
# Plot the loss for every LR
plt.semilogx(lr_history.history["lr"], lr_history.history["loss"])
plt.axis([1e-6, 1, 0, 30])
def create_model():
tf.random.set_seed(51)
model = create_uncompiled_model()
### START CODE HERE
model.compile(loss=tf.keras.losses.Huber(),
optimizer=tf.keras.optimizers.SGD(learning_rate=5e-6, momentum=0.9),
metrics=["mae"])
### END CODE HERE
return model
# Save an instance of the model
model = create_model()
# Train it
history = model.fit(dataset, epochs=50)
4주차
model = tf.keras.models.Sequential([
tf.keras.layers.Conv1D(filters=32,
kernel_size=5,
strides=1,
padding='casual',
activation='relu',
input_shape=[None, 1]),
tf.keras.layers.LSTM(32, return_sequences=True),
tf.keras.layers.LSTM(32),
tf.keras.layers.Dense(1),
tf.keras.layers.Lambda(lamdba x : x*200)
])
optimizer = tf.keras.optimizers.SGD(learning_rate=1e-5, momentum=0.9)
model.compile(loss=tf.keras.losses.Huber(),
optimizer=optimizer,
metrics=['mae'])
model.fit(dataset, epochs=500)
- LSTM에 입력될 데이터의 차원을 바꿔주던 lambda 레이어 대신에 Conv1D
- input_shape = [None, 1] : input_shape specify 하고 있음
조금 더 오래 학습해보거나, Bidirectional LSTM 으로 수정해보기
model = tf.keras.models.Sequential([
tf.keras.layers.Conv1D(filters=32,
kernel_size=5,
strides=1,
padding='casual',
activation='relu',
input_shape=[None, 1]),
tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32, return_sequences=True)),
tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32)),
tf.keras.layers.Dense(1),
tf.keras.layers.Lambda(lamdba x : x*200)
])
작은 batch들이 가져오는 randomness 때문에 noise 발생하는 문제 -> 다양한 batch size로 실험해볼 수 있음
<real-world 데이터 적용해보기>
import csv
time_step = []
sunspots = []
with open('/tmp/sunspots.csv') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
next(reader) # column title
for row in reader:
sunspots.append(float(row[2]))
time_step.append(int(row[0]))
series = np.array(sunspots)
time = np.array(time_step)
trend 없고, noise 살짝 있고, seasonality 있음
split_time = 1000
time_train = time[:split_time]
x_train = series[:split_time]
time_valid = time[split_time:]
x_valid = series[split_time:]
window_size = 20
batch_size =32
shuffle_buffer_size = 1000
def windowed_dataset(series, window_size, batch_size, shuffle_buffer):
dataset = tf.data.Dataset.from_tensor_slices(series)
dataset = dataset.window(window_size + 1, shift=1, drop_remainder=True),
dataset = dataset.flat_map(lamda window: window.batch(window_size+1))
dataset = dataset.shuffle(shuffle_buffer).map(lambda window: (window[:-1], window[-1]))
dataset = dataset.batch(batch_size).prefetch(1)
return dataset
먼저 DNN
dataset = windowed_dataset(x_train, window_size, batch_size, shuffle_buffer_size)
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(10, input_shape=[window_size], activation='relu'),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1)
])
model.compile(loss='mse', optimizer=tf.keras.optimizers.SGD(learning_rate=1e-6, momentum=0.9))
model.fit(dataset, epochs=100, verbose=0)
- window size가 문제는 아닐까?
지금은 20으로 셋팅되어 있는데, 20 time step 이면 위 데이터 기준으로 2년 좀 안 되는 주기.
하지만 위 데이터의 seasonality를 생각해보면 (약 11년 주기)... 그러니까 132로 설정해보면 어떨까?
--> mae 더 안 좋아짐. 왜? window 안에 full season이 필요한 것은 아님.
한 30정도로만 높이기
- split_time = 1000 이므로 고작 1000개 데이터로 학습시키고 있음
3000으로 늘리기
개선된 모습
- 신경망 아키텍처를 수정해보는 건 어떨까? learning rate는?
prediction
model.predict(series[3205:3235][np.newaxis])
마지막 30 time step을 input으로 넘겨줌
가장 예측 잘 나온 구조 및 하이퍼파라미터
split_time = 3000
window_size = 60
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(20, input_shape=[window_size], activation='relu'),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1)
])
model.compile(loss='mse', optimizer=tf.keras.optimizers.SGD(lr=1e-7, momentum=0.9))
아는 거 다 갖다 써볼까?
window_size = 60
batch_size = 64
train_set = windowed_dataset(x_train, window_size, batch_size, shuffle_buffer_size)
model = tf.keras.models.Sequential([
tf.keras.layers.Conv1D(filters=32,
kernel_size=5,
strides=1,
padding='casual',
activation='relu',
input_shape=[None, 1])
tf.keras.layers.LSTM(32, return_sequences=True),
tf.keras.layers.LSTM(32)
tf.keras.layers.Dense(30, input_shape=[window_size], 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.optimizer.SGD(learning_rate=1e-8, momentum=0.9)
model.compile(loss=tf.keras.losses.Huber(), optimizer=optimizer, metrics=['mse'])
history = model.fit(train_set, epochs = 100, callbacks=[lr_schedule])
-> 최적의 learning rate 1e-5 로 설정하고 epoch 500으로 재학습
튀고 있으므로 batch_size 256으로 증가했을 때 조금 나아지는 모습
데이터 개수가 3000 이니까 딱 맞도록 window size 60, batch size 250, conv1d 필터수 및 LSTM 셀수 60으로 맞춰보는 건?
window_size = 60
batch_size = 250
train_set = windowed_dataset(x_train, window_size, batch_size, shuffle_buffer_size)
model = tf.keras.models.Sequential([
tf.keras.layers.Conv1D(filters=60,
kernel_size=5,
strides=1,
padding='casual',
activation='relu',
input_shape=[None, 1])
tf.keras.layers.LSTM(60, return_sequences=True),
tf.keras.layers.LSTM(60)
tf.keras.layers.Dense(30, input_shape=[window_size], 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.optimizer.SGD(learning_rate=1e-5, momentum=0.9)
model.compile(loss=tf.keras.losses.Huber(), optimizer=optimizer, metrics=['mse'])
history = model.fit(train_set, epochs = 500)
... 이런 식으로 계속 hyperparameter 실험을 해보세요
과제
def create_uncompiled_model():
### START CODE HERE
model = tf.keras.models.Sequential([
tf.keras.layers.Conv1D(32, 5, padding='causal', activation='relu', input_shape=[None, 1]),
tf.keras.layers.LSTM(32, return_sequences=True),
tf.keras.layers.LSTM(32),
tf.keras.layers.Dense(30, input_shape=[64], activation='relu'),
tf.keras.layers.Dense(10, activation='relu'),
tf.keras.layers.Dense(1)
])
### END CODE HERE
return model
'인공지능 > tensorflow certificate' 카테고리의 다른 글
텐서플로우 자격증 취득 후기 (1) | 2022.08.27 |
---|---|
텐서플로우 자격증 시험을 위한 개발환경 구축 및 신청 (0) | 2022.08.23 |
Sequences, Time Series, and Prediction(1) - mathematical method (0) | 2022.08.22 |
Natural Language Processing in TensorFlow(2) (0) | 2022.08.21 |
Natural Language Processing in TensorFlow(1) (0) | 2022.08.21 |