220704_TIL / training Neural Network

신두다·2022년 7월 4일
0

TIL

목록 보기
51/82

Key words

순전파(Forward propagation / Feedforward), 역전파(Backpropagation), 손실함수(Loss function), 옵티마이저(optimizer), 경사하강법(Gradient Descent), 확률적 경사하강법 (Stochastic GD), Mini-batch GD

1. 신경망은 어떻게 학습이 이루어질까?


[반드시 기억하기!]
1. 데이터가 입력되면 신경망 각 층에서 가중치 및 활성화 함수 연산을 반복적으로 수행한다.
2. 1의 과정을 모든 층에서 반복한 후에 출력층에서 계산된 값을 출력한다.
3. 손실 함수를 사용하여 예측값(Prediction)과 실제값(Target)의 차이를 계산한다.
4. 경사하강법과 역전파를 통해서 각 가중치를 갱신한다.
5. 학습 중지 기준을 만족할 때까지 1-4의 과정을 반복한다.


순전파란 입력층에서 입력된 신호가 은닉층의 연산을 거쳐 출력층에서 값을 내보내는 과정을 말한다.

  • 쉽게 input layer로 값이 들어간 후 가중치-편향 연산을 거쳐 활성화 함수를 통해 다음 layer로 전달되는 과정을 생각하면 된다.

손실함수(Loss Function)

  • 이렇게 한번 output layer를 거치면 어떤 예측값이 튀어나올텐데, 여기서 우리가 이런 모델링을 하는 목표는 뭐다?! 실제값과 예측값의 차이를 줄이는거다~!
  • 이때 쓰이는게 바로 손실함수다. 출력된 예측값과 실제값(=타겟값)은 이 손실함수에 들어가 손실(loss/error)을 계산하게 된다.
  • 대표적인 손실함수로는 MSE(Mean-Squared Error), CEE(Cross-Entropy Error)가 있다. (이것에 대해선 머신러닝 할 때 다뤘기 때문에 낯선 개념은 아니다.)
    • 다중분류 문제에서 사용할 수 있는 손실함수로 categorical_crossentropy / spase_categorical_crossentropy
      가 있는데, 이 둘의 차이는 이 글을 참고하자.

역전파 오늘의 핵심..!!!

  • 역전파는 말 그대로 순전파의 반대말이다. 순전파가 input layer > output layer 방향으로 진행되었다면, 역전파는 손실 정보(예측값과 타겟값의 차이)를 output layer > input layer까지 전달하며 각 가중치를 얼마나 업데이트 해야할지를 구하는 알고리즘이다.
  • 이때 가중치 업데이트는 손실(Loss)를 줄이는 방향으로 진행된다. 당연하겠지!
  • 근데 이때 가중치를 어떻게 수정해야 손실을 줄일 수 있을까? 바로 그 때 쓰는 게 경사하강법(Gradient Descent, GD)이다.

경사 하강법

  • 이 수식은 기억해두어야 한다.
  • 경사 하강법은 머신러닝할 때 한 번 봤었다. 매 iteration (= 순전파 역전파 한번 도는 것)마다 해당 가중치에서의 비용함수의 도함수를 계산해서 경사가 작아질 수 있도록 가중치를 변경하는 것이다.
    • (만약 나중에 너 이 말 다시 보고 헷갈리면 경사하강법에서 비용함수를 미분한 값이 0에 가까워지도록 하는 것이 오류(손실)를 최소화하는 것이라는 의미를 까먹은거니까 다시 공부하거라)

여기서! 옵티마이저(Optimizer)를 한 번 얘기해보자.

  • 옵티마이저는 쉽게 말해 경사를 내려가는 방법을 결정하는 것이다. 이런 것들이 있는데, 다 외우지는 않아도 된다고 함.
  • 우리가 일반적으로 쓰던 경사하강법은 위 이미지에서 GD이다. 한 iteration마다 주어진 모든 데이터를 다 쓰면서 가중치를 업데이트 하는거다. 그럼 문제가 뭐다? 데이터가 많으면 시간이 엄청나게 들겠지!
  • 그래서 이 문제를 해결하려고 나온게 바로 확률적 경사하강법(SGD)mini-batch 경사하강법이다.
    • 먼저 확률적 경사하강법(SGD). 이건 전체 데이터에서 딱 하나의 데이터를 뽑아서 신경망에 입력한 후 손실을 계산하고, 그 정보를 역전파하여 가중치를 업데이트 하는 방법이다. 다시 말해 한 iteration 마다 1개의 데이터를 사용한다는 거다.
      • 하나씩 돌리니 가중치를 빠르게 업데이트할 수 있다는 장점은 있지만, 만약 그 1개의 데이터가 Outliar라면? 학습과정에서 불안정한 경사하강을 보일 수 있는 단점이 있다. (여기저기 쓕쓕 튈 수도 있을거 같다.)
    • 이런 SGD의 문제점을 개선하고자 나온게 바로 mini-batch 경사하강법이다. 아까 SGD가 딱 1개의 데이터만 썼다면, 미니배치 경사하강법은 지정된 N개의 데이터를 쓴다는 차이만 있다. 이때 이 N개는 batch size 라고 부른다.
      • 참고1. 메모리 크기가 허락한다면 큰 배치 사이즈를 쓰는 것이 학습을 안정적으로 진행할 수 있다고 한다. SGD가 이상치 때문에 튈 수 있던 상황을 생각하면 될 듯.
      • 참고2. 만약 총 데이터 1000개에서 배치 사이즈를 256개로 하면, 마지막에 배치에서 232개 밖에 없는데 이때는 어떻게 할까? 정답은 그냥 232개로 돌려서 가중치를 갱신한다고 한다.
잠깐 여기서 나중에 헷갈릴 것 같은 것 정리하고 가보자.

Q. 아래 조건에 따라 학습을 진행할 경우 전체 Iteration 횟수로 알맞은 걸 골라주세요.

조건1) 학습에는 총 20000개의 데이터를 사용한다.
조건2) Batch size는 1000, Epoch는 5로 설정한다.

정답은?! 100이다.
--
- Epoch란 데이터셋 전체를 이용해서 학습한 횟수를 말한다.
- 즉, 한 epoch에는 20000/1000인 20번의 iteration이 돌게 되고, 이걸 5번 반복하면 총 100번의 iteration이 도는거다.

(참고로 iteration은 무조건 전에 골랐던 데이터를 제외한 나머지 중에 선택된다고 한다.)
  • 당연하게도 어떤 옵티마이저가 가장 좋은지 정답은 없고 사바사라고 한다. (근데 잘 모르겠으면 일단 adam을 써보면 된다고 한다. 성능이 꽤 잘 나온다고 함.)

자, 여기까지 하면 우리가 케라스 돌릴 때 쓰던 model.compile의 각 요소에 대해서 공부한 것이다.

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

2. 역전파 편미분 / Chain Rule(연쇄 법칙)

  • 아, 역전파 편미분해서 가중치 찾아나가는거 오늘 여럿 봤는데 정말 이해하기 너무 힘들었다. 이 웜업영상도 그렇고.. 무조건 알아야 하는건데,,!!!
  • 이 영상도 추가로 찾아봤었음.
  • 일단 오늘은 시간이 늦었으니까 주말에라도 시간내서 다시 공부하자.

Chain Rule은 이전에 함수 속에 또 함수가 있을 때 겉미분*속미분이걸로 기억하고 있었다. 오늘은 특정 변수에 대한 (편)미분 값을 다른 변수의 미분을 사용하여 나타낼 수 있는 방식으로 보았다.


3. 퀴즈 푼 것

퀴즈 푼 것중 코드와 관련해서 기억해야할 것만 옮겨둔다.

1. 빈칸에 들어갈 숫자를 모두 더한 값은?

  • 은닉층은 총 __개다.
  • 입력층에서 은닉층으로 갈 때의 가중치는 __개다.
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

model = Sequential()
model.add(Dense(5, activation='relu', input_dim=2))
model.add(Dense(3, activation='softmax'))
  • 정답은 11이다. 이거는 가중치 행렬에 대한 것이다. 은닉층이 1개인 건 쉽게 알 수 있을거고. 입력층의 노드는 2개(input_dim)이고 은닉층에 노드가 5개 있으니 10개의 가중치가 존재하는 거다.

근데 그러면 여기서 또 헷갈리는 문제가 하나 있었다.
바로 model.summary()를 했을 때 나오는 pram(파라미터의 수)를 구하라는 거였다.

  • 여기서 파라미터는 입력노드와 출력노드에 대해 연결된 간선의 수를 말한다. 즉 위위 이미지에서 저 각 노드간 연결되어있는 선들!을 말한다.
  • 그럼 만약 1번 문제에서 입력층 > 은닉층의 파라미터의 수를 구하면 10일까? 아니다. 정답은 12다. 왜냐? 인풋에 편향(instance, bias) 노드가 추가되기 때문이다.
  • 근데 이게 input layer > hidden layer로 넘어갈 때 뿐 아니라 그 이후 Layer이동할 때도 편향이 계산되길래, 이게 참 헷갈려서 아래와 같은 질문을 하기도 했다.

    (...) 제가 드린 질문의 포인트는 은닉층에도 편향이 있다는게 어떤 의미인지였습니다. 금요일에 본 신경망 그림에서는 instance가 input layer에서만 표시가 되어있던 것 같거든요. 근데 레이어 넘어가면서 파람 구하는거 보면 매 레이어마다 편향이 있다는 것처럼 여기는데 그 의미가 뭔지 궁금했어요)

  • 대답은 모든 노드에는 편향이 존재하며, use_bias 파라미터의 디폴트가 True여서 모든 은닉층에서도 편향을 포함해 계산한다고 한다. 만약 use_bias 파라미터를 False로 하면 미포함 계산 가능였다.
  • 이 사이트 참고했고, 암튼 가중치 행렬이랑은 헷갈리지 말자!!!

4. 실습한 것

[sigmoid 함수 구현하기]
S(x)=(1+ex)1S(x) = (1+e^-x)^-1

class Sigmoid:
    def __init__(self):
        self.out = None

    def forward(self, x):
        out = 1 / (1 + np.exp(-x)) # 위의 sigmoid 식을 그대로 표현하면 된다. 
        self.out = out
        return out

    def backward(self, dout):
        # dout : 앞선 레이어에서 chain rule에 의해 넘어온 값
        dx = dout * (self.out * (1-self.out)) # sigmoid(x)를 x에 대해 미분하면 sigmoid(x)(1-sigmoid(x))이다. 
        
# 레퍼런스 http://taewan.kim/post/sigmoid_diff/ & https://wiserloner.tistory.com/m/1076
  • 이건 Sigmoid 함수가 뭔지, 미분하면 어떻게 되는지를 알면 풀 수 있는 문제였다.
  • 참고로 sigmoid 함수 미분은 증명 보고 나도 아래와 같이 따라해보았다.
  • 역전파 노트별 정리 부분의 이 블로그 글도 좋았다. 참고하자.

[softmax 구현하기]

def softmax(x):
    return np.exp(x) / np.sum(np.exp(x)) # 증명은 나중에 해보자.

test_array = np.array([19, 15.5, 10.4, 3.33, 20.8])

# tensorflow softmax와 값 비교
print(softmax(test_array)) # 결과 해석: 각각의 클래스에 속할 확률을 나타내준다. 합은 1이며, 그 중 가장 확률이 가장 큰 클래스에 속한다고 결론을 내릴 수 있음.  
print(tf.nn.softmax(test_array))
  • 레퍼런스
  • 나중에 증명 해보자.. softmax 수식 찾아서 표현만 해봤다.

[cross_entropy 구현하기]

def cross_entropy_loss(y_true, y_pred):
    first = y_true*np.log(y_pred + (1e-7)) # 레퍼런스: 디스코드에 공유된 수식 & https://kejdev.tistory.com/41
    second = -np.sum(first)
    return second
  • 참고하자.

[Keras 이용하기]

  • 32개의 노드를 가진 입력층, 64개, 256개의 노드를 가진 각 1개(=총 2개)의 은닉층, 5개의 클래스로 구성된 데이터를 가진 신경망을 만들고자 합니다. 주석 처리된 곳에 알맞은 숫자를 입력해주세요.
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

A = 64
B = 32
C = 256
D = 5

model = Sequential([
    Dense(A, activation='sigmoid', input_dim=B), # A, B
    Dense(C, activation='sigmoid'), # C
    Dense(D, activation='softmax') # D
])

lossFunction = 'categorical_crossentropy' # activation function으로 softmax가 쓰였으니 다중 분류 문제임. sparse_categorical_crossentropy도 가능
batch_size = 50 # 1-3번 문제의 조건을 보고 지정해둠.

model.compile(optimizer='sgd', loss=lossFunction, metrics=['acc'])
 
results = model.fit(X,y, batch_size=batch_size, epochs=100)
  • 진짜 이거 헷갈리기 딱 좋을 듯!!!!!!! 잘 기억해둬라.

5. 그 외

  • 지수함수는 미분해도 자기 자신이다. 다시 찾아봤음..

Feeling


  • 오전부터 역전파 편미분 때문에 완전 멘붕의 연속이었다. 오늘은 수학적 개념을 가장 많이 다뤘던 것 같다. 아~ 수학이시여~~ 그래도 그 전에 자의건 타의건 공부 안 해서 이번에 처음 본 거니까 혼나면서 배워야지 뭐 어쩔 수 있나!
  • 그래도 오늘 sigmoid 미분 증명 따라해보며 이해한거는 재밌었다. 어차피 수학은 언젠가라도 반드시 다시 만나서 해야할 공부니까 재미있게 해보자!
profile
B2B SaaS 회사에서 Data Analyst로 일하고 있습니다.

0개의 댓글

관련 채용 정보