EECS 498-007

[EECS 498-007] Lecture 10. Training Neural Networks I

y_unique 2024. 1. 29. 01:14
728x90

어김없이 찾아오는 ~ 

그런데 벌써 금요일이야 

거짓말 같애

시간이 아주 매섭게 훅훅 지나간다 

날씨도 살짝쿵 풀린 것 같지?

초코송이 먹구십다 


오늘은 신경망을 실제로 훈련하는 방법! 에 대해 알아볼테다.

 

섹션을 둘로 나누어 진행할텐데, 이번 포스팅에서도 첫번째에 해당하는 One time setup에 관해 다룰 것이다. 

다음 포스팅에서는 11강인 2, 3에 대해서 써볼게요.

 

[Activation Functions]

활성화 함수는 인공신경망에서 중요한 구성 요소로, 모델에 nonlinearity를 부여하는 역할을 한다. 

기본적으로 활성화함수가 이전 layer의 입력들의 가중 합에 작용한 후 결과를 다음 layer로 전달해주는데, 

이런 활성화 함수가 존재하지 않으면 네트워크가 단일 선형 레이어가 되어 처리 능력이 매우 저하된다.

 

저번 강의에서도 언급했던 활성화 함수 종류들인데 이번엔 더 자세히 다뤄보고자 한다. 

 

먼저 클래식한 아주 많이 만나본 sigmoid이다. 

- Sigmoid

  • S모양의 0-1사이의 확률 값을 가지는 함수
  • 발사 속도에 대한 비선형 의존성을 모델링 해줌
  • 확률적으로 접근하면 odds, odds에 log를 취하면 logit, logit의 역함수가 logistic, logistic이 사실 sigmoid! 
    • 확률의 어떤 값으로 해석할 수 있고, 클래스를 나눌때도 연속적으로 표현이 가능했음. 

problem! 

  • Saturated neurons "kill" the gradients

시작과 끝 부분에 평면 영역이 있어 기울기가 0이 되므로 네트워크를 훈련하는 것에 어려움을 겪게 된다는 문제점이다. 

예를 들어 위와 같이 sigmoid gate가 중간에 있고 함수의 입력이 매우 작거나 큰 경우! (-10 or 10) local gradient가 거의 0에 가까워지게 되어 downstream gradient또한 0에 가까워질 것이다.

(downstream = upstream * local 임을 기억! upstream의 값에 상관없이 local이 0에 가까우면 downstream도 0에 가깝게 될 것!)

그렇다면 이는 학습을 매우 느리게 진행되는 결과를 가져오며 효과적으로 gradient를 update하는 데에 방해가 될 수 있다. 

 

  • Sigmoid outputs are not zero-centered 

만약 neuron의 input들이 모두 positive라면 x가 전부 양수이기 때문에 w에 대한 gradient 또한 모두 양수이게 될 것. 

즉, upstream이 양수라면 모든 w에 대한 gradient는 양수, 혹은 음수라면 w에 대한 gradient도 모두 음수가 된다. 

그래서 만약 2차원에서 두번째 그림에서 오른쪽과 같이 우리가 optimal한 w vector를 가졌다면, 1, 3분면으로만 향할테니 지그재그 형태로 나타나게 될 것이다. 하지만 2차원이 아닌 고차원이라면 모든 w의 차원이 전부 +, 또는 전부 -로만 갈 수 있으므로 제약이 클 것이다. 

그래서 모든 요소들이 positive라면 된다면 문제가 될 것이다! 

 

어떻게 해결할래?

 

-> minibatch를 이용하기!

어떤 data는 전부 positive, 어떤 것은 전부 negative라면 그런것들을 합친다면 적절한 방향을 자유롭게 만들어 질 수 있다. 

 

  • exp() is a bit compute expensive

 

위 식에서 보면 -x에 대한 exponant값을 구해야하는데, 이를 계산하는데에 많은 비용이 든다! 

 

=> 일반적으로 첫번째 문제가 sigmoid에서 가장 큰 문제점이라고 한다! 

 

그래서 이러한 문제를 해결하기 위해 등장한 Tanh! 

- Tanh

  • 범위가 [-1, 1]로 바뀜  (-> sigmoid는 [0, 1]이었음) -> 학습이 빨라지겠지? 
    • 왜? 활성화 함수의 출력범위가 넓을수록 학습이 빠르게 이루어질 수 있는 것이다. -> gradient가 작으면 가중치의 조정이 작게 일어나고 그로인해 학습이 느려진다. 그럼 gradient가 큰게 좋겠다. sigmoid, tanh모두 중앙 부근에서 gradient가 커! 근데 출력범위가 좁은 경우보다 큰 경우가 더 기울기가 크겠지! 그래서 출력 범위가 -1, 1로 확장된 tanh의 경우가 sigmoid의 단점을 보완할 수 있는 것이다. 
  • 평균이 0에 가까워짐 -> zero-centered 
    • 이게 왜 좋아? 출력이 특정 값으로 치우치게되면 gradient가 작아져서 역전파 과정에서 소실될 수 있다 (gradeint vanishing)  그래서 평균이 0에 가까워지면 gradient가 양쪽 방향으로 고르게 분포되어, gradient vanishing의 문제를 해결할 수 있음.   
  •   problem !! 
    • 여전히 saturated된 부분에 gradient가 죽는 부분에 대해서는 해결되지 못했다. -> 해결해야겠찌? 해서 등장한 

- ReLU

  • 양수에서 더이상 saturate 하지않음! 
  • 계산상으로도 항상 효과적임! 음수는 0이고 양수는 그 값 그대로니까! 
  • 실제로 sigmoid나 tanh에서도 6배빠르게 수렴되는 특징이 있음
  • problem 
    • 하지만 sigmoid와 동일하게 zero-centered문제가 남아있음.
    • 음수일 때 gradient가 0이 되는 문제점이 있음. -> 어 근데 장점일 수도 있대 .. 작은 값을 계속 연산하는 것보다 나으니까 

data가 특정 ReLU보다 negative에 다 모여있으면 이 노드는 더이상 활성화되지 않고 모든 뉴런은 0으로 출력될 것이다. -> dead ReLU

그래서! ReLU를 조금이라도 positive하면 좋을 것 같애 

 

-> 

- Leaky ReLU

  • 모든 범위에서 더이상 saturate되지 않음 (음수에서도 0.01을 곱해서 기울기가 존재하도록 해줌) 
  • 이 또한 계산적으로 효과적임
  • 이 또한 6배 빠르게 계산해줌
  • gradient가 죽지않아!!!! 
  • Parametric Rectifier -> 0.01또한 hyperparameter 이므로 이를 학습시켜 learnable parameter로 여겨서 진행! \

그치만 위에 등장한 Sigmoid, tanh, ReLU, leaky ReLU 모두 원점에서 미분이 불가능하다는 문제점을 가지고 있다. 

 

그래서 등장한 친구! 

-ELU

  • ReLU의 모든 장점을 가지고 있다
  • 또한 평균이 0에 가깝고
  • Leaky ReLU에 비해서 noise에 robust하다.
  • problem
    • 하지만 위에서 언급했듯 exponatioal 연산이 요구되어 많은 계산량을 가져야 한다는 점이 단점이다. 

-SELU

*아래 SELU식을 보면 범위의 오타가있다! x>0 경우가 그 값 그대로 출력되도록 바꾸어야 한다. 

  • ELU에서 scale을 진행한 버전! 앞에다가 람다를 곱하고 있음. -> 더 잘 작동됨.
    • SELU는 출력이 특정 평균0과 분산1로 수렴되도록 설계되어있다. x>0에는 입력을 그대로 출력하므로 평균을 따라갈 수 있으며 그렇지 않은 경우에는 지수함수를 포함하여 평균에 가까워지도록 설계되었다. 또한 이 경우에 값이 급격하게 증가하므로 분산도증가하게 되어 입력의 분산을 제어하고 수렴시키는 역할도 하게되기 때문이다.
    • BatchNorm이 없는 경우에도 깊은 SELU를 진행할 시에 self-normalizing하는 효과가 있다.

 

한 아키텍처에 위와 같은 activation function을 다르게 하여 CIFAR10으로 test를 해 본 결과,

위와 같은 성능을 냈다고 한다. 

뭐.. 해석하면 되겠지만! DenseNet 같은 경우 ReLU가 다른 것들과 거의 동일한 성능을 내고 있다. 

 

요약하자면, 

  • 복잡하게 생각할 것 없이, 필요하면 일단 ReLU를 사용하자 
  • 다만, 0.1정도 올리고 싶으면 Leaky ReLU, ELU, SELU, GELU등을 사용하자! 
  • Sigmoid, tanh는 사용하지 말자.. 

다음은 Data Preprocessing 에 대해 알아보자 

[Data Preprocessing] 

  • original data
    • x라고 하는 N x D (N : data의 개수, D : data의 dimention)의 크기인 data를 2차원 공간에 뿌려본 것. 
  • zero-centered data
    • original data를 중심 mean을 기준으로 shift 시킨 것
  • normalized data 
    • 각 축마다 표준편차가 1이 되도록 scale 한 것

 

우리가 앞에서 input이 positive 하다면 weight의 gradient의 방향이 모두 + or -가 됨을 언급했었다. 

그래서 zero-mean data가 필요하다고 결론을 내리기도 했었다.  -> data processing의 작업을 거쳐야 한다. 

 

하지만 실제 x, y의 좌표값자체는  중요하지 않고 적절한 과정을 통해 변환되는데, 

PCA와  Whitening를 사용해야함. 

  • PCA를 통해 diagonal covariance matirx가 되는 즉, decorrelated data의 형태가 되도록 한다. (서로간의 연관성이 없도록) 
    • 연관성? -> 특정 x값일 때, 특정 y값을 가지는 우리가 흔히 아는 그래프의 형태! 가 correlate 상태!                                           두번째 그래프를 보면 그 상관관계가 깨짐! 
  • Whitening을 적용 
    • 각 해당하는 축에 대해 normalize를 적용하는 것. 

근데 왜 이렇게 해 ????

  • normalization을 진행하지 않는다면 -> 약간의 변화에 매우 민감하게 작용하여 optimize 하기 어려울 것! 
    • 빨간색, 파란색을 서로 classifier 하려고 하는 line이 위와 같은 굵은 검은 선일때, linear classifier이므로 어떠한 normal한 벡터가 weight의 matrix로 나타나게 될 것이다. 여기서 기울기 값을 아주 조금만 바꾸어도 값이 달라질 정도로 매우 sensitive하게 반응할 것이다. 
  • normalization을 진행하면 -> weigth의 작은 변화에 대해 덜 민감해! optimize하기 비교적 easy 

실제로 Image에 대해서 Data preprocessing을 진행한 예를 보면, 

CIFAR-10의 [32, 32, 3] 크기를 가진 image data가 있을 때

  • AlexNet
    • 모든 이미지의 평균을 구해 각 데이터해서 평균을 뺀 값으로 mean image를 구함. -> zero-mean의 형태
  • VGGNet
    • 각 채널마다 평균을 구해 뺀 값 
  • ResNet 
    • 각 채널의 평균에 대해서 빼고, 각 채널의 std(표준편차)에서 나눠가지고 normalization 한 것 

뭐 위와 같은 것들이 PCA나 whitening을 적용한 것은 아님! 

 

[Weight Initialization]

-> 가장 초기의 w, b를 설정하는 것을 말함. 

  • 초기값을 전부 W = 0, b = 0으로 한다면 어떻게 될까?
    • output이 전부 0! -> 모든 gradient는 모두 똑같은 값을 갖게 됨. 
     

그래서 일반적으로는 가우시안 분포를 따르는 아주 작은 값의 랜덤 값을 넣어주는데, 

위와 같은 코드를 통해 작성할 수 있다. 그치만 이는 

-> 아주 작은 network에서는 잘 작동해! 그치만 deeeeep한 network에서는 잘 작동하지 않는다고 한다! 

 

실제 실험을 해보면,

dim이 4096이고, 6개의 layers가 있다. 

input x는 random하게 16개를 뽑아낸 뒤 W를 구하고 tanh를 적용시킨다. 

위와 같이 x를 hidden layerㅇ에 넣어주면서 6개의 layers를 통과한 것을 data를 layer마다 뿌려보면

위와 같은 형태가 띌 것이다. 

layer가 쌓일수록 점점 std가 줄어드는 모습 즉, 0으로 수렴해가는 모습을 볼 수 있다. -> W가 바뀌면서 loss도 줄어들 것 

==> 학습이 되지 않는 것을 볼 수 있다. 

 

  • std가 0으로 수렴한다! 는 무슨 뜻인데?
    • 각 레이어에서의 출력 값이 거의 동일한 범위에 위치하게 되는 현상을 나타낸다 -> 각 뉴런이나 레이어의 출력 값들이 거의 동일한 패턴을 갖게된다. 이는 다음 레이어에 전달되는 gradient도 큰 차이가 없다는 것을 의미한다. -> 학습되지 않겠징!

 

0.01이 너무 작아서그런가? -> 좀 더 키워보까?

키웠더니 tanh에 의해서 -1 or 1로 모두 몰려버리는 상황이 발생했다. -> local gradient가 모두 0이 되어 학습이 되지 않음! 

 

그럼어떡해!

 

Xavier Initialization 을 사용해 봐! 

-> 입력과 출력의 개수에 기반하여 가중치를 초기화하는 방법, 초기 가중치를 너무 크게 또는 작게 설정하는 것을 방지해줌 

1/x의 dim의 제곱근의 형태가 std가 되는 형식이다. 

이러한 방식으로 layers를 쌓았을 때,

점점 좋은 형태의 그래프 모양을 띄고있다. 

위는 fully-connected의 경우이고, CNN의 경우!

위와 같은 Din으로 설정해주면 된다. 

 

왜 이런 원리로 사용되느냐! 이론적으로 접근해보자

-> output의 variance와 input의 variance를 갖게 만들어주었기 때문에!

마지막 3번째 식에서 variance of output과 variance of input을 같다고 하면 Var(Wi)는 1/Din가 되므로 오른쪽 상단에 있는 파란색 글씨와 같은, std = 1 / sqrt(Din)로 설정하게 되는 것이다. 

 

이것을 ReLU에다가 적용시켜보자! 

ReLU는 0보다 작은 값은 다 0으로 만들어버리기에 그래프를 보면 왼쪽은 없는 형태로 그려진다. 

더하여 오른쪽 양수의 경우도 layers를 쌓을수록 0으로 수렴하여 학습이 이루어지지 않는 것을 볼 수 있다. 

 

또 해결해야지! -> kaming이라는 알고리즘을 적용해보겠대!

 

Kaming -> MSRA Initialization

std = sqrt(1/Din)가 아닌 sqrt(2/Din)로! 2로 바꾸어주는 것이다.  -> Kaming

코드상 5번째 줄은 오타로, Din/2로 수정해주어야 한다. 

 

이것을 ResNet에 적용시켜보면,

x의 variance와 F(x)의 variance를 같도록 만드는 것! 

그런데 Var(F(x) + x) > Var(x) 가 되므로 각 block마다 variance가 점점 더 커지는 문제가 발생하게 된다. 

 

=> Solution

첫번째 초기화는 MSRA를 사용하고, 두번째 초기화에서는 zero로 초기화하여 Var(x + F(x)) == Var(x)가 되도록 만들어주자! 

 

이것 뿐만아니라

Weight Initialization이라고 하는 것이 어떻게 하면 좋을지, 해당되는 아키텍처마다 어떻게 활용하면 좋을지 서술하는 여러 연구가 있다.

 

그리고 우리가 train할 때 overfit이 되는 현상이 발생하는데, 

train loss가 감소하고 train accuracy는 증가하지만, validation accuracy는 증가하지 않을 때 overfit 되었다고 말한다. 

주어진 데이터에 대해서만 너무 fit하게 학습된 것이다. 

-> Regularization을 해야겠지! 

[Regularization]

위와 같이 Regularization term을 추가하여 적용하는데, 보통 3개의 regularization을 사용한다. 

이 regularization과 비슷한 개념으로 

 

Dropout이라는 것이 존재한다. 

dropout은 neural network가 있을 때, 그 중 특정한 neuron의 값을 랜덤으로 0으로 만들어 버리는 것이다. 

얼마의 확률로 내 현재의 neuron이 dropout에 적용될 것인지가 일종의 hyperparameter가 되는 것이다. 보통 0.5로 설정한다고 한다. 

-> 둘 중 하나가 인위적으로 0이 되는 것! 

코드로 살펴보면, input에 ReLU를 씌운 hidden layer1에서 그 값의 랜덤 확률이 특정 확률 p보다 작으면 dropout 시키는 구조이다. 

현재 코드에서도 p는 0.5로 설정되어 있다. 

 

dropout은 Prevents co-adaptation of features라는 특징이 있다. 

co-adaptation은 상호의존성으로 어떤 뉴런이 다른 뉴런에 항상 의존하여 같이 변화하는 것을 막아준다는 것이다.

또 dropout은 다른 관점에서 해석할 수 있는데, 

굉장히 많은 앙상블(ensemble)모델(parameter를 모두 같이 공유하는)을 학습한 것과 같은 효과를 내는 것이다. 

모든 가능한 조합들의 모델을 모아두는 꼴이 되기 때문에! 우주의 원자들 보다 많대 ... 경우의수가 ..... 굉장이 파워쁄..

 

그럼 이 좋은 것을 test에도 적용시킬 수 있을까?

test에 적용한다면 output도 랜덤하게 도출될 것이다! ->음 ... 안 좋아! 

개념적으로는 random mask인 z를 다양하게 적용시켜서 나온 합한 값, 즉 평균값을 test에 사용하면 좋겠다! 

 

single neuron으로 예를 들면, 

실제로 우리가 dropout을 적용하지 않고 test를 구해보면 위 첫번째 처럼 나오는데, 

train동안 dropout을 적용해보면 결국 test와 다른 점은 앞에 1/2가 곱해진! 즉, scale의 변화만 있는 것을 알 수 있다. 

그래서 test에서 dropout을 굳이 적용하지 않고 dropout probability를 곱해주면 되겠다! 라는 결론을 얻을 수 있다. 

 

prediction을 할 때에도 마지막에 p를 곱하여 scaling을 적용하는 것을 볼 수 있다. 

 

dropout을 정리해보자면, 

p를 매번 predict할 때 곱하지 않고 train에서 p를 미리 나누어주면 되겠다! 

-> Inverted dropout이라고 한다. 

 

그럼 이러한 dropout을 언제할그냐! 

실제로 AlexNet이나 VGG에서 가장 많은 파라미터를 fully-connected layers에서 갖는 것을 앞에서도 보았었다. 

이러한 경우에 dropout을 적절하게 적용하면 좋을 것 같다. 

근데 또 뒤에 등장했던 GoogLeNet이나 ResNet에서는  global average pooling을 사용하기 때문에 dropout은 사용하지 않는다고 한다. 

  • GAP는 보통 FC대신 사용되어 파라미터수를 크게 감소시키면서 공간 정보를 유지하는 효과가 있다. 

Regularization은 보통 일정한 패턴이 있는데,

  • training : Add some kind of randomness
    • 다양한 데이터에 대응하도록 도와주는 효과, 또한 일반화 될 수 있도록 모델의 일관성을 깨뜨려줌
  • Testing : Averge out randomness 
    • 무작위로 나온 것들을 평균내는 방식으로 진행됨

Batch Normalization을 예로 들면,  

random minibatch(전체 데이터셋을 사용하는 대신 작은 무작위 미니배치를 사용하여 각 모델을 훈련시키는 것)를 통해 train! 

train때 사용한 data를 가지고 test할 때 사용한다. 

-> ResNet 또는 그 이후에 나온 모델들은 보통 L2 or Batch Normalization을 통해 regularizer를 진행한다. 

     dropout은 사용하지 않는 경향! 

 

[Data Augmentation] 

원래 input image에서 CNN을 거쳐서 loss를 계산하는데 정답이 cat이면 cat과 비교해서 loss를 최소화 하는 방식으로 학습이 진행된다. 

그런 상황에서 우리가 data를 다양하게 해주어서 오른쪽 고양이도 input으로 취급(?)하여 data를 증강시키는 것을 data Augmentation이라고 한다. 

 

-Horizontal Flips

인위적으로 수평적으로 뒤집어서 data의 Input으로 넣기! 

 

-Random Crops and Scales

  • Training : sample random crops and scales -> ResNet에서!
    • 256 ~ 480 사이에서 랜덤한 값 L을 고른다
    • short side가 L이 되도록 resize 시킴
    • 그 중에서 224 x 224 patch를 랜덤 샘플링 시킨다. 
  • Testing : average a fixed set of crops -> ResNet에서!
    • 5개의 scale에서 이미지를 resize 한다. 
    • 각각의 사이즈에 대해서 224 x 224 10개를 crop한다
      • corners 4개 + center 1개를 flip하는 구조로 총 10개! 

  • 각 이미지의 픽셀들의 값을 가지고  R, G, B 공간상에서 PCA를 적용시킨다 
  • 모든 픽셀에 대해 주성분 방향을 따라 color offset을 샘플링한다. 
    • color offset : 색상을 변경하기 위한 어떤 양 -> RGB 색상 값에 더해지는 값을 의미 
  • 샘플링된 offset을 모든 픽셀에 추가한다. (색상 변경 과정) 

AlexNet과 ResNet 등에서 이를 사용 

 

-> 이미지의 밝기와 명암대비를 무작위로 조절하여 데이터 다양성에 추가하려는 것! 

 

문제에 따라 다른데, 

여러가지 방법으로 데이터의 다양성을 추가할 수 있다.

 

Regularization 

앞서 언급했던 Dropout, Batch Normalization, Data Augmentation 모두 일종의 regularization임. 

무작위성을 추가하여 학습한 뒤, 실제 test에서는 무작위성을 해소한 뒤 진행되었다. 

이는 뉴런과 뉴런 사이의 connection에 대해서 랜덤하게 weight를 0으로 만들어주는 것을 말한다. 

꾾어주는 것과 똑같은 효과! 

 

Factional Pooling

이미지 사이즈를 줄여주는 과정에서 영역을 랜덤하게 설정하여 Pooling을 진행하는데, 여러 다른 샘플들에 대해서 랜덤하게 pooling을 적용시키고, 다양한 샘플들에 대해서 평균을 구해서 결과를 내는 방식이다. 

 

앞에서는 노드나 weight를 drop했었는데, 

ResNet에서 아예 ResNet block 통째로 skip시키면서 처리하는 것이 존재한다 -> Stochastic Depth 

이 경우에는 그럼 depth가 달라질 것이다.

 

CutOut! (* 아래 Stochastic Depth가 아니라 cutout임! 오타!)

이미지의 특정 영역을 0으로 셋팅시켜 정보를 없애버리는 것! 하지만 test할 때는 전체 이미지를 사용한다. 

실제로 CIFAR와 같은 작은 데이터 셋에서는 작동이 아주 잘 된다고 하지만 ImageNet과 같은 큰 데이터 셋에서는 잘 사용하지 않는다고 한다. 

  • 왜 굳이 0으로 셋팅시켜? 왜 굳이 정보를 없앨까?
    • 모델이 특정 부분에 과도하게 의존하지 않도록 일반화 해주는 특징이 있다. 
    • 또한 노이즈를 추가하는 효과를 가져 노이즈에 robust해지는 특징이 있음 -> 이미지 누락의 경우 올바른ㅇ ㅖ측 수행 가능성 up
    • 분류 문제에서 효과적 
      • 왜? -> train data의 다양성이 증가하고, 노이즈를 강화시켜주고 일반화적이니까! 또한 적은 Dataset에서 효과적이라서?

Mixup

이미지를 랜덤하게 blend 시켜서 train하고 test에서는 원래 original image로 진행한다. 

예를 들면 위와 같이 고양이(40%)와 강아지(60%)를 mix시켜서 targel label이 cat : 0.4, dog : 0.6이 나오게 즉, blend weight의 값 그대로 출력되도록 학습시키는 것이다.

 

일반적으로 

  • fully-connected layers에서는 dropout을 자주 사용하도록 하고
  • 일반적으로는 Batch Normalization과 data augmentation으로 충분히 잘 된다고 한다. 
  • 작은 classification 경우에는 cutout, mixup을 적용시키면 잘 된다고 한다. 

오늘의 썸머리

서론과 같아! 

다음 강의에 이어서 2, 3을 배워보겠어요

 


.. 드디어.. 

몸 하나를 쪼개서 요기조기 보내도 

모자랐던 금토일 이엇어 

약속은 가야겟고 공부해야겍고를 다 해내느라

잠을 미친듯이 줄인 사람이야 

(오후)2시 약속이라 (오전)8시부터 학교간사람..

그치만 또 다시 학교로 복귀한사람

집 언제가냐.....

한 주의 시작인데 벌써부터 피곤타 

이번주야 이번주도 화이팅!