자연어 처리 - 딥 러닝을 이용한 자연어 처리 입문(13) _ 딥러닝
08. 딥 러닝(Deep Learning) 개요
위키독스
온라인 책을 제작 공유하는 플랫폼 서비스
wikidocs.net
- 기본 구조 : 인공 신경망(Artificial Neural Network)
- 초기 신경망(퍼셉트론), 피드 포워드 신경망 언어 모델, 기본적인 케라스 사용법
1) 퍼셉트론(Perceptron)
- 딥 러닝 : 인공 신경망을 복잡하게 쌓아 올린 방법
- 퍼셉트론 : 초기 인공 신경망
1. 퍼셉트론(Perceptron)
- 다수의 입력으로부터 하나의 결과를 내보냄
- 뉴런과 유사 : 가지돌기(신호) ----(일정치 이상의 크기라면)"신호"----> 축삭돌기
- x : 입력값, W : 가중치(축삭돌기 역할), y : 출력값(인공 뉴런)
- 가중치↑ --> 입력값의 중요도↑
- 계단 함수 : x1W1+x2W2+ ... + xnWn > 임계치(threshold)이면 1을 출력하고 아니면 0을 출력함
- 편향 : 퍼셉트론의 입력으로 함께 사용되며 입력값1에 가중치 b가 곱해진 형태이다.
- 활성화 함수(Activation Function) : 출력값을 변경시키는 함수 like 계단 함수, 시그모이드 함수, 소프트맥스 함수
2. 단층 퍼셉트론(Single-Layer Perceptron)
- 단층 퍼셉트론 : 값을 보내는 단계(입력층_input layer) + 값을 받아서 출력하는 단계(출력층 _ output layer)
- AND, NAND, OR 게이트 쉽게 구현 가능 :
두개의 입력값(x1, x2)와 하나의 출력값(y) + 두개의 가중치(w1, w2)와 하나의 편향(b) --> 각 게이트의 동작 구현
EX> AND 게이트의 단층 퍼셉트론 식
EX> NAND 게이트의 단층 퍼셉트론 식
EX> OR 게이트의 단층 퍼셉트론 식
EX> XOR 게이트 : 단층 퍼셉트론으로 구현이 불가
- 입력값 두개가 서로 다른 값 --> 1 / 입력값 두개가 서로 같은 값 --> 0
- 단층 퍼셉트론의 성질 : "직선" 하나로 두 영역(0/1)을 나눌 수 있는 문제에 대해서만 구현 가능
--> "선형 영역"에 대해서만 분리 가능 --> 다층 퍼셉트론 필요
3. 다층 퍼셉트론(MultiLayer Perceptron, MLP)
- XOR : 기존의 AND, NAND, OR게이트의 조합 = 퍼셉트론의 층을 더 쌓으면 만들 수 있음.
- 다층 퍼셉트론(MLP) : 입력층 + 은닉층(hidden layer) * N(1개 이상) + 출력층
- 심층 신경망(Deep Neural Network, DNN) : 은닉층이 2개 이상인 신경망
- 학습(training) 단계 : 기계가 가중치를 스스로 찾아내도록 자동화 - 손실 함수(Loss function)과 옵티마이저(Optimizer)를 사용
- 딥 러닝(Deep Learning) : 학습 시키는 인공신경망이 "심층 신경망"인 경우!!
2) 인공 신경망(Artificial Neural Network) 훑어보기
1. 피드 포워드 신경망(Feed-Forward Neural Network, FFNN)
- 피드 포워드 신경망 : 입력층에서 출력층 방향으로 연산이 전개되는 신경망 = 순방향 신경망
- 순환 신경망(Recurrent Neural Network, RNN) : 은닉층의 출력값을 출력층으로도 값을 보내지만 동시에 다시 은닉층의 입력으로 사용 --> 09. RNN 챕터
2. 전결합층(Fully-connected layer, FC, Dense layer)
- 전결합층(FC) : 어떤 층의 모든 뉴런이 이전 층의 모든 뉴런과 연결돼 있는 층 = 밀집층(Dense layer)
--> keras : Dense()
- 전결합 피드 포워드 신경망(Fully-connected FFNN) : 전결합층만으로 구성된 피드 포워드 신경망
3. 활성화 함수(Activation Function)
- 활성화 함수 : 은닉층과 출력층의 뉴런에서 출력값을 결정하는 함수
- 단일 퍼셉트론의 계단함수도 여기에 포함
(1) 활성화 함수의 특징 - 비선형 함수(Nonlinear function)
- 선형 함수 :
출력이 입력의 상수배만큼 변하는 함수(직선 1개로 그릴 수 있음)
은닉층을 쌓을 수 없음(여러번 추가해도 1회 추가한 것과 같음) --> 능력 향상 불가
**선형층(linear layer) =투사층(projection layer) : 선형 함수를 사용한 층
f(x) = Wx + b
- 비선형 함수 : 직선 1개로 그릴 수 없는 함수(ex> 계단 함수)
**비선형층(nonlinear layer) : 일반적인 은닉층. 선형층과 비교하기 위한 용도
(2) 계단 함수(Step function)
(3) 시그모이드 함수(Sigmoid function)와 기울기 소실
- 과정 :
순전파(forward propagation) 연산 --> 손실함수 : 예측값, 실제값의 오차 --> 기울기(gradient) --> 역전파(back propogation)
- 기울기 소실 문제 :
역전파 과정에서 0에 가까운 아주 작은 기울기 곱해짐 --> 앞단에 기울기 전달↓(출력층과 먼 은닉층)
--> 매개변수 W의 업데이트 X
즉, 은닉층에서 사용하는 것은 지양
(4) 하이퍼볼릭탄젠트 함수(Hyperbolic tangent function)
: 입력값을 -1~1의 값으로 변환
- 기울기 소실 문제 있음 BUT 0이 중심이므로 반환값의 변화폭이 더 큼!!ㅜ --> 기울기 소실 증상 적음
(5) 렐루 함수(ReLU)
- 인공신경망에서 가장 많이 쓰임
- 수식 : f(x) = max(0,x)
- 깊은 신경망에서 더 잘 작동 : 특정 양수값에 수렴X
- 연산이 아닌 단순 임계값 --> 연산 속도 빠름
- 입력값이 음수 --> 기울기도 0 --> 죽은 렐루
(6) 리키 렐루(Leaky ReLU)
- 죽은 렐루를 보완하기 위한 변형함수
- 입력값이 음수 --> 0.001과 같은 매우 작은 수 반환
- 수식 : f(x) = max(ax, x) a - 하이퍼파라미터_Leaky 정도를 결정.(default : 0.01)
- 새지만 죽지는 않음
(7) 소프트맥스 함수(Softmax function)
- 분류 문제 : 로지스틱 회귀와 소프트맥스 회귀를 "출력층"에 적용
- 특히 다중 클래스 분류 문제
4. 행렬의 곱셈을 이용한 순전파(Forward Propagation)
EX> 케라스로 만드는 인공신경망 : 4 - 8 - 8 - 3
#Forward Propagation
from keras.models import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Dense(8, input_dim = 4, init = 'uniform', activation= 'relu'))
#입력층 : 4, 은닉층:8, 활성화 함수는 relu
model.add(Dense(8, activation = 'relu')) #8인 은닉층 추가, relu
model.add(Dense(3, activation = 'softmax')) #3인 출력층 추가, softmax
- 입력층 ~ 출력층까지 순차적으로 인공신경망의 층 한층씩 추가함.
- 순전파(Forward Propagation) : 인공신경망에서 입력층에서 출력층 방향으로 연산을 진행하는 과정
= 주어진 입력으로부터 "예측값"을 계산하는 과정 = 벡터, 행렬 연산이 층마다 적용
- keras : 내부에서 해줌 / Numpy : 행렬크기 고려 필요
(1) layer 1의 행렬 크기 추정
- (입력행렬) X (가중치 행렬) 가정 & 배치크기 = 1
(2) layer2와 layer 3의 행렬 크기 추정하기
- 위와 같은 과정 반복
- 활성화 함수는 행렬 크기에 영향X
**순전파 진행 --> 오차 계산(예측값VS실제값) --> 가중치, 편향 업데이트(역전파 __ 순전파와 반대로 진행)
**참고 : https://www.youtube.com/watch?v=UJwK6jAStmg
3) 딥러닝의 학습방법
- 손실함수, 옵티마이저의 개념과 딥 러닝에의 적용
1. 순전파(Forward Propagation)
: 입력층에서 출력층의 방향으로 예측값의 연산 진행
2. 손실 함수(Loss Function)
: 실제값과 예측값의 차이를 수치화 = 오차
- 오차↑(너무 낮은 확률 or 너무 높은 확률) --> 손실함수 값↑
- 회귀 : 평균제곱오차(MSE) / 분류 : 크로스엔트로피(이진/다중클래스)
- 손실함수 값 최소화 방향으로 W, b 찾아가기
3. 옵티마이저(Optimizer)
- 손실함수의 값을 줄여나가는 방법
- 배치(Batch) : 가중치 등의 매개변수 값을 조정하기 위해 사용하는 데이터의 양(전체 or 일부)
(1) 배치 경사 하강법(Batch Gradient Descent)
- 오차를 구할 때 "전체 데이터"를 고려
- 1번의 에포크에 모든 매개변수 업데이트 한번에 수행 --> 시간, 메모리↑ / 글로벌 미니엄 찾을 수 있음
model.fit(X_train, y_train, batch_size=len(trainX)) #trainX 사이즈만큼 전부
(2) 확률적 경사 하강법(Stochastic Gradient Descent, SGD)
- "랜덤으로 선택한 하나의 데이터"에 대해서만 계산
- 시간, 메모리↓ / 정확도↓, 변경폭의 불안정성
model.fit(X_train, y_train, batch_size= 1)
(3) 미니 배치 경사 하강법(Mini-Batch Gradient Descent)
- "정해진 양의 데이터"에 대해서만 계산
- 전체보다는 빠르고 SGD보다는 안정적
model.fit(X_train, y_train, batch_size=32)
(4) 모멘텀(Momentum)
- 관성을 더 해줌
- SGD에서 계산된 접선의 기울기에 한 시점 전의 접선의 기울기값을 일정한 비율만큼 반영
--> 로컬 미니엄 도달하였을 때 기울기 0이라서 끝나지 않고 글로벌 미니엄으로 갈 수 있는 가능성!!
keras.optimizers.SGD(lr = 0.01, momentum = 0.9)
(5) 아다그라드(Adagrad)
- 각 매개변수에 서로 다른 학습률 적용(변화가 많음 --> 학습률↓)
keras.optimizers.Adagrad(lr = 0.01, epsilon = 1e-6)
(6) 알엠에스프롭(RMSprop)
- 아다그라드의 단점 개선 : 나중에 학습률이 지나치게 떨어짐 --> 다른 수식으로 대체
keras.optimizers.RMSprop(lr = 0.001, rho = 0.9, epsilon = 1e-06)
(7) 아담(Adam)
- 알엠에스프롭 + 모멘텀 : 방향과 학습률 두가지 모두 잡음
keras.optimizers.Adam(lr = 0.001, beta_1 = 0.9, beta_2 = 0.999, epsilon = None, decay = 0.0, amsgrad = False)
**cf> 옵티마이저 사용법 : https://keras.io/optimizers/
4. 역전파(BackPropagation)
- 위의 경사하강법을 사용하여 가중치를 업데이트하는 과정
(1) 인공 신경망의 이해(Neural Network Overview)
- 입력층, 은닉층, 출력층
- EX> 2 * 입력 + 2 * 은닉층 뉴럭 + 2 * 출력층 뉴런 / 활성화함수 : 시그모이드 함수
z = 이전층의 모든 입력이 가각의 가중치와 곱해진 값들이 모두 더해진 가중합 --> 시그모이드 함수의 입력
h, o = z가 시그모이드 함수를 지난 후의 값
--> 목표 : 역전파를 통해 모든 가중치 W 업데이트!(단, 편향 b는 고려X)
(2) 순전파(Forward Propagation)
- 입력값(파란색) * 가중치 값(빨간색)을 입력층~은닉층 방향으로 계산 한 후 활성화 함수(여기선 시그모이드)에 적용
- 예측값, 실제값의 오차를 손실함수(Loss function)로 계산 --> 여기선 MSE
(3) 역전파 1단계(BackPropagation Step 1)
- 출력층 -> 입력층으로 가중치 업데이트
- 역전파 1단계 = 출력층과 출력층 바로 이전의 은닉층(N층) 사이 가중치 업데이트
- 역전파 2단계 = N층과 N-1층 사이의 가중치 업데이트
- EX> 1단계에서 업데이트 할 가중치 : W5, W6, W7, W8
a. 미분의 연쇄법칙(Chain rule)에 따라 계산 (∂ - 미분기호) :
가중치 W5 업데이트 시
- Etotal = (순전파 진행 결과 나온 전체 오차값)
- 1번째 항 :
- 2번째 항 : (단, 시그모이드 함수의 미분 - f(x)(1-f(x))
- 3번째 항 : (h1 - sigmoid(z1) = sigmoid(W1x1 + W2x2) , z3 = W5h1 + W6h2)
- 결론 : 경사하강법을 통해 가중치 업데이트. 학습률 0.5로!
(4) 역전파 2단계(BackPropagation Step 2)
- 입력층 방향으로 다시 계산 이어감
- EX> 2단계에서 업데이트할 가중치 : W1, W2, W3, W4
- 미분의 연쇄 법칙(Chain rule)이용 :
가중치 W1을 업데이트 시
- 1번째 항
- 2번째 항 : 시그모이드 함수의 미분
- 3번째 항 : z1 = W1x1 + W2x2이므로 W1으로 미분하면 x1
- 결론 : 경사하강법을 통해 가중치 업데이트
(5) 결과 확인
업데이트 된 가중치로 다시 한 번 순전파를 진행 --> 오차 감소 확인!(0.02397190으로 오차 감소!)
4) 과적합(Overfitting)을 막는 방법들
- 과적합(Overfitting) : 훈련 데이터에 대한 정확도는 높지만 새로운 데이터(검증 데이터, 테스트 데이터)에 대해서 제대로 작동 안함 = 훈련 데이터의 노이즈까지 학습 --> 모델의 성능 하락
1. 데이터의 양 늘리기
- 데이터의 양이 적음 : 해당 데이터의 특정 패턴, 노이즈까지 암기 --> 과적합 현상 발생 확률 증가
- 데이터의 양이 많음 : 데이터의 일반적인 패턴 학습
- 데이터 증식/증강(Data Augmentation) : 의도적으로 기존 데이터를 조금씩 변형, 추가 --> 데이터의 양 늘리는 방법
(cf> 이미지 : 이미지 돌리기, 노이즈 추가, 일부분 수정)
2. 모델의 복잡도 줄이기
- 인공 신경망의 복잡도 : 은닉층(hidden layer)의 수, 매개변수의 수 = 모델의 수용력(capacity)
--> 이런 요인들을 통해 복잡도 줄이기
3. 가중치 규제(Regularization) 적용하기
- 복잡한 모델을 간단하게 하는 방법
- L1 규제(L1 노름) : 가중치 w들의 절대값 합계를 비용함수에 추가 = λ |w|
- L2 규제(L2 노름) : 모든 가중치 w들의 제곱합을 비용함수에 추가 = 1/2 * λw^2
(단, λ : 규제의 강도를 정하는 하이퍼파라미터 / 클수록 규제를 위해 추가된 항들을 작게 유지하는 것을 우선시)
- 두 규제식의 비용 함수 최소화 방법 : 가중치 w들이 값이 작아져야 함
EX> L1규제 : 비용 함수 최소인 가중치, 편향 찾기 + 가중치들의 절대값 합도 최소 --> 가중치가 0 또는 0에 가깝게 작아져야!!
--> 작아진 가중치에 곱해진 특성은 영향이 별로 없음
EX> L2규제(= 가중치 감쇠) : 가중치들의 제곱을 최소화 --> 0에 가까워지는 경향
--> 특성별 영향력 판단, 더 잘 동작!!
4. 드롭아웃(Dropout)
- 학습과정에서 신경망의 일부를 사용하지 않는 방법. 드롭아웃 비율만큼은 사용 안함
- "신경망 학습" 시에만 이용. 예측 시에는 이용X
- 특정 뉴런, 조합에만 의존적이지 않도록 하는 효과
- 코드 예시 - Keras
5) 기울기 소실(Gradient Vanishing)과 폭주(Exploding)
- 기울기 소실(Gradient Vanishing) : 깊은 인공 신경망 학습 중 역전파 과정에서 입력층으로 갈 수록 기울기(Gradient)가 점차 작아지는 현상 --> 가중치 업데이트가 X, 최적의 모델 찾기 실패
- 기울기 폭주(Gradient Exploding) : 기울기가 점차 커짐 --> 가중치가 비정상적으로 큰 값, 발산 (순환 신경망 RNN에서 발생)
1. ReLU와 ReLU의 변형들
- 시그모이드 함수 : 입력의 절대값이 클수록 출력값이 0또는 1에 수렴 --> 기울기가 0에 가깝
- 역전파 과정 : 전파 시킬 기울기 점차 사라짐 --> 역전파 전달X
- 완화 방법 : 은닉층의 활성화 함수로 ReLU, Leaky ReLU 이용
2. 그래디언트 클리핑(Gradient Clipping)
- 기울기 값이 임계값을 넘지 않도록 자름 --> 기울기 폭주 저지
- RNN(순환 신경망)에서 유용
- Keras에서의 이용
from tensorflow.keras import optimizers
Adam = optimizers.Adam(lr = 0.0001, clipnorm = 1.) //clipnorm으로 임계값 지정
3. 가중치 초기화(Weight initialization)
- 가중치의 초기값이 훈련 결과에 영향을 주기 때문
(1) 세이비어 초기화(Xavier Initialization) = 글로럿 초기화
- 이전 층의 뉴런 개수(nin)와 다음 층의 뉴런 개수(nout)를 가지고 식을 세움
- (경우1) 균등 분포(Uniform Distribution)로 초기화
- (경우2) 정규 분포(Normal Distribution)로 초기화
- 효과 : 여러 층의 기울기 분산 사이에 균형 맞춤 --> 특정 층이 주목/뒤쳐지는 것 막음
- 단점 : 시그모이드, 하이퍼볼릭 탄젠트(S자형)엔 좋지만 ReLU, ReLU변형함수에는 안 좋음
(2) He 초기화(He initialization)
- 다음 층의 뉴런의 수를 반영X
- (경우1) 균등분포로 초기화
- (경우2) 정규분포로 초기화
4. 배치 정규화(Batch Normalization)
- 인공 신경망의 각 층에 들어가는 입력을 평균과 분산으로 정규화
(1) 내부 공변량 변화(Internal Covariate Shift)
- 공변량 변화 : 훈련 데이터의 분포 ≠ 테스트 데이터의 분포
- 내부 공변량 변화 : 층 별로 입력 데이터 분포가 달라지는 현상
(이전층의 가중치 업데이트 --> 현재 층의 입력데이터 분포가 학습시점과 달라짐)
(2) 배치 정규화(Batch Normalization)
- 한 번에 들어오는 배치 단위로 정규화
- 각 층의 활성화 함수를 통과하기 전에
- 과정 : 입력에 대해 평균 0으로 정규화 --> 스케일(γ), 시프트(β) 수행
- 수식 : BN(배치 정규화)
- 장점 :
- 단점, 한계:
● 모델을 복잡화(추가 계산 요구) --> 예측 실행 시간이 느려짐
● 미니 배치 크기에 의존적 : 너무 작은 배치 크기 --> 동작X
● RNN 적용 어렵 : 각 시점(time step)마다 다른 통계치 --> 적용 어렵
<--> 보완 : 층 정규화(layer normalization)
5. 층 정규화(Layer Normalization)
- 배치 정규화
- 층 정규화