이전까지, fully-connected networks를 만드는 법에 대해서 배웠습니다.
무조건 모든 network의 가중치는 무작위로 설정했고요. 이 상태는 network가 아무 학습도 되지 않은 상태입니다.
이번 시간에는 nerual network를 훈ㄹ녀시키는 방법을 배우게 됩니다.
모든 기계학습 일이 그렇듯, training data부터 시작합니다.
training data 속 각각의 example은 몇가지 features(입력값)과 하나의 예상되는 target(출력값)으로 구성되어 있습니다.
network를 훈련한다는 것은 features를 target으로 변형시키는 방식을 이용해 가중치를 조절하는 것입니다.
80 Cereals dataset으로 'sugar', 'fiber', 'protein'을 이용해 'calories'를 예측했지요.
성공적으로 network를 훈련시키려면, 가중치는, training data에 표현된 것을 바탕으로,
features와 target 사이의 관계를 특정한 방식으로 나타나게 해줍니다.
또한 추가적으로 training data에 2가지가 더 있는데
1. "loss function" - network의 예측 성능 측정함
2. "optimizer" - network가 가중치를 어떻게 변형시키는지 알려줌
The Loss Function
지금까지 하나의 network를 설계하는 방법을 보았지, 그 network가 어떤 문제를 풀어줄지 구별해내는 방법은 몰랐습니다. 이를 위해, loss function이 있습니다
loss function은 target의 실제값과 model의 예측값 사이 차이를 측정합니다.
문제가 달라지면 loss function(공식)도 달라집니다.
특정한 숫자값을 예측해주는 regression 문제에 흔히 사용되는 loss function은
(ex - calories in 80 Cereals, rating in Red Wine Quality, regression task로는 집값예측, 차의 연비효율성 예측 등)
MAE(mean absolute error)입니다.
abs(y_true - y_pred)로 실제와 예측 사이 차이를 구해줍니다.
총 MAE loss는 다른 모든 뺄셈에 대한 절댓값의 총합과 일치합니다.
MAE외에도, regression problem에서 접할 다른 loss function으로,
MSE(mean-squared error) 그리고 Huber loss가 있습니다. 둘다 Keras에서 가져올 수 있고요.
훈련하는 동안 model은 loss function을 가중치의 최적값을 찾는 용도로 사용합니다.
loss가 낮아질 수록 더 좋아집니다. 즉, loss function은 network가 target에 제대로 향하고 있는지 알려줍니다.
The Optimizer - Stochastic Gradient Descent
network가 어떻게 문제를 해결하는지 알고 싶다면 optimizer를 써야합니다.
loss를 최소화해주는 가중치로 조정하는 알고리즘입니다.
deep learning에 쓰이는 모든 optimiziation 알고리즘은 stochastic gradient descent로 불립니다.
이는 iterative(반복) algorithms으로 network가 한 step씩 훈련하게 해줍니다.
한 번의 step은 다음과 같은 과정을 거칩니다.
1. training data에서 몇몇 data를 가져와(sampling) network에 실행시켜 예측
2. 예측값과 실제값 사이 loss를 측정
3. 마지막으로, loss가 더 작은 방향으로 가중치를 조정
이 과정을 반복하여 loss가 가장 낮아질 때까지 하는 겁니다.
각각의 iteration을 위한 sampling은 "minibatch" (or "batch")로 불립니다.
전체 training data를 한 번 쭉 다 훑어보았다면 이는 '1 epoch'이라고 합니다.
epochs의 수는 훈련한 횟수를 의미합니다.
위의 GIF 중 첫번째는 linear model에 SGD를 적용한 것입니다. 흐릿한 빨간점은 전체 training data를 의미합니다. 진한 빨간 점은 minibatches를 의미하고요.
세번째 GIF로, 항상 SGD는 새로운 minibatch를 생성하며, 그럴 수록 가중치 w(slope)가 움직이며, 이에 따라 b(y절편)도 움직이는 것을 볼 수 있습니다. 이들은 그 batch에서 정확한 값을 향하고 있지요. batch를 계속 생성해낼 수록 선은 결국 최선의 일차함수로 수렴하게 됩니다.
보시다시피, 실제값에 가까워지도록 해주는 weights를 가질 수록 loss가 줄어드는 것을 두번째 GIF로 볼 수 있습니다.
SGD's meaning
'gradient'는 가중치들을 조정하여 어떤 기울기를 가져야하는지 알려주는 벡터입니다.
가중치가 변하는 방법 그리고 loss의 변화 속도도 빨라지는 방법도 알려줍니다.
"Gradient Descent"라고 부른 이유는, loss curve가 최저점을 향하도록 gradient 아래로 향하게 했기 때문입니다.
Stochastic은 "우연에 의해 결정된다"라는 의미입니다.
SGD가 우연성이 있다고 말할 수 있는 이유는, minibatchs가 dataset에서 무작위로 뽑아온 부분집합이기 때문입니다.
Learning Rate and Batch Size
직선은 각 batch에 따른 기울기를 조금 바꿀 수 있는 것뿐이란 점을 명심하세요.
이러한 움직임의 보폭(크기)는 learning rate로 결정됩니다.
learning rate가 작다는 의미는, network는 최적의 가중치로 수렴하기 전에 minibatchs가 더 필요하다는 의미입니다.
learning rate와 minibatch들의 크기는 SGD의 성능을 크게 좌우하는 parameters입니다.
두 parameter 간 상호작용의 영햑력은 미묘하지만 이러한 모수에 대한 올바른 선택이 항상 명확한 것은 아닙니다. (이러한 효과에 대해 실습해 보겠습니다.)
다행히도, 대부분의 작업에서 광범위한 hyperparameter search를 할 필요는 없습니다.
Adam은 SGD 알고리즘으로 parameter 튜닝 없이 대부분의 문제에 적합한 learning rate를 가집니다.
Adam은 훌륭한 범용 최적화 도구(general-purpose optimizer.)입니다.
정리하자면, learning rate와 batch size로 다음의 3가지를 조정할 수 있습니다.
1. model의 훈련 기간
2. learning curve의 noise 양
3. loss의 감소량(기울기)
아래의 코드블록은 각 parameter를 넣어보고 실행 시 GIF(animate_sgd)를 보여줍니다
# YOUR CODE HERE: Experiment with different values for the learning rate, batch size, and number of examples
learning_rate = 0.2 # more than 0.9 is overfit
batch_size = 32
num_examples = 256 #how many data points
animate_sgd(
learning_rate=learning_rate,
batch_size=batch_size,
num_examples=num_examples,
# You can also change these, if you like
steps=50, # total training steps (batches seen)
true_w=3.0, # the slope of the data
true_b=2.0, # the bias of the data
)
-> batch size가 작을 수록, Weight와 loss curves의 noise가 증가.
(이는 표본집합의 크기가 작으면 무작위 추출로 인해 측정치 noise가 생길 수 밖에 없음)
-> learning rate가 작을 수록, 업데이트가 작아지며, 훈련 (수렴하는) 기간이 길어짐
(learning rate가 크면 훈련 속도는 빨라지나, 최소값에 머무르게 됨. 그럼 훈련에 실패 -> 특히 0.99)
Add Loss and Optimizer
model를 정의한 후, model의 'compile' method로 loss function과 optimzier를 추가할 수 있습니다.
model.compile(
optimizer="adam",
loss="mae",
)
코드를 보면 loss와 optimizer를 String로 적어도 된다는 점 명심하세요.
parameter를 튜닝하고 싶다면, Keras API로 직접 접근해도 됩니다. (현재 실력으로는 기본값으로 하는 것이 낫습니다.)
Ex. Red Wine Quality Dataset
1600도 포루투갈 레드와인의 물리화학적 성분 및 블라인드 테스트를 통한 평가 점수를 담은 dataset입니다.
[0,1] 간격으로 일렬로 나열된 각 feature를 재배치하려 합니다.
neural networks는 입력값이 모두 같은 크기 일 때 최상의 성능을 발휘하니깐요.
import pandas as pd
from IPython.display import display
red_wine = pd.read_csv('../input/dl-course-data/red-wine.csv')
# Create training and validation splits
df_train = red_wine.sample(frac=0.7, random_state=0)
df_valid = red_wine.drop(df_train.index)
display(df_train.head(4))
# Scale to [0, 1]
max_ = df_train.max(axis=0)
min_ = df_train.min(axis=0)
df_train = (df_train - min_) / (max_ - min_)
df_valid = (df_valid - min_) / (max_ - min_)
# Split features and target
X_train = df_train.drop('quality', axis=1)
X_valid = df_valid.drop('quality', axis=1)
y_train = df_train['quality']
y_valid = df_valid['quality']
print(X_train.shape) #(1119, 11) -> 11 columns mean 11 inputs
약 1500개의 neurons보다 많이 가진 3-layer network를 선택해봅시다. (512*3+1)
이 network는 위의 data 속 복잡한 관계를 학습하기에 충분합니다.
from tensorflow import keras
from tensorflow.keras import layers
model = keras.Sequential([
layers.Dense(512, activation='relu', input_shape=[11]),
layers.Dense(512, activation='relu'),
layers.Dense(512, activation='relu'),
layers.Dense(1),
])
model의 구조를 정하는 것은 매우 중요한 절차입니다.
처음에는 간단하고 쉽게 만들어 본 후 validation loss를 보며 상세하게 그 구조를 정해갑니다.
model development에 대해서 이후 튜토리얼에 더 나옵니다.
model을 정의한 후 그 model에 optimizer와 loss function을 compile합니다.
model.compile(
optimizer='adam',
loss='mae',
)
Train Model
training을 하는 법은 다음과 같습니다.
Keras로 train data 속 256개의 rows (=batch size)를 한 번에 optimizer에 넣어줍니다.
이를 10번 (=epochs)합시다.
history = model.fit(
X_train, y_train,
validation_data=(X_valid, y_valid), #필수적이지 않음
batch_size=256,
epochs=10,
)
model이 trains를 거칠 수록 loss가 줄어들고 있습니다.
loss의 값을 편한 방식으로 보는 또다른 방법은 그래프로 그려보는 것입니다.
'fit' 메소드는 모델이 훈련되는 동안의 loss 값들을 'History' 객체에 기록해둡니다.
import pandas as pd
# convert the training history to a dataframe
history_df = pd.DataFrame(history.history)
# use Pandas native plot method
history_df['loss'].plot();
# 5번째 epoch부터 그래프를 그리고 싶다면,
# history_df.loc[5:, ['loss']].plot();
그래프를 이용하면 훈련 중에 loss가 어떻게 변화하는지 한 눈에 파악할 수 있습니다.
epochs가 진행될 수록 loss 값이 어떻게 변화하는 지 보는 것은 매우 중요하다는 점을 명심하세요
loss curve 또는 learning curve가 위와 같이 수평이 되면, 그 의미는 model의 학습이 완료되었음을 의미하며,
더 이상 eopchs를 추가적으로 진행할 필요가 없습니다.
두 curve 모두 수평을 보이면 제일 좋겠지요.
(learning curve란 train data로 그려본 loss curve에 epochs가 진행됨에 따라 validation data에서는 loss가 어떻게 변화하는지 train data와 valid data를 한 그림에 나타낸 그래프 -> 바로 다음 게시글에)
'Machine Learning > [Kaggle Course] ML (+ 딥러닝, 컴퓨터비전)' 카테고리의 다른 글
[Kaggle Course] Dropout, Batch Normalization (0) | 2020.12.26 |
---|---|
[Kaggle Course] Overfitting, Underfitting → early_stopping + capacity↑ (0) | 2020.12.24 |
[Kaggle Course] Deep Neural Networks _ nonlinear with ReLU (0) | 2020.12.19 |
[Kaggle Course] A Single Neuron _ Define a linear model (0) | 2020.12.17 |
[Kaggle Course] How to prevent "Data Leakage" (0) | 2020.11.01 |