[딥러닝] 신경망 학습

Bpius·2023년 11월 27일
0

딥러닝 기초

목록 보기
3/3
post-thumbnail

1. 학습

신경망의 특징은 데이터를 보고 학습할 수 있다는 것으로, 데이터에서 학습한다는 것은 가중치 매개변수의 값을 데이터를 보고 자동으로 결정한다는 뜻이다.

1.1 데이터 주도 학습

기계학습은 데이터에서 답을 찾고 패턴을 발견하는 등으로 데이터가 생명이다. 데이터가 이끄는 접근 방식으로 사람 중심 접근에서 벗어날 수 있게 된다.
사람과 달리 기계학습은 사람의 개입을 최소화하고 수집한 데이터로부터 패턴을 찾으려 시도한다. 게다가 신경망과 딥러닝은 기존 기계학습에서 사용하던 방법보다 사람의 개입을 더욱 배제할 수 있게 해주는 특징을 지녔다.

이미지에서 '특징(feature)을 추출하고 그 특징의 패턴을 기계학습 기술로 학습을 할 때, '특징'은 여전히 '사람'이 설계하는 것임에 주의해야 한다. 다시 말해 문제에 적합한 특징을 쓰지 않으면(설계 하지 않으면) 좀 처럼 좋은 결과를 얻을 수 없다는 뜻이다.

신경망의 이점은 모든 문제를 같은 맥락에서 풀 수 있다는 것이다. 주어진 데이터를 온전히 학습하고 주어진 문제의 패턴을 발견하려 시도한다. 즉 신경망은 모든 문제를 주어진 데이터 그대로를 입력 데이터로 활용해 'end-to-end'로 학습할 수 있다.
종단간 기계학습(end-to-end machine learning)에서 종단간은 '처음부터 끝까지'라는 의미로, 데이터 입력에서 목표한 결과까지 사람의 개입 없이 얻는다는 뜻이다.

1.2 훈련 데이터와 시험 데이터

기계학습에서 데이터를 취급할 때 주의할 점은 훈련 데이터와 시험 데이터를 나눠 학습과 실험(평가)을 수행하는 것이다. 시험 데이터를 사용하여 앞서 훈련한 모델의 실력을 평가하는 것이다.
이렇게 데이터를 나누는 것은 범용적으로 사용할 수 있는 모델을 설계하기 위함이다. 아직 보지 못한 데이터(훈련 데이터에 포함되지 않은 데이터)로도 문제를 올바르게 풀어내는 능력이 있어야 한다. 이 범용 능력을 획득하는 것이 기계학습의 최종 목표이다.

데이터셋 하나로만 매개변수의 학습과 평가를 수행하면 올바른 평가가 될 수 없다. 수중의 데이터셋은 제대로 맞히더라도 다른 데이터셋에는 엉망인 일도 벌어진다. 하나의 데이터셋에만 지나치게 최적화된 상태를 '과적합'(overfitting)이라고 하며, 이 과적합 피하기는 기계학습의 중요한 과제 중 하나다.

2. 손실 함수

신경망 학습에서는 현재의 상태를 '하나의 지표'로 표현한다. 그리고 그 지표를 가장 좋게 만들어주는 가중치 매개변수의 값을 탐색한다. '하나의 지표'를 기준으로 최적의 매개변수 값을 탐색하는데, 이 지표를 '손실 함수(loss function)이라 한다.

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

y는 신경망의 출력(신경망이 추정한 값), t는 정답 레이블, k는 데이터의 차원의 수를 나타낸다.
실제 예로 확인해보자.

def sum_squares_error(y, t):
    return 0.5 * np.sum((y - t)**2)

# index 2 정답
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]

# ex1
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
sum_squares_error(np.array(y), np.array(t))
>
0.09750000000000003

# ex2
y = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
sum_squares_error(np.array(y), np.array(t))
>
0.5975

예와 같이 정답은 '2'로 첫번째 예에서는 약 10%로 두번째 예에서는 60%로, 첫 번째 예의 손실 함수 쪽 출력이 작으며 정답 레이블과의 오차도 작다. 즉 오차제곱합 기준으로는 첫 번째 추정 결과가 오차가 더 작으니 정답에 더 가까울 것이라 판단할 수 있다.

2.2 교차 엔트로피 오차(cross entropy error, CEE)

log는 밑이 e인 자연로그, y는 신경망의 출력, t는 정답 레이블로 정답에 해당하는 인덱스의 원소만 1이고 나머지는 0(원-핫 인코딩)

def cross_entropy_error(y, t):
    delta = 1e-7
    return -np.sum(t * np.log(y + delta))

# index 2 정답
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]

# 예1
y = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
cross_entropy_error(np.array(y), np.array(t))
>
0.510825457099338

# 예2
y = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
cross_entropy_error(np.array(y), np.array(t))
>
2.302584092994546

delta값을 더한 이유는, np.log() 함수에 0을 입력하면 마이너스 무한대가 되기에, 아주 작은 값을 더하여 0이 되지 않도록(마이너스 무한대가 되지 않도록) 한 것이다.

정답일 경우 첫 번째 예의 오차는 0.51이고 두 번째 예의 오차는 2.3으로, 결과(오차 값)가 '더 작은' 첫 번째 추정이 정답일 가능성이 높다고 판한한다.

2.3 미니배치 학습

예로 MNIST 데이터셋은 훈련 데이터가 60,000개로 모든 데이터를 대상으로 손실 함수의 합을 구하려면 시간이 오래 걸린다. 더 나아가 빅데이터 수준이 되면 그 수는 수백만에서 수천만도 넘는 거대한 값이 된다.
이 많은 데이터를 대상으로 일일이 손실 함수를 계산하는 것은 현실적이지 않을 수 있다. 그래서 데이터 일부를 추려 전체의 '근사치'로 이용할 수 있는데, 신경망 한습 시 훈련 데이터로부터 일부만 골라 학습을 수행한다. 이 일부를 미니배치(mini_batch)라고 한다.
예로 MNIST 60,000장 중에서 100장을 임의로 뽑아서 100장만을 사용하여 학습을 한다.

from tensorflow import keras

mnist = keras.datasets.mnist

(train_x, train_y), (test_x, test_y) = mnist.load_data()
train_x.shape, train_y.shape, test_x.shape, test_y.shape
>
((60000, 28, 28), (60000,), (10000, 28, 28), (10000,))

훈련 데이터는 28*28 데이터가 6만장이고, 정답 레이블은 해당하는 숫자가 6만개인 데이터다.
이중에서 무작위로 100장만 빼내서 사용해보자.

train_size = train_x.shape[0]
batch_size = 100
batch_mask = np.random.choice(train_size, batch_size)
batch_x = train_x[batch_mask]
batch_y = train_y[batch_mask]

2.4 손실 함수 설정

신경망 학습에서 최적의 매개변수(가중치와 평향)를 탐색할 때 손실 함수의 값을 가능한 한 작게 하는 매개변수 값을 찾는다. 이때 매개변수의 기울기를 계산하고 그 기울기 값을 단서로 매개변수의 값을 서서히 갱신하는 과정을 반복한다.
매개변수의 손실 함수의 기울기란 '가중치 매개변수의 값을 아주 조금 변화시켰을 때, 손실 함수가 어떻게 변하나'라는 것이다. 만약 이 미분 값이 음수면 그 가중치 매개변수를 양의 방향으로 변화시켜 손실 함수의 값을 줄일 수 있다. 그러나 기울기 값이 0이면 가중치 매개변수를 어느 쪽으로 움직여도 손실 함수의 값은 줄어들지 않게 되어 가중치 매개변수의 갱신은 멈추게 된다.

'정확도'를 지표로 삼아서는 안 되는 이유는 바로 기울기(미분) 값이 대부분의 장소에서 0이 되어 매개변수를 갱신할 수 없기 때문이다.
정확도는 매개변수의 미소한 변화에는 거의 반응을 보이지 않고, 반응이 있더라도 그 값이 불연속적으로 갑자기 변화한다. 이는 활성화 함수로 '계단 함수'를 쓰지 않고 시그모이드 함수를 쓰는 이유와도 들어맞는다.

계단 함수는 한순간만 변화를 일으키지만, 시그모이드 함수의 미분(접선)은 출력이 연속적으로 변하고 곡선의 기울기도 연속적으로 변한다. 즉 시그모이드 함수의 미분은 어느 정소라도 0이 되지는 않는다.
이는 신경망 학습에서 중요한 성질로, 기울기가 0이 되지 않는 덕분에 신경망이 올바르게 학습할 수 있는 것이다.

3. 수치 미분

3.1 미분

미분은 '특정 순간'의 변화량을 나타낸다. 즉 미분은 특정 순간 기울기다.

미분하는 계산을 파이썬으로 구현해보자.

def numerical_diff(f, x):
    h = 1e-50
    return (f(x + h) - f(x)) / h

여기에서 2가지 문제가 있다.
먼저 h를 0에 최대한 가까운 값으로 하기 위해 '1e-50값을 지정하였으나 반올림 오차로 인해 0.0이라는 값을 가지게 된다. 보통은 h값으로 10에 -4승을 이용한다.
두번째는 f의 차분과 관련되어 있다. 특정 순간의 값은 0을 가지지 않기에, 특정 순간의 기울기가 아닌 x+h, x 사이의 기울기다. 그래서 특정 순간에서 (x-h)와 (x+h)일 때의 f 차분을 계산하는 방식을 쓰기도 한다. x를 중심으로 그 전후의 차분을 계산한다는 의미에서 중심 차분 혹은 중앙 차분이라 한다.

def numerical_diff(f, x):
    h = 1e-4
    return (f(x + h) - f(x - h)) / (2 * h)

3.2 편미분

변수가 여럿인 함수에 대한 미분을 편미분이라고 한다.

f(x0, x1) = x0^2, x1^2
위 식을 파이썬으로 표현하면 다음과 같다.

def function_2(x):
	return x[0]**2 + x[1]**2

f(x0, x1)을 미분하려면 x0와 x1 중 어느 변수에 대한 미분인 것인지 구별해야 한다.
x0은 3, x1은 4일 때, x0과 x1의 편미분을 파이썬으로 표현하면 다음과 같다.

# x0 편미분
def function_1(x0):
    return x0 * x0 + 4.0 ** 2.0

numerical_diff(function_1, 3.0)
>
6.00000000000378

# x1 편미분
def function_2(x1):
    return 3.0 ** 2.0 + x1 * x1

numerical_diff(function_2, 4.0)
>
7.999999999999119

편미분은 변수가 하나인 미분과 마찬가지로 특정 장소의 기울기를 구한다. 목표 변수 하나에 초점을 맞추고 다른 변수의 값은 고정을 한다.

4. 기울기

편미분에서는 x0와 x1을 따로 계산한 반면, 동시에, 한 번에 모든 변수의 편미분을 벡터로 정리한 것을 기울기(gradient)라고 한다.
아래와 같이 기울기는 방향을 가진 벡터(화살표)로 그려진다. 기울기는 함수의 '가장 낮은 장소(최소값)'을 가리키고 있다. 엄밀히 말해서 반드시 가장 낮은 장소를 가리키는 것이 아닌, 각 지점에서의 낮아지는 방향을 가리킨다.
기울기가 가리키는 쪽은 각 장소에서 함수의 출력 값을 가장 크게 줄이는 방향이다.

4.1 경사법

기계학습에서 최적의 매개변수(가중치와 편향)을 학습 시에 찾아야 한다. 그래서 기울기를 이용하여 함수의 최솟값(가능한 가장 작은 값)을 찾으려는 것이 경사법이다.
주의할 점은 각 지점에서 함수의 값을 낮추는 방안을 제시하는 지표가 기울기라는 것이다. 그러나 기울기가 가리키는 곳에 정말 함수의 최솟값이 있는지, 그 방향이 나아가야 할 방향인지는 보장할 수 없다.
기울어진 방향이 꼭 최솟값은 아니나, 그 방향으로 가야 함수의 값을 줄일 수 있다. 그래서 최솟값이 되는 장소를 찾는 문제에서는 기울기를 단서로 나아갈 방향을 제시하게 된다.

경사법은 현 위치에서 기울어진 방향으로 일정 거리만큼(learning rate) 이동한다. 이동한 곳에서 다시 기울기를 구하고 또 기울어진 방향으로 나아가기를 반복한다. 이렇게 해서 함수의 값을 점차 줄이는 것이 경사법(gradient method)이다.

이동을 할 때 얼마만큼 이동을 해야하는지, 즉 매개변수를 갱신할 때 갱신하는 양을 학습률(learning rate)이라고 한다. 이 값이 너무 크거나(값이 매우 불안정하게 튄다) 너무 작으면(국소적인 지역에 빠져 학습 진행이 안 된다) '좋은 장소(최솟값)'을 찾아갈 수가 없다.
학습률 같은 매개변수를 하이퍼파라미터(hyper parameter, 초매개변수)라고 하며, 사람이 직접 설정해야 한다. 이 하이퍼파라미터들은 여러 후보 값 중에서 시험을 통해 가장 잘 학습하는 값을 찾는 과정을 거친다.

4.2 신경망에서의 기울기

신경망 학습에서도 기울기를 구하는데, 여기서 기울기는 가중치 매개변수에 대한 손실 함수의 기울기다.
형상이 2x3, 가중치가 W, 손실 함수 L인 신경망이 있다. 여기에서 가중치를 변경했을 때 손실 함수 L이 얼마나 변했는지 나타내는 경사(경사의 형상은 2x3인 W와 같다)를 구할 수 있는데, 그 값들은 양수 혹은 음수로 되어 있다. 여기에서 음수는 양의 방향으로 양수는 음의 방향으로 갱신하고 값이 클 수록 갱신되는 데에 크게 기여하게 된다.

5. 학습 단계

신경망에는 적응 가능한 가중치와 편향이 있고, 이 가중치와 편향을 훈련 데이터에 적응하도록 조정하는 과정을 '학습'이라고 한다. 보통 다음과 같이 4단계를 거친다.

  • 1단계 - 미니배치 : 훈련 데이터 중 일부를 무작위로 가져온다. 선별된 데이터를 미니배치라고 하며, 그 미니배치의 손실 함수 값을 줄이는 것이 목표이다.
  • 2단계 - 기울기 산출 : 미니배치의 손실 함수 값을 줄이기 위해 각 가중치 매개변수의 기울기를 구한다. 기울기는 손실 함수의 값을 가장 작게 하는 방향을 제시한다.
  • 3단계 - 매개변수 갱신 : 가중치 매개변수를 기울기 방향으로 아주 조금 갱신한다.
  • 4단계 - 반복 : 1-3단계를 반복한다.

tip. 확률적 경사 하강법(SGD : stochastic gradient descent) : 데이터를 미니배치로 무작위로 선정하기에 확률적 경사 하강법이라고 부른다.

profile
데이터 굽는 타자기

0개의 댓글