머신러닝과 딥러닝/딥러닝

DNN(Deep Neural Net)의 전체적인 Flow

Stat_in_KNU 2020. 12. 2. 19:27

매번 수박 겉핥기 식으로 딥러닝 공부를 하고, 또 코드를 긁어서 쓰는 수준에 그쳤었습니다.

 

그러다 S사 면접에서 전문가들의 깊이 있는 질문에 답하지 못했던 아쉬움이 남아, 늦었지만 딥러닝 이론을 정리해보고자합니다.

 

개인적인 정리용도이지만 오류나 질문사항이 있으면 댓글 부탁드립니다!

 

딥러닝이 담고있는 수학, 컴퓨팅 알고리즘적인 깊이 때문에 깔끔한 정리는 되지않을 것 같습니다. 또한, 대략적인 요약이라 상세한 부분은 생략할것입니다.


 

1. 딥러닝은 어디에서부터 왔는가?

 

 

퍼셉트론

딥러닝은 우리 뇌의 신경망 구조를 본뜬 퍼셉트론(Perceptron)에서 부터 출발했습니다. 딥러닝이 현재 실제로 상용화된 인공지능 서비스까지 닫기에 많은 고난을 거쳤지만(XOR문제, 계산속도 문제, Backpropagation의 등장 등..) 아무튼 현재는, 퍼셉트론에서 시작한 딥러닝이 생활 곳곳에 자리잡고 있습니다.

 

누군가는 퍼셉트론과 딥러닝신경망의 차이점을 활성함수(Activation Function)의 유무라고 표현하였는데 확실한지는 모르겠습니다.

 

아무튼 딥러닝은 가중치의 학습을 통한 정확한 예측을 목적으로 하고 있습니다.

 

2. 그러면 딥러닝 가중치는 무엇을 기준으로 학습해야하나?

 

무언가를 학습하려면 목적에 알맞게 학습할 필요가 있습니다. 컴퓨터 또한 마찬가지입니다. 어떠한 목적을 가지는 "방향"으로 학습 할 필요가 있습니다.

 

딥러닝은 Cost 즉, 비용(오류)를 최소화하는 방향으로 학습합니다.

 

이때, 가능한 비용이 적은 부분을 찾는 과정이 최적화(Optimization)이고 Cost(Loss)가 얼마나 있는지 나타내는 것이 Cost Function(Loss Function)입니다. 실제로는 Cost와 Loss의 정의가 조금 다르다고 하지만, 아래에서 부터는 Loss Function으로 용어를 통일하겠습니다.

 

딥러닝에서 해결해야할 문제는 크게 회귀문제, 분류문제로 나눌 수 있습니다. 회귀, 분류에 대한 자세한 설명은 생략하고 바로 Loss Function에 대해 알아보겠습니다.

 

2-1) 회귀문제에서 Loss Function

 

먼저, L1 loss입니다. 예측값과 절대값의 차이형태로 표현됩니다. 

L1 Loss Function

다음으로  L2 loss 입니다. 일반적으로 많이 쓰이고, 회귀분석에서도 쉽게 볼 수 있었던 MSE입니다.

L2 Loss Function

공통점

절대값, 제곱의 형태로 오차를 양수로 제한 하였습니다.

 

차이점

오차값의 크기를 증가시키는 정도가 다릅니다. L2 Loss는 제곱의 형태이기 때문에 0~1사이 값을 더욱 작게, 1이상의 값을 더욱 크게 해줍니다. 즉, outlier의 영향을 줄이고 싶으면 L1 Loss를 이용해야합니다.

하지만 일반적으로 L2를 많이 사용합니다.

 

2-2) 분류문제에서 Loss Function

 

교차 엔트로피 오차(CEE : Cross Entropy Error)

 

CEE

t_k는 원 핫 인코딩된 정답 레이블입니다. 즉, [0,0,0,0,1,0] 이런식으로 인코딩 되어 있기 때문에 실제로는 정답레이블에 

-logy_k를 곱한 형식입니다.

 

-log(y)

분류모델에서 출력은 0~1사이 이므로 -log(y)는 위와 같습니다. 즉 정답이 1이라고 했을때 오차가 거의 0에 수렴하고, 0에 가까워지면 오차가 기하급수적으로 증가합니다. 즉, 오답을 맞추면 큰 패널티를, 정답을 맞추면 적은 패널티를 준다고 볼 수 있습니다.

 

3. Loss Function에 대해서 알았는데 대체 무얼 어떻게 학습하는 걸까?

위 질문에 대한 대답은 "가중치"를 학습시키는 것 이라고 할 수 있습니다. 아니, 가중치를 학습시키는 것이 딥러닝의 전부입니다.

Gradient Descent

좌변의 세타는 업데이트 될 가중치,

우변의 세타는 업데이트 이전의 가중치

알파는 Learning Rate로 HyperParameter입니다. 알파의 크기에 따라 가중치를 얼마나 학습할지 즉, Step Size를 결정할 수 있습니다. Learning Rate의 크기가 너무크면, Gradient가 발산할 수 있고 너무 작으면 수렴속도가 너무 느리다는 문제가 있습니다. 즉, 적당한 값을 주어야합니다.

J는 Loss Function 입니다.

Learning Rate가 보폭의 크기라면, Loss Function의 미분값은 방향을 지정해준다고 생각하면 됩니다.

아래 2차함수 그래프에서 원점보다 좌측이면 Loss Function의 미분값이 음수로 결국 가중치 세타는 양의 방향으로 업데이트 됩니다.(결국 minimum을 향해 나아가는 형국) 우측일때는 그 반대 작용이 일어나겠죠.

 

그러면 Loss Function의 미분값은 어떻게 구할 수 있을까요? 이는 뒤에 나올 BackPropagation에서 설명하겠습니다.

 

Convex Function을 가정했을때 위와 같이 f(손실함수)를 최소값을 가지도록 x를 최적화 시켜나가는 과정이라고 보면 됩니다. 실제 Problem Space는 훨씬 복잡하겠지만 이차함수를 떠올리면 직관적으로 이해할 수 있습니다.

 

 

Learnig Rate의 크기에 따른 함수 최적화의 문제점

 

4. 그러면 미분이 가능해야하잖아 어떻게 미분할건데?

기존 Perceptron은 뉴런의 전기신호를 모방한것이기 때문에 0과 1을 가지는 Step Function을 Activation Function으로 이용했습니다. 가중치의 학습을 위해서는 미분이 필요했는데 Step Function은 미분이 불가능하다는 문제가 있습니다.

 

아래 그래프 검은선과 같이 Step Function은 미분이 불가능한 점이 있습니다. 그래서 각 레이어에 Activation Function을 미분이 불가능한 Step Function 대신 미분가능한 함수인 Sigmoid Function(통계학에서는 Logistic이라고 합니다.)을 걸어줍니다.

 

Sigmoid로 미분 불가능하다는 문제가 있지만 Sigmoid또한 문제점이 있었습니다. 각 극값으로 가면 미분값이 매우 작아지는 현상(Gradient Vanishing)이 일어납니다.

step function과 sigmoid function

 

그래서 등장한것이 RELU입니다. Sigmoid 처럼 0에서 1사이로 출력값이 제한되지도 않고, 0 이상일 때 일정한 기울기를 가지고 있어 Gradient Vanishing 문제도 해결했습니다.

여기서 더 나아가, RELU는 0 이하 값에서 기울기가 0이므로 이 정보를 이용해보자는 생각에서 Leaky ReLUPReLU등의 Activation Function이 등장했습니다. 하지만 ReLU와 큰 차이는 나지 않고 그냥 상황에 따라(?) 쓰면 된다고합니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5. 그럼 Loss Function의 미분값을 어떻게 구하지??

이 질문에 대한 대답이 그 유명한 Backpropagation(오류역전파법)과 이어집니다.

오류역전파는 딥러닝의 발전에 지대한 영향을 끼쳤습니다.

 

다시 원론으로 돌아와서, 딥러닝은 어떻게 수행되고 딥러닝은 무얼 하는 건가요?

다시 말하지만 딥러닝은 "가중치"를 업데이트 시켜가면서 최적의 "가중치"를 찾아 오류를 최소화 시키는 방향으로 학습하는 작업입니다.

 

이에 따라 필요한 작업은 가중치에 변화를 주었을때, Loss Function이 어떻게 변화하는지 -> 즉, 가중치에대한 Loss Function의 미분 값이 필요합니다.

 

다시 Gradient Descent를 상기해봅시다.

Gradient Descent

가중치를 위와 같은 식에서 가중치를 업데이트 하기 위해서 우변의 J의 미분값 즉, 세타에 대한 Loss Function의 변화량을 알면 됩니다.

 

여기서 등종하는것이 Backpropagation(오류 역전파법)입니다.

 

오류역전파법은 Chain Rule을 기반으로 하고있습니다.

Chain Rule은 특별한 것이 아니라, 고등학교때 배운 합성함수의 미분(의 확장?)입니다.

 

www.youtube.com/watch?v=aUd2MKLvDsc&list=WL&index=1&t=1257s

자세한 계산 과정은 위 선생님이 알려주신 것이 이해가 잘되었습니다.

이과수학을 하신분이라면 어렵지않게 이해할 것이라고 생각합니다.

 

6. Gradient Descent에 대해 잘 알았는데.. 데이터가 커지면 너무 느린데 어떻게 해야하지?

 

위에서 여러번 보여드렸던 Gradient Descent(경사하강법)의 식은 가장 기본적인 Optimizer입니다. 실제로는 더 빠르고, 성능이 좋은 Optimizer가 여러가지 있습니다.

 

흔히 Optimizer의 수행과정을 "산에서 길 잘찾기"에 비유하고는 합니다. 실제로 상당히 유사한 면이 많습니다. Problem Space는 굉장히 복잡합니다. 

Local Minimum에 빠지지 않으면서도 빠른 속도로 최적값에 수렴시키기 위해 다음과 같이 Optimizer가 발달해왔습니다.

 

아래 이미지는 Optimizer의 계보를 잘 정리해놓았습니다.

수식은 생략하겠습니다. Optimizer에 대해 깊이있게 공부하시고 싶으신 분은 논문이나 웹서칭을 이용하시길 바랍니다..

또한 용어를 많이 혼용해서 쓰기 때문에 다른 블로그나 참고자료와 다를 수 있습니다. 참고해서 보시길!

 

datascience.stackexchange.com/questions/53870/how-do-gd-batch-gd-sgd-and-mini-batch-sgd-differ/53884

 

How do GD, Batch GD, SGD, and Mini-Batch SGD differ?

How do these four types of gradient descent functions differ from each other? GD Batch GD SGD Mini-Batch SGD

datascience.stackexchange.com

 

GD (Gradient Descent)

 

최초에는 Gradient Descent를 사용하였으나 모든 데이터를 확인하고 가기 때문에 너무 느립니다. 또한 Step Size가 일정하기 때문에 Local Minimum에 빠질 염려도 많습니다. 

 

SGD (Stochastic Gradient Descent)

 

데이터를 하나씩 전부 확인하기 힘드니, 하나의 데이터만 가지고 확인을 합니다. Gradient Descsent와 다르게 정확한 답을 내지 못할 수도 있습니다. 

 

sgd vs gd

하나의 데이터에 대해서만 체크하기때문에 SGD는 뒤죽박죽입니다. 반면 GD는 모든 데이터를 확인하며 가기때문에 느리지만, 확실한 방향으로갑니다(물론 GD는 local minimum에 빠질 염려가 있습니다)

 

정리하자면

GD : 확실하지만 천천히 모든 데이터를 훑고간다! (+ Local Minimum에 빠질 염려가 있음)

SGD : 조금 헤매지만 빠르게 간다! (+ GPU를 충분히 활용할 수 없음)

 

Mini-Batch SGD

이 부분에 용어 혼동이 있습니다. 최초의 SGD는 하나의 데이터를 이용해서 Weight를 업데이트 시켜나가는 방식이었는데, 하나는 너무 불확실 하니 Mini-batch로 잘라서 Stochastic Gradient Descent를 수행하는 겁니다. 쉽게말해 GD와 SGD의 장점만 뽑아 쓴 느낌입니다.

 

Momentum

 

Momentum vs SGD

관성으로 이해하면됩니다.

 

local minima와 global minima

Gradient Descent는 일정한 Step size(learning rate)를 가지기 때문에 local minima에 빠질 염려가 큽니다. 즉, global minima에 수렴하지 못하고 local minima에 수렴하게된다는 것입니다.

Momentum을 이용하면 관성을 이용해 local minima에서 나올 수 있는 확률이 높아지고, 속도 또한 빨라집니다.

 

즉, 

- 속도의 향상

- Local Minima 문제 해결

두 가지 장점을 가집니다.

 

대신 메모리는 2배로 필요하게 됩니다.

 

NAG(Nesterov Accelerated Gradient)

 

Momentum과 크게 다르지는 않습니다. 차이점은 Momentum Step을 이미 이동했다 생각하고 Gradient를 구합니다.

일단 Momentum으로 이동을 반정도 한 후 이동방식을 결정하기 때문에 적절한 시점에 제동을 걸기 좋습니다.

 

Adagrad(Adaptive Gradient)

 

지금까지는 Learning Rate가 고정되어있었습니다. AdaGrad를 문자그대로 해석하면 "적응하는 그레디언트"입니다.

핵심 아이디어는 "지금까지 변화하지 않은 변수들의 Step Size는 크게, 많이 변화했던 변수들은 Step Size를 작게"하는 것입니다. 

이렇게하면 더 빠르고 정확하게 Global minima를 향해 나아갈 수 있을 것입니다.

 

그런데, 학습을 여러번 반복하면 Learning Rate가 점점 작아지는 문제가 있습니다.

 

RMSProp

학습을 여러번 반복하면 Learning Rate가 점점 작아진다는 AdaGrad의 문제점을 보완하기 위해 나온 Optimizer입니다. Adaptive를 위한 변수인 G가 무한정 커지지는 않으면서 최근 변화량 변수간의 상대적인 차이는 유지해준다고 합니다.

 

Adam(Adagrad + Momentum)

Optimizer의 '거의' 끝판왕이라 할 수 있습니다.

말그대로 Adagrad의 성질에 Momentum성질을 더해주었습니다.

 

비슷하게 NAdam이 있는데, NAdam은 Adagrad성질에 NAG의 성질을 더해주었습니다.

 

7. 열심히 학습시켰더니.. 뭐? 과적합??

머신러닝(딥러닝)에서 Overfitting은 정말 중요한 이슈입니다.

학부교육과정에서도 그 중요성을 인지했고 여러번의 데이터 분석/모델링 관련 경진대회와 공모전에서 오버피팅 이슈를 피해가기위해 노력했습니다.

 

Underfitting, good Fitting, overfitting

일반적인 방법으로는 3-hold Validation, Cross-validation, early stopping 등.. 다소 모델 외적인 요소로 오버피팅을 방지하곤 하는데 뉴럴 네트워크에서는 나름대로의 방법이 또 있습니다.

 

너무 구체적으로 다루지는 않겠습니다...

 

Regularization

 

L1, L2 규제 방법이 있습니다. 통계학을 전공하신 분이라면 Lasso와 Ridge에 대해 들어보셨을텐데 이와 관련된 내용입니다.

 

- L1 Regularization(Lasso)

Cost Function에 Lasso 규제항을 더해주는 형식입니다.

계속해서 특정상수를 빼주는 꼴이 되고 어떤 Weight는 0이 되도록 합니다.

즉, 영향이 큰 핵심 feature들만 학습과정에 반영하게되어 Overfitting을 방지할 수 있습니다.

 

- L2 Regularization(Ridge)

Lasso처럼 일부 항을 0으로 만들어 버리지는 않지만, 전체적인 Weight의 절대값을 감소시켜 덜 구불구불한(달리 말하면, Smooth한) 곡선을 만들어냅니다.

위 Fitting그림을 다시 상기해보면, 너무 Train데이터에 대해 구불구불하면 Overfitting되어있다고 판단할 수 있습니다.

 

결론적으로 L1, L2 Regularization으로 입력차원을 낮춰주고, Overfitting을 방지할 수 있습니다.

 

Dropout

은닉층의 노드를 전부 사용하지않고, 랜덤하게 몇개를 선택해서 사용합니다.

Dropout
Visualize Effect of Dropout 

blog.naver.com/PostView.nhn?blogId=laonple&logNo=220818841217&categoryNo=0&parentCategoryNo=0&viewDate=&currentPage=1&postListTopCurrentPage=1&from=postView

 

[Part Ⅵ. CNN 핵심 요소 기술] 2. Dropout [1] - 라온피플 머신러닝 아카데미 -

Part I. Machine Learning Part V. Best CNN Architecture Part VII. Semantic Segmen...

blog.naver.com

Dropout은 위 블로그를 참고하였습니다.

 

Hidden Layer가 많아질수록 Overfitting의 가능성이 높아집니다.

 

- Dropout을 사용하면 뭐가좋지?

Overfitting을 방지합니다.

뉴런들끼리의 Co-adaption을 방지할 수 있습니다.

 

원리와 용어에 대한 자세한 설명은 생략하겠습니다...

 

8. 데이터간 단위차이가 너무커서 효율적인 학습이 안되는데 어쩌죠 이거

 

모든가중치에 대해 동일한 상수값(Learning Rate)이 적용되기 때문에 입력데이터의 범위를 동일화 해줄 필요가 있습니다.

즉, 딥 뉴럴네트워크의 효율적인 학습을 위해 정규화(Normalization)는 필수 입니다.

 

9. Network의 각 층과 Activation 마다 input의 분포(distribution)이 달라지는 현상을 해결해보자.

 

Training 전체 과정을 안정화 시키기 위해 Batch Normalization을 이용합니다.

 

Internal Covariacne Shift 현상은 Netwrok 각 층과 Activation 마다 input의 distribution이 달라지는 현상을 의미합니다. 쉽게 생각하면 input을 normalize하면 되는데 Whitening으로 해결 할 수 있습니다. 

 

근데 문제는 Whitening을 하기 위해서는 Covariacne Matrix와 inverse의 계산이 필요해 계산량이 상당히 필요하고,

일부 Parameter들의 영향이 무시되는 경향이 생깁니다. 

 

이 문제를 해결하기 위해 나온것이 Batch Norm입니다.

 

Batch Norm의 장점은

- 기존 Deep Neural Net에서는 Learning Rate를 높게 잡으면 Graidient explding/vanishing 그리고 local minima에 빠지는 문제가 있었는데 Batch norm을 이용하면 propagation과정에서 parameter scale에 영향을 받지 않을 수 있습니다. 그래서 큰 Learning Rate를 잡을 수 있고 이는 빠른 학습을 가능케 합니다.

 

Batch Normalization의 경우 자체적인 regulariztion(규제)효과가 있습니다. 이는 기존의 다른 regularization term을 제거할 수 있게 합니다.(예를들어 Dropout을 없애도 됨)

 

 


여기까지 딥러닝, DNN(Deep Neural Network)의 정리였습니다.

 

이렇게 전체적인 Flow만 잡는데도 양이 방대한데, 수식으로 끄적일 생각하니까 끔찍하긴 합니다. ㅎㅎ

지금생각해보면 조금 나눠서 작성해봤으면 더 좋았을 것 같다는 생각도 들지만, 다른 블로그 보면 이거조금 저거조금 그리고 더 자세하고 깊게 정리를 많이 해놓으셨길래 글 하나에 전체적인 Flow를 담고 싶었습니다.

 

이부분을 정리하는데도 많은 부분을 생략했고, 더 나아가 딥러닝은 알아야할 부분이 훨씬 많습니다.

예를들면 CNN, RNN, LSTM, GAN과 이에 파생된 모델들.., 강화학습, 그리고 구체적인 수식과 과정 , XAI 등..

 

아무튼 저처럼 딥러닝 이론 전반에 대해 빠르게 정리하고싶으신 분들이 읽으시면 좋겠구 도움이 되었으면 좋겠습니다.

 

빠진 내용이나 오류에 대해서는 댓글로 피드백 부탁드립니다!