[밑바닥딥러닝] 5. 신경망 학습 - 손실 함수, 미니 배치 학습

2021. 9. 30. 22:43Deep Learning

본 게시글은 한빛미디어 『밑바닥부터 시작하는 딥러닝, 사이토 고키, 2020』의 내용을 참조하였음을 밝힙니다.

 

기계학습에서 '학습'이란 훈련 데이터(입력, 타깃)를 통해 가중치 매개변수의 값을 가장 최적의 방향으로

 

조정하는 과정을 말한다.

 

이번 장에서는 신경망에서 학습이 이루어지는 원리를 실습을 통해 알아보도록 하자. 

 

 

훈련 데이터


기계학습에서는 예측 모델을 학습시키기 위해서 훈련 데이터(training data)를 사용한다. 

 

훈련 데이터란 오로지 학습을 위해서 전체 데이터에서 일부분의 데이터를 따로 떼어놓은 데이터들이다. 

 

(이후에 훈련 데이터도 하이퍼 파라미터의 조정을 위해서 또 나눠지긴 하지만 일단은 위의 수준까지만 알아두자.)

 

훈련 데이터로 훈련시킨 예측 모델은 시험 데이터(test data)를 통해 정확도를 측정한다. 

 

이렇게 데이터를 훈련 데이터 / 시험 데이터로 분리하는 이유는 무엇일까?

 

바로 과적합(overfitting)을 막기 위해서이다. 

 

과적합 혹은 오버피팅이라고 부르는 이 상황은 예측 모델이 특정 데이터에 대해서만 과도하게 

 

정확하게 예측하고, 이외의 데이터에 대해서는 좋은 성능을 내지 못하는 상황을 말한다. 

 

좋은 인공지능 모델은 어떤 데이터가 주어져도 최대한 정답에 근접하게 예측하는 것을 목표로 해야한다.

 

이러한 과적합을 막기 위해서 일부(75% 정도)를 훈련 데이터로 가중치를 조정하고, 이렇게 훈련시킨 모델을 

 

나머지 데이터(25%)로 평가한다. 

 

 

 

손실 함수


예측 모델이 가중치 파라미터들을 조정하는 과정을 학습이라고 하는데, 무엇을 근거로 가중치들을 조정하는 것일까?

 

우리가 어떤 실수를 했을 때 그에 대한 피드백이 얼마나 좋게 돌아오는지에 따라서 내가 했던 행동이 옳은 행동인지, 

 

나쁜 행동인지 판단한다. 아주 나쁜 피드백이 돌아왔을 경우, 나의 행동이 크게 잘못되었음을 깨닫고 다음에는 그와

 

거리가 먼 행동을 한다. 반대로 아주 작은 피드백만 돌아왔을 경우 나의 행동이 크게 잘못된 것은 아니라고 생각하고, 

 

조금만 수정한다. 기계 학습에서도 마찬가지로 이러한 피드백을 근거로 학습을 진행한다. 

 

이 피드백은 바로 '손실 함수(loss function)'이다.

 

오차제곱합(sum of squares for error)

위는 대표적인 손실 함수 중 하나인 오차제곱합(sum of squares for error, SSE)이다. 

 

모든 데이터셋 각각에 대해 예측값과 타깃값과의 차를 제곱한 값의 총합이다. 

 

좋은 예측모델을 만들었다면 이 차들이 작을 것이고 그에 따라 총합 역시 낮게 계산된다. 

def mean_squared_error(y, t):
    return 0.5 * np.sum((y - t) ** 2)
>>> t
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
       [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.]])
>>> y
array([[ 0.09087905, -0.39666383, -0.38272683, -1.76902441,  0.00956927,
        -1.40161612, -0.53399542,  0.56951132,  0.38564311,  0.6447074 ],
       [ 0.2697426 ,  0.60503135,  0.58924686, -0.06857632,  0.44826793,
        -0.23927187,  0.12297712, -0.7148171 , -0.16705371, -0.45505456],
       [ 0.52421486,  1.15794998,  0.33975237, -0.36683005,  1.99543272,
         0.2059575 , -0.78080009,  1.03524916, -0.32994566,  0.93765515]])
>>> mean_squared_error(y, t)
8.867202543926036

다음으로 살펴볼 손실 함수는 교차 엔트로피 에러(Cross entropy error, CEE)이다. 

Cross entropy loss

출처 : https://androidkt.com/choose-cross-entropy-loss-function-in-keras/ 

 

log 함수 안에 들어간 값은 신경망의 출력이고, 로그 앞에 곱해진 값은 타깃값이다. 

 

값이 원-핫 인코딩(출력 차원에서 정답만 1, 나머지는 0을 갖는 인코딩방식)되었을 경우, 교차 엔트로피 손실은 

 

정답일 때의 log_예측값에 의해 좌우된다. 식의 앞에 -(마이너스)가 붙은 것은 만약 예측값이 낮은 값일 경우에 

 

로그 함수는 0에 가까워질수록 음의 무한대로 발산하기 때문에 로그 값은 (절대값이 아주 큰) 음의 값을 갖게 되고

 

이 음수가 마이너스에 의해 양수로 전환됨에 따라 손실함수의 값이 매우 매우 커지게 된다. 

def cross_entropy_error(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)

    # 훈련 데이터가 원-핫 벡터라면 정답 레이블의 인덱스로 반환
    if t.size == y.size:
        t = t.argmax(axis=1)

    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size

만약 예측값인 y가 1차원일 경우(하나의 케이스에 대해서만 예측) y와 t를 각각 일렬로 펼친다. 

 

데이터가 원-핫 벡터라면 타깃데이터인 t에서 가장 큰 값을 가진 인덱스만을 골라낸다. (원-핫 벡터에서는 정답이 아닌 값은 모두 0이기 때문에 1만 뽑아서 곱한다.)

 

예측값인 y 값에서 정답값에 해당하는 확률값을 모두 더한 뒤, 이를 배치 크기로 나누어 평균값을 구한다. 

(주의 : y값이 정답이라고 인식하는 값이 아닌, 실제 정답인 값을 y에서 정답일 것이라고 예측하는 확률을 의미한다.)

>>> y
array([[0.16032653, 0.27251742, 0.9881026 , 0.21175294, 0.87292987,
        0.52573235, 1.74619987, 0.68761469, 0.26265203, 0.07598653],
       [0.99181652, 0.79332495, 0.77192382, 0.40548031, 1.00313664,
        0.23676847, 1.27241243, 0.58213501, 0.15612919, 1.52075023],
       [0.19447486, 0.55598307, 0.98332517, 1.02117306, 0.87142618,
        0.18348051, 0.90962924, 0.37697229, 0.31292802, 0.13194723],
       [0.84941354, 1.85203688, 1.44241911, 1.22524383, 2.43431079,
        0.0778846 , 0.05049367, 0.48077644, 0.12184315, 0.47838131]])
>>> t
array([[0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
       [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
       [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.]])
>>> cross_entropy_error(y, t)
0.522943135433109

 

손실 함수값을 계산할 때, (미니)배치 크기로 나누는 이유는 무엇이고, 미니 배치를 뽑는 이유는 무엇일까?

 

 

 

미니배치 학습


예측 모델을 훈련시킬 때 훈련 데이터에서 미니 배치라는 특정 데이터들을 뽑아낸다. 

 

이를 미니배치 학습이라고 한다. 

베지터가 훈련 시 상대하는 재배맨과 이름도, 용도도 유사하다

미니 배치를 따로 뽑아서 훈련시키는 이유는 무엇일까? 전체 훈련 데이터로 한꺼번에 계산해서 나온 값으로 

 

조정하지 않는 것일까?

 

우리가 여론 조사를 할 때 5000만 국민들의 의견을 전부 조사할 수 없듯이, 실제 기계학습에서도 훈련 데이터를 

 

전부 사용해서 계산하기는 어렵다. 따라서 훈련 데이터에서 일부씩을 추출하여 학습에 이용한다. 

 

또한 각 epoch마다 서로 다른 배치 데이터를 추출하여 손실 함수값을 계산하면 예측 모델의 학습에 

 

무작위성이 추가되기 때문에 더 정확한 학습을 기대할 수 있다. 우리가 원하는 모델의 미덕은 범용성이지 않은가!

환경에 따라 서로 달리 진화한 새 종. 기계 학습도 이처럼 데이터에 따라 가중치가 달라진다.

출처 : https://www.britannica.com/science/speciation