본문 바로가기

ComputerScience/Machine Learning

DeepLearning - 3. Stochastic Gradient Descent

728x90
 

Stochastic Gradient Descent

Explore and run machine learning code with Kaggle Notebooks | Using data from DL Course Data

www.kaggle.com

*Kaggle에서 제공하는 Deep Learning Tutorial을 학습하며 번역한 내용입니다.

Introduction

이전 tutorial에서 dense layers의 stack에 따른 fully-connected networks를 만들어 보았다. 가장 처음 networks가 만들어지면 weights는 random하게 정해진다. 아직 network는 아무것도 모르는 상태인 것이다.

이번 장에서는 neural network를 학습시켜볼 것이다. 모든 machine learning task에서 처럼 우리도 data를 학습시키는 것 부터 시작할 것이다. 각 training data들은 input으로 받을 features와 기대값, output이 있다.

network를 학습시킨다는 것은 weights를 adjust하며 features로부터 target을  도출하도록 하는 것이다. 성공적으로 network를 학습시킨다면 weights는 features와 target의 relationship을 찾게 될 것이다.

데이터를 학습시키기 위해서는 다음 두가지가 필요하다.

  • network의 예측 정확도를 측정하는 "loss function".
  • network가 weights를 어떻게 변화시키는지 말해주는 "optimizer"

The Loss Function

network를 design하는 방식을 배웠다면 이번에는 network에게 어떤 문제를 풀어야 하는지 알려줄 것이다. 이 역할을 loss function이 수행한다.

loss function은 target의 실제 값과 model의 에측값의 차이를 측정하는 함수이다. different loss funciton이라고도 한다.

먼저 regression문제가 무엇인지 알고 설명을 이어가자. regression problems는 numerical value를 예측하는 task를 말한다. 예를 들면 첫시간에 예로 들었던 cereal의 칼로리 예측하기, 화인 점수 예측하기 문제가 이에 속한다.

regression 문제에서 쓰는 일반적인 loss function은 mean absolute error(MAE)이다. 각 예측값에 대해서 y value의 차이를 평균내서 구하는 것이다.

https://www.kaggle.com/ryanholbrook/stochastic-gradient-descent

mean absolute error는 fitted curve와 data points의 평균 거리이다. MAE외에 regression problems에서 loss functions으로 mean-squared error (MSE) 또는 Huber loss를 보게 될 수 도 있다.

학습하는 중에 model은 loss function을 가이드로 올바른 weights를 찾아가게 된다. 즉 loss가 낮을 수록 목표지점으로 잘 가고 있는 것이다.

The Optimizer - Stochastic Gradient Descent

model이 어떤 문제를 풀어야 하는지 공부했다. 올바른 weights를 찾기위해 loss function을 줄이는 문제를 풀어야 하는 것은 알겠는데 그럼 "어떻게" 이를 풀 수 있을까? optimizer가 이를 수행한다. optimizer는 loss를 줄이도록 weights를 조정하는 알고리즘이다.

사실상 deep learning에서 사용되는 모든 optimizer algorithms은 stochastic gradient descent에 속한다. 수치해석, 선형대수학 과목에서 공부할 수 있는 내용이다. 이 iterative algorithms으로 network를 한 스텝씩 학습시킨다.

각 스텝은 다음과 같다.

  1. 학습 데이터를 가지고 network에게 값을 예측해보라고 한다.
  2. true values와 predictions의 loss를 계산한다.
  3. 마지막으로 loss를 줄이는 direction으로 weights를 조정하게 된다.

loss가 만족할 만한 수준이 될때까지 혹은 더 이상 줄지 않을 때까지 이 과정을 계속 반복한다.

https://www.kaggle.com/ryanholbrook/stochastic-gradient-descent

Stochastic Gradient Descent로 neural network를 학습하는 모습이다.

각 iteration(위에서 설명한 학습 단계를 거쳐 최적화 하는 단계)에서 사용되는 training data를 minibatch라고 한다. 반면 모든 round를 마친 data를 epoch(전체 dataset에 대해 한번 학습을 마친상태)라고 한다. epochs의 수가 network가 training example을 학습하는 수와 동일하다. epochs = 40이라면 전체 데이터를 40번 사용해서 학습을 거치는 것이다.

 

애니메이션이 보여주는 것은 linear model이 SGD로 학습하는 모습이다. 연한 빨강 점들이 전체 training set이고 진한 빨강 점이 minibatch이다. 매번 SGD에서 새로운 minibatch를 학습하고 그에 따라 올바른 value를 향해 weights가 바뀐다. batch를 거듭하면 할 수록 line은 결국 best fit으로 수렴하게 된다. loss는 점점 작아지고 weights는 true value에 점점 가까워지는 것을 볼 수 있다.

Learning Rate and Batch Size

각 batch의 방향에 따라 Line이 조금씩 움직이다. 이 shift의 속도는 learning rate에 따라 결정된다. learning rate가 느리다는 것은 network의 weights가 best values로 수렴하기 위해 더 많은 minibatches를 봐야 함을 나타낸다.

전체 2000개의 데이터가 있고, epochs = 20, batch_size = 500이라고 하면 1 epoch는 size가 500인 batch들로 네 번의 iteration을 통해 학습한다. 그리고 전체 데이터셋에 대해서는 20번의 학습이 이루어졌으며, iteration 기준으로 보자면 총 80 번의 학습이 이루어진 것이다.

 

learning rate와 minibatches의 크기는 SGD training 진행에서 가장 큰 영향을 미치는 두 매개변수들이다. 이 두 매개변수들의 관계는 미묘해서 항상 최적의 선택을 하기가 쉽지는 않다.

하지만 만족할 만한 결과를 얻기 위해 반드시 minibatches의 수와 learning rate를 구할 필요는 없다. Adam은 SGD알고리즘으로 매개변수를 튜닝하지 않으면서도 대부분의 문제에서 적절한 learning rate를 얻도록 해준다. 일종의 "selft tuning"이다.

Adding the Loss and Optimizer

모델을 정의하고 나면 loss function과 optimizer를 mode.compile 메서드로 추가할 수 있다.

model.compile( 
    optimizer="adam", 
    loss="mae", 
)

loss와 optimizer를 string으로 쉽게 specify할 수 있다. 

Keras API를 통해서 직접 여기에 접근해서 parameters를 튜닝할 수도 있지만 우리에게 defaults로도 당분간은 충분할 것이다.

 

gradient는 weights가 이동해야하는 방향을 vector로 표현한 것이다. 더 구체적으로 말하면 loss가 빠르게 변하도록 weights가 이동해야하는 방향을 알려준다. 

loss curve를 minimun으로 낮추도록 gradient를 사용하기 때문에 gradient descent라고 부른다.

stochastic은 우연히 결정된다는 뜻이다. minibatches는 dataset에서 random하게 얻어지는 samples기 때문에 우리가 진행하는 학습은 stochastic하다.

Example - Red Wine Quality

이제 deep learning models을 학습시키기 위해 필요한 모든 것을 알았다. Red Wine Quality dataset을 학습시켜 보자. 1600 Portuguese red wines의 physiochemical measurements 구성에 대한 정보를 갖고 있다. 또한 각 와인에 대한 rating의 정보도 들어있다. measurements를 가지고 quality rating을 예측해보자.

 

아래 코드는 데이터를 준비하기 위한 코드이다. 가벼운 마음으로 넘어갈 것이다. 단

한가지 살펴볼 점은 각 feature가 [0,1][0,1] interval에 놓이도록 rescale했다는 것이다. 뒤에서 더 배우겠지만 neural networks는 inputs가 common scale일 때 최고의 결과를 보이는 경향이 있다.

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']

https://www.kaggle.com/ryanholbrook/stochastic-gradient-descent

newtwork가 몇개의 input 가져야 할까? 화면에 표시한 matrix에서 target열을 제외한 column의 수를 살펴보자. 

print(X_train.shape)

https://www.kaggle.com/ryanholbrook/stochastic-gradient-descent

데이터는 1119행 11열로 되어있다. 이 데이터를 학습시키기 위해 1500개의 neurons으로 구성된 three-layer network를 정의할 것이다. 이정도면 데이터의 복잡한 관계들을 꽤나 잘 학습할 수 있을 것이다.

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의 architecture를 결정하는 것도 과정의 일부이다. 뒤에서 연습을 통해 배울 것이다.

모델을 정의하고 나면 optimizer and loss function에서 모델을 compile하자.

model.compile(
    optimizer='adam',
    loss='mae',
)

이제 training을 위한 준비는 끝났다. Keras에게 data set에서 한번에 256개의 행의 data를 optimizer에게 넘길 것(the batch_size) 이고 전체 dataset에 대해 학습을 10번 반복할 것이다(the epochs) 라고 말해주자.

history = model.fit(
    X_train, y_train,
    validation_data=(X_valid, y_valid),
    batch_size=256,
    epochs=10,
)

https://www.kaggle.com/ryanholbrook/stochastic-gradient-descent

Keras는 model이 학습할때마다 loss를 업데이트 하고 있다. loss를 그래프로 그려서 확인할 수도 있다.

fit 메서드는 학습을 진행하는 중에 loss의 기록을 보여주는 함수이다.

pandas dataframe으로 data를 변환해서 쉽게 loss를 화면에 그래프로 그려보자.

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();

https://www.kaggle.com/ryanholbrook/stochastic-gradient-descent

epochs가 진행되면 될 수록 loss가 줄어드는 것을 보자. 위 그림처럼 수평에 다다를 때 쯤이면 model이 학습을 마쳤기 때문에 추가 epochs를 학습할 필요가 없다.

Exercise

Fuel Economy dataset을 neural network에게 학습시켜보고 SGD에서 learning rate와 batch size가 미치는 영향을 살펴보자.

# Setup plotting
import matplotlib.pyplot as plt
from learntools.deep_learning_intro.dltools import animate_sgd
plt.style.use('seaborn-whitegrid')
# Set Matplotlib defaults
plt.rc('figure', autolayout=True)
plt.rc('axes', labelweight='bold', labelsize='large',
       titleweight='bold', titlesize=18, titlepad=10)
plt.rc('animation', html='html5')

# Setup feedback system
from learntools.core import binder
binder.bind(globals())
from learntools.deep_learning_intro.ex3 import *

자동차의 엔진, 제조년도등의 features를 가지고 fuel economy를 예측할 것이다. 

아래 코드를 통해 데이터를 불러오자.

import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import make_column_transformer, make_column_selector
from sklearn.model_selection import train_test_split

fuel = pd.read_csv('../input/dl-course-data/fuel.csv')

X = fuel.copy()
# Remove target
y = X.pop('FE')

preprocessor = make_column_transformer(
    (StandardScaler(),
     make_column_selector(dtype_include=np.number)),
    (OneHotEncoder(sparse=False),
     make_column_selector(dtype_include=object)),
)

X = preprocessor.fit_transform(X)
y = np.log(y) # log transform target instead of standardizing

input_shape = [X.shape[1]]
print("Input shape: {}".format(input_shape))

https://www.kaggle.com/ryanholbrook/stochastic-gradient-descent

target이 되는 FE column을 제외하고 남아있는 column이 input features가 된다.

# Uncomment to see original data
fuel.head()

https://www.kaggle.com/scratchpad/notebookc5abbb1f2a/edit

위가 original data를 출력한 모습이고

아래가 pandas dataframe으로 데이터를 변환한 모습이다. 

https://www.kaggle.com/scratchpad/notebookc5abbb1f2a/edit

이제 아래처럼 network를 정의하고 compile 메서드로 Adam optimizer와 MAE loss를 추가해준다.

from tensorflow import keras
from tensorflow.keras import layers

model = keras.Sequential([
    layers.Dense(128, activation='relu', input_shape=input_shape),
    layers.Dense(128, activation='relu'),    
    layers.Dense(64, activation='relu'),
    layers.Dense(1),
])
# YOUR CODE HERE
model.compile(
    optimizer='adam',
    loss='mae',
)

모델을 정의하고 loss, optimizer를 컴파일 했다면 학습 준비는 끝났다.

200 epochs, batch_size = 128, input data는 X, target은 y로 데이터를 학습시킨다.

# YOUR CODE HERE
history = model.fit(
    X, y,
    validation_data=(X, y),
    batch_size=128,
    epochs=200,
)

https://www.kaggle.com/scratchpad/notebookc5abbb1f2a/edit
https://www.kaggle.com/scratchpad/notebookc5abbb1f2a/edit

loss curve를 관찰하고 training을 평가해보자. training loss를 plot해보자.

import pandas as pd

history_df = pd.DataFrame(history.history)
# Start the plot at epoch 5. You can change this to get a different view.
history_df.loc[5:, ['loss']].plot();

https://www.kaggle.com/scratchpad/notebookc5abbb1f2a/edit

만약 model을 더 오래 train했다면 loss는 더 줄었을까?

만약 learning curve가 다시 반등한다면 additional epochs를 학습시키는 것에 이점이 없을 것이다. 반면 loss가 꾸준히 줄어드는 것이 보인다면 epochs를 추가로 학습시키는데 이점이 있을 수 있다. 

learning rate와 batch size로 통제할 수 있는 것은 다음과 같다.

  • model을 학습시키기 위해 얼마나 시간이 필요한가?
  • learning curves가 얼마나 noisy한가?
  • loss를 얼마나 줄일 수 있나?

이 두 매개변수를 더 잘 이해하기 위해서 single weight와 a bias만으로 구성된 아주 간단한 neural network의 linear model을 보자.

https://www.kaggle.com/scratchpad/notebookc5abbb1f2a/edit

다음의 코드를 실행하면 animation이 나올 것이다. learning_rate, batch size, num_examples를 조작해서 각 결과를 살펴보자.

# YOUR CODE HERE: Experiment with different values for the learning rate, batch size, and number of examples
learning_rate = 0.05
batch_size = 32
num_examples = 256

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 curve가 noisy하게 update된다. 하지만 "averaging"효과를 장점으로 취할 수 있다.

https://www.kaggle.com/scratchpad/notebookc5abbb1f2a/edit

learning rate가 작을수록 update가 적고 training이 오래 걸린다. 

https://www.kaggle.com/scratchpad/notebookc5abbb1f2a/edit

learning rate가 클수록 training 속도는 빠르다 하지만 minimun한 값으로 settle되지 않을 수 있다. 즉 학습이 실패할 수 있는 것이다.

728x90
반응형