본문 바로가기
연구실/인공지능(Coursera)

[AI 5주차] Deep learning의 실용적인 측면

by whiteTommy 2024. 7. 2.
반응형

 Train / Dev / test sets

모든 data를 가져와서 이를 training set, validation set, test set으로 나누고 training set를 사용해서 training을 하고, validation set에서 다양한 모델 중 가장 성능이 좋은 모델을 체크한다. 이러한 과정을 충분히 수행한 후 evaluate하고 싶은 최종적인 모델이 있을 때, test set을 사용해서 evaluate할 수 있다.

  

여기서 주의할 점은 각각의 data set의 distribution이 일치해야된다는 점이다.

 

사용자가 많은 사진을 업로드할 수 있는 application을 만들고 있고, 사용자에게 보여주기 위해 고양이 사진을 찾는 것이 목표라고 해보자.

 

training set은 web page에서 수집한 많은 사진이 있을 수 있지만, validation set과 test set은 application을 사용하는 사용자로가 업로드한 사진이다. 많은 web page에는 해상도가 높고 전문적이며 퀄리티가 좋은 사진이 만연해있지만, 사용자가 업로드한 사진은 평범한 핸드폰으로 촬영한 해상도가 상대적으로 낮은 사진, 퀄리티가 좋지 않은 사진이 대부분인 경우가 많다. 따라서 data의 distribution이 다를 수 있다.

 

즉, data에서 training set와 dev / test set이 같은 distribution에서 온 것인지 확인을 해야 한다.

 

Bias & Variance

  • Bias : 예측 값과 실제값의 차이의 평균이다. 이 값이 크면 예측값과 실제 값의 차이가 크다는 것을 의미한다. 수식은 아래와 같다. 이에 대한 수식은 아래와 같다.

 

  • Variance : 다양한 데이터 셋에 대해서 예측값이 얼만큼 변화할 수 있는지에 대한 양의 개념이다. 이에 대한 수식은 아래와 같다.

 

Train Set Error 1% 15% 15% 0.5%
Dev Set Error 11% 16% 30% 1%
  low bias
(overfitting)
high bias 
(underfitting)
high bias & 
high variance
low bias & low variance

 

training set error 가 낮다는 것은 bias 가 낮다는 것을 의미하며 이에 비해 validation set error 가 상대적으로 높다는 것은 test set 에 overfitting 되고 있다는 의미이다. 반면에, training set error 가 높다는 것은 bias 가 높아서 학습이 추가적으로 필요하며 underfitting 되고 있다는 의미이다.

 

bias와 variance 값 모두가 낮아지도록 모델을 설계하는 것이 목표이다. 하지만 Deep learning 이전 시대에는 bias나 variance 중 하나의 값만 조절하는 tool 이 부족해서 bias 를 낮추면 variance 가 증가하고, variance 를 낮추면 bias 가 증가하는 bias variance trade-off 가 있었다. 

 

하지만, deep learning 시대에는 다른 것에 영향을 주지 않고 하나만 줄이는 tool 이 많아져서 trade-off 문제가 해결이 되었다. 

그래서 학습 모델이 높은 bias를 갖고 있는지 우선 확인을 할 필요가 있다. 높다면, network의 hidden layer를 더 deep 하게 쌓거나, unit node 를 늘려서 bigger network 를 만들어야 한다. 

 

이 과정을 반복하여 bias 가 줄어들었다면 이제 variance 가 높은지 낮은지 확인하여 높다면 이를 줄여야 한다.

 

variance 를 줄이기 위해서 data의 양을 늘리거나 regularization 을 해야 한다.

 

 

Regularization

: training set 에 과하게 적합하게 되는 overfitting 문제로 인해 cost function이 필요 이상으로 작아지는 문제를 방지하기 위해 추가적으로 더해줘서 generalization performance를 늘려주는 정규화 방식이다. 이는 2가지 방식이 있다. 여기서 사용되는  λ (lambda) 는 regularization parameter 이다.

  • L1 regularization 

L1 정규화를 통해 w는 희소행렬이 될 것이다.  w 벡터 원소에 많은 0 값이 들어간다는 의미이다.  그러면, model 을 저장할 memory가 덜 필요하기 때문에 model  compressing 할 수 있다. 이러한 목적 말고는 실제로 많이 사용되지는 않는다.

 

  • L2 regularization 

L2 정규화는 실제로 L1 정규화보다 더 많이 사용된다.

 

그렇다면 neural network에서는 L2 정규화가 어떻게 될까? 

 

여기서 w 는 (n^[l] , n^[l-1]) 행렬이기 때문에, 다음이 성립한다.

이를 Frobenius norm 이라고 한다. 

 

그렇다면, 이를 가지고 어떻게 gradient descent 를 구현할 수 있을까?

 

이전에 계산한 식에서 추가적으로 더해주기만 하면 된다. 이후 업데이트 과정은 동일하다. 첫번째 식을 두번째 식에 대입해서 이를 풀어서 쓰면 다음과 같다.

여기서 w^[l] 로 묶으면 (1-  ( α* λ) /m ) 이기 떄문에 이 값은 1보다 작아서 weight decay 라고 불린다.

 

L1 정규화는 미분을 했을 때, weight update 과정에서 상수를 빼기 때문에 weight의 특정 원소가 0이 되는 회소 행렬이 되며 이는 weight가 높은 feature 가 selection 되는 효과를 얻는다. 반면에, L2 정규화는 미분을 했을 때, 정리를 하면 weight update 과정에서 전체 weight 가 같은 비율로 감소하기 때문에 0이 되지 않는 차이점이 있다. 

 

즉, regularization을 통해 weight 가 0에 가까워지면 neural network 의 complexity 가 감소해서 overfitting 을 막을 수 있다. 아래와 같이 neural network 가 작아지고 단순해진다.

 

λ 가 커지면, w^[l] 은 작아지기 때문에, z^[l] 도 값도 작아진다. 즉, z 값이 작은 범위에서 존재하므로 tanh activation function의 경우 linear 에 근사하여 전체 network 도 linear 하게 되어 model 이 simple 해진다.

 

 

Dropout Regularization

각각의 layer를 0.5 확률로 제거한다고 하자. 그러고 나서, 제거된 노드를 기준으로 들어오고 나가는 edge를 지운다.

 

제거된 더 작은 network 로 training 을 하는 방식이 Dropout Regularization 이다. 

 

dropout 구현의 한 예제인 Inverted dropout을 살펴보자. 여기서 layer 의 개수는 3으로 하자.

keep.prob = 0.8  # dropout.prob = 0.2
d^[3] = np.random.rand(a^[3].shape[0], a^[3].shape[1]) < keep.prob

d^[3] 는 20%는 0 값을 갖고, 80%는 1 값을 갖는 boolean 행렬이다. 

 

a^[3] = np.multiply(a^[3], d^[3]) # a^[3] *= d^[3]

20%는 0 값을 갖고, 80%는 해당 a의 원소값을 갖는 행렬이다.

 

예를 들어, 3번째 layer의 unit 개수가 50개라면, a^[3] 는 50 x 1 행렬이다. (m training example 이라면 50 x m 행렬) 여기서 80% 확률로 유지가 되고 20% 확률로 dropout이 발생하므로, input 값의 총합(기댓값)이 dropout이 되더라도 유지가 되어야 학습이 안정화가 되기 때문에 keep.prob 으로 나눠준다. 유지가 되지 않으면 loss 값이 예기치 못하게 높아지거나 낮아지는 문제가 발생한다.

a^[3] /= keep.prob

 

dropout 은 L2 regularization 과 비슷한 효과를 가져온다. random하게 특정 node를 dropout하는 상황에서 높은 weight를 갖고 있는 node가 dropout 된다면, 학습이 적절한 방향으로 이루어지지 않기 때문에 weight는 특정 뉴런이 높은 weight를 가져가면 안되고 weight 는 적절하게 퍼져야 하기 때문이다.

 

또한, 각각의 layer에서 dropout이 발생할 확률을 다르게 설정할 수 있다. 중요하다고 판단이 되어서, 특정 layer의 node를 모두 남겨야 하는 노드는 keep.prop을 1.0으로 설정하는 것도 가능하다. 한편, x1,x2,x3 에 해당하는 input layer에서 dropout을 설정할 수도 있는데, 이 경우는 실제로 잘 사용되지는 않는다.

 

Computer Vision에서는 모든 픽셀값을 사용하기 때문에 대부분의 경우 데이터가 부족하다. 따라서 거의 항상 dropout을 사용한다. 그러나 네트워크가 overfitting 문제를 가지기 전까지는 적용하지 않아야 한다.

 

 

Other Regularization Methods

  • Data augmentation : overfitting을 줄이기 위해서 더 많은 data로 학습을 하면 문제를 막을 수 있지만, 비용이 상당할 수 있고, 실제로 수집을 더 하기 어려운 경우도 많다. Data augmentation은 같은 사진을 좌우 대칭시키거나, random 하게 zoom-in 하거나 회전시키는 왜곡의 방식을 사용하 data set을 augment 할 수 있다. 
  • Early Stopping : 반복을 거듭하면 trainin error는 계속 감소하고, validation error는 감소하다가 증가한다. 반복이 많이 진행되면 overfitting이 발생한다. 그래서, validation error가 다시 증가하기 직전에 반복을 조기에 종료시켜주는 방식이다.

 

Normalization Inputs

 

input 의 차원이 2 라고 하자(x1, x2) 아래는 training set의 scatter plot이다.

 

input을 normalize 하는 방식은 2가지 step 을 따른다.

  • subtract mean : training set의 input 의 평균을 input 값에서 빼준다.

  • normalize variance : 평균을 뺀 값에서 표준편차로 나눠준다.

 

 

그렇다면 왜 input을 normalize 해야 할까?

 

input을 normalize하지 않으면 cost function은 다음과 같다.

Gradient descent 과정에서 global miminum 을 찾는 과정이 길어질 수 있다.

 

반면에, input 을 normalize 하면 cost function은 다음과 같다.

 

Gradient descent 과정에서 global minimum 을 찾는 과정이 빨라질 수 있다. 최적화가 용이해진다.

 

 

Gradient Vanishing & Exploding

아래와 같은 DNN 이 있다고 하자. 여기서 activation function 은 linear function 이고, bias 는 0이다.

 

그러면 ŷ  = w^[l] * w^[l-1] * ... * w^[2] * w^[1] * x 이다. 

 

여기서, w^[l] = [1.5 , 0; 0, 1.5] 인 2 x 2 가중치 행렬이라고 할 때,  ŷ = w^[l] * [1.5, 0; 0, 1.5]^(l-1) * x 이므로 ŷ 값이 비정상적으로 커진다. 한편, w^[l] = [0.5, 0; 0, 0.5] 인 2 x 2 가중치 행렬이라고 할 때, ŷ = w^[l] * [0.5, 0; 0, 0.5]^(l-1) * x 이므로 ŷ 값이 아주 작아진다.

 

즉, weight 행렬이 항등 행렬보다 조금이라도 큰 경우에는 activation 이 explode 될 것이고, 반대로 조금이라도 작은 경우에는 activation 이 vanish 될 것이다. 따라서, gradient 도 각각 explode 되고, vanish 된다.

 

 

Weight Initialization for DNN

input 의 차원이 n이라고 할 때 bias 가 0이면 , z = w1x1 +w2x2 + w3x3 + ... + wnxn 이다. 여기서 z가 너무 크거나 작지 않도록 해야 한다. n 이 크면, wi는 작아진다. Var(w) = 1/n 이 되도록 설정하여 w를 작게 만들어줄 수 있다. 

Var(wi) = 1/n
w^[l] = np.random.randn(shape...) * np.sqrt(1/n^[l-1])

 

 

  • He initialization

activation function으로 relu 를 사용하는 경우에는 Var(wi) = 2/n 이 되도록 설정하는게 더 효과가 있다. 

Var(wi) = 2/n
w^[l] = np.random.randn(shape...) * np.sqrt(2/n^[l-1])

 

따라서, activation의 input feature들이 대략 평균 0이고, 표준편차가 1이 돼서 z도 비슷한 scale 를 갖게 될 것이다. 이는 weight가 1보다 너무 크거나 작지 않게 되서 너무 빠르게 explode 되거나 vanish 되는 문제를 줄여준다. 

 

  • Xavier initialization

만약, activation function으로 tanh 를 사용하는 경우에는 상수 2를 사용하는 대신에 1을 사용하는 것이 더 효과가 있다. 

Var(wi) = 1/n
w^[l] = np.random.randn(shape...) * np.sqrt(1/n^[l-1])

# the other formula
w^[l] = np.random.rand(shape...) * np.sqrt(2/(n^[l-1] + n^[l])

 

 

 

 

반응형