ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [PyTorchZerotoAll 내용정리] 07 Wide(다변량) & Deep(gradient vanishing problem)
    ML&DL 이야기/Pytroch 2023. 8. 30. 12:55

    더 많은 x를 사용해보자

    Wide

    이전 시간(06) logistic regression을 이용해 PHD 합격 여부를 예측하는 모델을 만들었었다. 

    그러나 실제로 합격, 불합격이라는 결과를 만들기 위해서는 GPA 뿐만 아니라 더 많은 요소들이 고려될 것이다(다변량)

    이런 다양한 input을 받아서 output으로 표현하기 위해서는 행렬의 곱셈 연산이 필요하다

    matric multiplication can make wide

    즉, 위와 같이 각 input의 data를 column형태로 쌓아 행렬로 만들고, 해당하는 데이터의 수만큼 가중치를 추가하면 된다. 

    이것이 Wide&Deep에서 Wide이다. 코드로는 아래와 같이 표현 가능할 것이다(n은 input data의 종류의 수) 

    import torch
    linear = torch.nn.Linear(n,1)
    y = linear(x_data)

    Deep

    go deep, 모델을 더 쌓아보자

    Deep, 깊게라는 개념은 위와 같이 여러 개의 층을 거쳐서 출력값을 가지는 것이다. 여기서 확인할 점은 모델의 이전 층의 출력노드의 개수가 다음층의 입력 노드의 개수와 같다는 점이다. 

    이를 보면 l1의 입력노드가 전체 모델의 입력 data의 종류와 같고, l3의 출력노드가 1개임으로 output이 1임을 알 수 있다. 

    Gradient Vanishing Problem 

    vanishing gradient problem

    Vanisihing Gradient Problem은 Back propagation 계산 시에 우리가 미분을 사용하기에 나타나는 문제이다. 

    Why?

    층을 깊게하면 깊게하면 깊게 할 수 록 아래의 문제가 커지는데 이는 Sigmoid의 함수의 output은 [0,1]이다. 즉, 1보다 작은 값이다. 

    Sigmoid 함수 원형과 미분 그래프(출처: https://heytech.tistory.com/388)

    미분한 값을 보면 최대값이 0.25에 불가함을 알 수 있다. 동시에 x값이 거의 0에 수렴하게 작아지는 것을 알 수 있다. 

    동시에 역전파 계산식을 보면(https://secundo.tistory.com/50 참고) output에서 input으로 갈 수록 해당 층의 가중치를 계산할 때 이전 가중치값을 계속 곱할 수 밖에 없는데, 이때 해당 가중치 값은 Activation finction의 도함수 값의 곱으로 구성되어 있다.  

    즉, 역전파 과정에서 Sigmoid 의 미분값이 거듭 곱해지면서 출력층과 멀어질수록 Gradient  값이 매우 작아질 수밖에 없다.

    더불어, $\e$(exponential)는 컴퓨터가 계산할 때 정확한 값이 아닌 근사값으로 계산해야 되기 때문에 역전파 과정에서 점차 학습 오차까지 증가하여 결국 Sigmoid 함수를 활용하면 모델 학습이 제대로 이루어지지 않는 문제가 발생한다. 

    Activation Function - ReLU and Leaky ReLU

    ReLU(출처: https://heytech.tistory.com/388)

    그림을 보면 알 수 있듯이 ReLU의 경우 입력값이 양수일 경우 입력 값에 상관없이 항상 동일한 미분 값(1)을 보장하기 때문에 기울기 소실 문제를 해결하고, 동시에 특별한 연산이 없이 임계값(0)에 따라 출력값이 결정되어 연산 속도 또한 빠르다는 장점이 있다.

    하지만 Dying ReLU문제가 존재하는데, 이는 입력값이 음수일 경우 미분값이 항상 0이기에 입력값이 음수인 경우 해당 에지는 죽어버리는 문제가 있다. 

    이를 해결하기 위해 나온 것이 Leaky ReLU이다. 

    Leaky ReLU는 음수일 때 출력값을 0이 아닌 0.0001 등과 같이 매우 작은 값이되, 0이 아닌 값을 출력하도록 만들어준다. 

    수식은 아래와 같다.

    $$max(ax, x)$$

    여기서 a는 0.01, 0.001 등과 갘이 매우 작은 값 중 하나로 하이퍼파라미터이다. 

     

    Leaky ReLU(출처: https://heytech.tistory.com/388)

    Skip connection

    Vanishing Gradient 문제의 대부분은 nomalized initialization 및 intermediate normalization layer에 의해 해결되며, 수십 개의 계층이 있는 network가 backpropagation을 통해 gradient descent를 위해 converging을 할 수 있다. 하지만 깊은 network에서 이러한 방법을 이용하더라도 깊은 network에서 gradient vanishing 문제를 완전히 해결하지는 못한다.

     

    Skip Connection은 입력 데이터가 네트워크의 여러 레이어를 건너뛰어 출력 레이어에 직접 연결되는 방식을 말하며, 위의 

    구체적인 예로는 Residual Network등이 있다(ResNet에서는 Skip Connection을 "shortcut" 또는 "residual" 연결이라고 부르며, 이를 통해 입력 값이 네트워크를 직접 통과하여 더 깊은 레이어로 전달되어도 원래의 정보를 보존할 수 있음)

    https://arxiv.org/pdf/1512.03385.pdf

    자세한 내용은 향후 따로 정리를 하려한다.

     

    Code Implementation

    https://colab.research.google.com/drive/1QB72fSRQTZihbzbp8qf7cf-jRWZFy4Ax#scrollTo=CixG8ouxujNI

     

    Google Colaboratory Notebook

    Run, share, and edit Python notebooks

    colab.research.google.com

    https://www.kaggle.com/datasets/saurabh00007/diabetescsv

     

    diabetes.csv

     

    www.kaggle.com

    위 캐글에 있는 diabetes.csv를 이용해 코드를 작성하였다. 

    위의 코드에서는 x_data에는 전체 행, 처음부터 n-2까지의 열만큼의 데이터를 저장하고(맨 마지막의 출력에 해당하는 열은 뺀 것), y_data에는 전체 행, 맨 마지막 열에 해당하는 데이터들을 저장한다.

    numpy에서 torch로 변형한 뒤에 Variable 함수를 써서 이 과정을 수행한다. torch의 shape함수를 사용하면 우리가 원하던대로 x_data가 759 행, 8열로 구성되어있고, y_data가 759행, 1열로 구성되어있는 것을 알 수 있다.

    이후 결과를 아래 코드를 통해 출력하면 다음과 같다.

     

Designed by Tistory.