파이썬 코드로 짠 M.L.N.N.의 코드를 하나하나 살펴보자.

image

위에는 Multi-Layer Neural Network(fully-connected N.N.)의 prototype이다.
여기서 하나하나의 요소를 개선해서 성능을 높일 수 있다.

activation function-> sigmoid만 썼었다.
weight initialization-> uniform으로 -1~1사이 랜덤하게 줬었다. 그리고 gradient를 태워서 알아서 찾아가게했다.
- 여기서 weight가 2개(행렬 묶음)이라는 것은 Layer가 2개라는 뜻이다.
Optimizer -> gradient descent로 backward propagation으로 w를 업데이트 해줬었다.


오늘은 이 중 activation function에 대해 공부해 볼 것이다.




Activation function


activation function은 각 layer에서 나오는 output(a1)을 복잡한 모델로 만들어주는 역할이라 생각하자.
image
먼저 우리 코드 가운데 sigmoid를 살펴보자. sigmoid는 2가지 역할이 있다.
- activation function으로서, 각층의 Layer마다 들어가서, 모델의 복잡도를 올린다.
- output function으로서, 0~1사이의 값을 가지게하여 classification ( 0 or 1)이 나오도록 하는 squarsh function
  1. z1까지는 덧셈과 곱셈으로만(linear : 단순함) 이루어져 있었다.
    여기에 sigmoid를 씌워(non-linear : 복잡함모델을 더 복잡하게 만들어주면 성능을 높일있을 것이다.
    여기서 sigmoid는 복잡한 연산이가능케 해주는 Activation function의 역활이다.

    여기서 만약에 sigmoid를 안씌운체로, 다음 Layer의 input으로 들어간다면??
    아래의 그림과 같이 M.L.N.N.의 마지막Layer의 output(h(x)- y_predict)가 Single-Layer Neural Network수준으로 나오게 되어
    복잡한 연산을 하지 못하게 될 것이다.
    즉, 중간중간Layer마다 activation function이 들어가지 않아 non-linear하지 않고 linear해진다면,
    아무리 Layer를 깊게 쌓는다고 하더라도 결국에는  w1개 + b1개로 학습시킨 것과 마찬가지가 된다.
    딥러닝 Layer의 복잡도를 높혀주어야된다!!

    image


  2. 마지막층의 z2에 씌운 sigmoid는 사실 keras상에서도 이름만 Activation function이지,
    역활은 input이 뭐가 들어가건 output이 0~1사이의 값이 나오도록 squarshing하여 classification이 가능하게 해주는 Squarsh function이다. 이후 다른 함수들과 같이  output  이라 불린다.
    image

    나중에는, output function이 sigmoid 이외에 softmax가 많이 쓰인다.
    특히, multi-class classification할 때 많이 쓰인다.
    softmax는 output function으로만 쓸 수 있지, activation func을 대체할 순 없다.


결론)


M.L.N.N. (= feed-forward N.N. = fully-connected N.N)의 각 Layer에서 W와 X의 dot product연산 후 or
Convolutional N.N. 의 각 Layer에서 convolution 연산
무조건 Acitivation func으로 복잡도를 늘려 층을 늘리는 것을 의미 있게 만들어야한다.
image






다양한 Activation function의 종류와 장,단점


  1. Sigmoid
    image
    - 장점 : activation func으로서의 장점은 없다. 앞으로는 다른 activation func를 쓰고, 마지막 output function(squarsh func)으로 쓰자.
    - 단점 : activation func의 좌우로 접선의 기울기가 0(da2/dz2)이 되는 지점이  -6, +6만 되어도 시작되어, back propagation을 이용하여 편미분할 때, dL/dw가 0이 되므로 w의 업데이트가 없어지는 saturation현상 발생한다. (앞으로 나올 모든 activation func의 단점)
    뒤쪽의 Layer가 Saturation 되면 앞의 모든 Layer도 Saturation되어 w의 업데이트가 중지된다
    .
    image


    즉, activation func의 시각화했을 때, 접선의 기울기가 0이 되는 지점은 da/dz = 0이 되어
    w업데이트량(w=w-람다*dL/dW)을 의미하는 dL/dW도 체인룰로 풀어보면 0이 된다.
    이것이 saturation현상이며, sigmoid뿐만 아니라 모든 activation func의 단점으로 작용한다

    참고)
    Loss = Mean Square Error를 쓰는 Regression문제에서,
    - L(y,h(x))의 w2편미분 = w와 L(y,h(x))의 시각화시 접선의 기울기 = 0 ===> loss 0인 지점으로 best w찾은 것
    Classification문제에서 각 Layer마다 모델복잡도를 위해 씌우는 Activation Func에서,
    - a2와 z2로 시각화시, 접선의 기울기 = 0 ===> saturation되는 지점으로 w업데이트량이 0인 지점.

    saturation현상이 있는지 판단하고 싶다면, actication function을 시각화 한 뒤, 기울기가 평평해지는 지점이 있는지 보면 된다.
    saturation현상을 포함해서 w의 업데이트가 0이 되는 현상을 모두 일컫어 vanishing gradient이라고도 한다.


    sigmoid의 activation func으로서 2번째 단점은 squarshing할려고 한 것도 아닌데 계속 sigmoid의 결과값이 0~1사이(+)로 나오게 된다.
    그리고 sigmoid의 편미분값(기울기, 0에서 최대 0.25로 가파름)도 0 ~0.25사이(+)로 나오게 된다.
    그 결과 아래와 같이 w2의 업데이트량은 하나의 부호(모두 + or 모두 -)로 결정된다.
    image

    그러면 이렇게 activationfunc 0~1로 양수 + activation func편미분(시각화시 기울기)도 양수 -> w2업데이트량 부호통일
    어떤 문제가 생길까?
    best의 w를 찾아가는데 있어서, 업데이트량이 항상 같은부호의 matrix로 구성되어,
    직선으로( + -> - ) 갈 수없고  (+  -> + , -   ->   -) 로 움직이는 ZigZag현상이 발생하여 업데이트가 느려진다.
    image


    즉, sigmoid의 output(0~1) 및 sigmoid의 편미분(기울기, 0~0.025)가 모두 양수이므로
    w2의 업데이트량은 언제나 + or -가 나오며, 업데이트 방향을 잡을 때, 비효율적으로 zigzag현상이 발생하여, 업데이트 속도가 느려진다.


    사실 best W를 찾아가는 가장 이상적인 activation func, +비중과 -비중이 비슷하면서 saturation안되는 y=x형태의 linear이다.
    그러나 activation func이 linear면 Layer를 쌓아도 결국에는 single-Layer수준밖에 안된다는 것을 배웠다.

    sigmoid의 세번째 단점은, np.exp연산이 들어가므로 연산이 느리다.
    - 사실은 Convolution연산이 더 오래 걸린다.

    그래서 이 sigmoid의 단점을 보완하기 위한, 개선된 activation func들을 알아보자.
     

  2.  tanh(hyperbolic tangent) : 탄치
    image
    sigmoid와 유사하게 생겼지만,  sigmoid의 output 0 ~ 1(양수)
    - 장점 : 결과값(output)이 -1 ~1사이면서, (-)와 (+)가 나오는 비중이 비슷하므로 --> zigzag현상이 덜하다.
    - 단점 : 변함없이 saturation현상이 있어 w업데이트가 멈출 수 있다. exp연산(4)이 더 많아서 시간이 더 오래걸린다.

  3. ReLU(Rectified Linear Unit) : 가장 많이 사용할 activation func, 실제 적용시 효과가 가장 좋다.
    - activation func을 넣는 이유는 non-linear한 함수를 씌우는 것인데, non-linear하면서 가장 심플한 함수이기 때문이다.
    image
    - 는 0으로 바꾸고, +는 x그대로 사용하는 function
    - 장점 : saturation되는 부분이 2군데에서 1군데로 줄었다. / exp연산이 없이 단순하여 빠르다. / loss수렴속도가 sigmoid, tanh에 비해 6배 가까이 빨리 수렴된다.
    ReLU가 나오기 전까지는 activation func이 smooth해야 w업데이트가 잘된다고 생각하여 exp연산이 들어간 sigmoid, tanh를 썼었다.
    하지만, acitvation func이 smooth한 구간에 걸린 순간, w업데이트 속도가 어마어마하게 느려지는 것이 발견되고,
    ReLU의 경우, 편미분(기울기)가 1로 일정하기 때문에, w업데이트 속도가 빨라져 성능이 좋아진 현상이 나타났다.
    ReLU가 딥러닝 activation func의 default가 되어버렸다.

    - 단점 : ReLU의 output(결과값)이 0 or (+)  / ReLU의 편미분 값도  0 or 1(+)  --> sigmoid처럼 둘다 양수라서 zigzag현상이 생긴다.
    ( w2 업데이트의 부호가 항상 같으므로, best w2를 찾아갈 때,,, 지그재그로 간다)


    결과적으로, saturation은 막을 수 없지만, sigmoid나 tanh보다 접선의기울기가 0되는 부분이 적기 때문에, ReLU를 쓴다.


  4. LReLU, PReLU ( Leacky ReLU, Parametric ReLU)
    - ReLU의 업그레이드 버전이나, 성능이 좋다고 100%말할 수 없는 activation func
    image
    - 리키 렐루 : x가 음일 때, 0이 아니라 0.01을 곱해준다.
    - 파라메트릭 렐루 : x가 음일 때, 0.01이 아니라 알파값을 주고, back propagation / gradient로 w와 같이 train시켜 업데이트한다.

    image
    - 둘다 saturation하는 부분(접선의 기울기0)이 없다.

    그러나 default는 ReLU만 쓰고, 거기서 성능개선시 바꾼다.

  5. ELU ( Exponential Linear Unit) : E렐루
    image


    squarsh function(output function)으로 sigmoid이전에 threshold function에 대해서 얘기했었다.
    imageimage
    하지만 이 함수를 쓸 수 없는 이유는 output function(squarsh function)미분불가하면
    Loss func이 smooth하지 못한 상태, 울퉁불퉁한 상태로 정의되기 때문에,
    gradient로 w를 업데이트 못시키거나 local optimer가 생길 수 있어서라고 했다.

    렐루도 마찬가지로 0에서 미분이 불가하다. 그러나 output function(squarsh function)이 아니므로,
    activation func으로는 미분불가해도, 0에 걸릴확률은 적으니 퉁치고 사용했던 것이다.

    왠지 미분불가하면 activation func도 사용하면 안될 것 같다 생각하는 사람이 개발한 것이다.

    그러나 ReLU보다 딱히 성능이 높아지지 않기 때문에 쓰는 사람만 쓴다.


  6. SELU (Scaled Exponential Linear Unit)
    - 엘루와 비슷하나, PReLU처럼, 파라미터를 집어넣어 train시킬 수 있게 ELU를 수정한 것이다.
    - 알파값 2개를 파라미터로 넣어, train시키면--> activation func의 분산이 일정하게 나와, 성능이 좋아진다고 알려졌다.
    image

    그러나, 알파값에 따라 activation func의 결과값이 일정하지 않기 때문에--> Layer를 많이 쌓을 수 없다.
    ( activation func의 결과값이 일정해야 Layer를 더 많이 쌓을 수 있다. 차후 학습하자)

    이것도,, ReLU에 비해 딱히 성능이 많이 좋아지진 않는다.


  7. Swish : Google에서 나온 가장 최근의 Activation func
    image

    ReLU와 비슷하게 생겼는데, smooth하다.
    activation func인데도, 드물게 0근처 음수에서 급하게 꺽였다가 다시 올라가서, 편미분/접선기울기가 음수가 나와서
    좀 더 복잡한 activation func으로 성능이 더 좋을 것이라고 예측
    된다.


  8. Maxout : saturation현상과 zigzag현상을 커버하는 유일한 activation func
    image
    maxout은 weight를 똑같은 버전으로 2개를 만든 뒤, dot product로 2개를 따로 train하고 난 뒤,
    2개의 weight 중 큰 것만 가져와서 activation function으로 쓴다.
    dot product의 결과는 linear한것으로만 나오지만, max연산을 통해 non-linear가 된다.

    실제 성능도 가장 좋게 나오지만, weight가 2개가 필요하기 때문에, 비효율적이다.



  9. 정리
    weight를 초기화를 잘했다는 가정하에 activation function에 따른 성능을 비교한 그래프이다.
    image
    - 파란색 ReLU와 노란색 swish의 성능은 거의 비슷하다.
    - 주황색 identity(activation func안쓴것) 과 sigmoid의 성능은 결국 비슷해진다.  sigmoid는 초반에 속도가 오히려 더 느리다.

    weight초기화를 제대로 못한 경우의 activation func 성능비교를 보자.
    image
    - sigmoid가 가장 높은 성능을 보인다.
    - 그다음이 relu와 swish는 비슷한 성능을 보인다.


결과적으로, ReLU나 Swish나 비슷하므로 ReLU를 activation function의 default로 쓰자.
더 성능을 뽑아내고 싶다면, 다른 것을 써보자.
activation function은 아직 미지의 영역이다.


요약하자면)

Activation Function을 쓰지 않으면, Layer 더 쌓더라도 의미가 없어질 수 있기 때문에,
Conv Layer나 Fully-connedcted Layer의 연산후에 무조건 activation Function을 입혀주자.

여러가지 activation function이 있지만, 결과적으로 우리는 ReLU를 쓰면 된다.
더 성능을 개선하고 싶다면, 리키렐루, 피렐루, 엘루, 에스엘루, 스위스를 써보면 된다.
궁극의 성능을 뽑고한다면, maxout을 써보자.

sigmoid는 output function(squarsh function)목적으로만 쓰자. 다음에는 softmax를 배워서 쓸 것이다.



실습

python으로 sigmoid, tanh, ReLU를 정해보고,  accuracy의 성능을 비교해보자.



+ Recent posts