cs231n

cs231n Assignment 2: Q3 (Dropout 구현)

츄츄츄츄츄츄츄 2023. 2. 15. 00:18

내 풀이 링크: https://github.com/lionkingchuchu/cs231n.git

 

GitHub - lionkingchuchu/cs231n: cs231n Spring 2022 Assignment

cs231n Spring 2022 Assignment. Contribute to lionkingchuchu/cs231n development by creating an account on GitHub.

github.com

이번 과제는 dropout layer에 관한 것이다 dropout은 한 layer를 지나고 각 뉴런마다의 output값이 있을 때, 일정 비율만큼의 랜덤한 뉴런들을 골라 그 output을 0으로 없애는 것이다. 예시로 dropout ratio가 0.5라면 전체 뉴런의 output값 중 절반을 랜덤으로 날리는 식이다.

 

이렇게 일정 비율의 값을 날리게 되면 다음 layer로 일정 output은 당연히 도달하지 못하게 된다. 매 epoch, 매 iteration마다 랜덤한 뉴런들이 활성화 되면서 매번 weight update하는 뉴런이 달라지기에 확실하게 overfitting을 막을 수 있다. 그리고 또 확실하진 않지만 랜덤한 뉴런들을 활성화 하고 update 하면서 좀 더 general 한 분류를 유도하여 validation accuracy와 test accuracy를 올리는데 도움을 줄 수 있다.

 

CS231n Convolutional Neural Networks for Visual Recognition 참고

위 그림은 원문 srivastava14a.pdf (toronto.edu) 에서 나온 이미지이고, 논문에서 dropout에 대한 상세한 설명을 볼 수 있다.

 

가장 먼저 늘 그래왔듯 forward 함수부터 구현하는 문제이다. 

def dropout_forward(x, dropout_param):
   
    p, mode = dropout_param["p"], dropout_param["mode"]
    if "seed" in dropout_param:
        np.random.seed(dropout_param["seed"])

    mask = None
    out = None

    if mode == "train":
        
        # *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

        mask = (np.random.random_sample(x.shape) < p) / p
        out = mask * x

        # *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
        
    elif mode == "test":
       
        # *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

        out = x

        # *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****

    cache = (dropout_param, mask)
    out = out.astype(x.dtype, copy=False)

    return out, cache

여기서 p는 dropout ratio이고 날리는 비율이 아니고 살리는 비율이다. 0.7이면 output 30%를 날리는 식이다. 간단하게 dropout ratio p만큼의 비율만 살리는 mask를 만들고, mask에 p를 나누어 주고 out에 곱한다. 여기서 p를 나누는 이유는 밑의 문제에서 묻는다.

Inline Question 1:

What happens if we do not divide the values being passed through inverse dropout by p in the dropout layer? Why does that happen?

Answer:

If we do not divide p in the dropout layer, the total network flow of layer's input and output will be different. Since we are passing only p amount of the inputs, output amount will be p * inputs. we can divide p to solve this problem or if you want to keep this decreasing amount, we should multiply p when predicting test data passes dropout layer.

 

여기서 p를 나누어 주는 이유는 총 output에서 (1-p) 만큼을 날려서 output의 전체 비율이 p로 줄어들었기 때문이다. 예시로

[[1, 1, 1],

[1, 1, 1]]

의 output 크기는  6이다. 이 output에서 0.5 를 dropout하면

[[1, 0, 0],

[0, 1, 1]]

이렇게 되어 output의 크기 3 으로 줄어들게 된다. output의 scale을 기존값과 같게 맞춰주기 위해 output에 0.5를 나누어 주면

[[2, 0, 0],

[0, 2, 2]]

가되어 output의 크기가 6으로 기존 output과 같게 scaled 된다. 그리고 test때는 dropout 하면 안되므로 그대로 보내준다.

 

그리고 backward 함수 구현은 cache에서 얻은 mask를 dout에 그대로 곱해주어 역전파해주면 된다.

 

다음은 dropout를 시행했을시, 시행하지 않았을시 dropout의 regularization 효과를 보여주는 그래프이다.

dropout keep ratio 1 과 0.25 비교

dropout keep ratio가 1이면 dropout을 하지 않은 것이고, 0.25는 0.75만큼 dropout 한 것이다. 마지막 문제는 두 차이를 묻는 문제이다.

Inline Question 2:

Compare the validation and training accuracies with and without dropout -- what do your results suggest about dropout as a regularizer?

Answer:

Training score was higher when we don't use dropout, but validation was higher when we use dropout. This shows using dropout can help us minimize the gap of training accuracy and validation accuracy and minimize overfitting. Result shows that dropout can also work as a regularizer because regularization acts to minimize overfitting.

 

dropout을 사용하지 않았을 때 train acc는 비교적 높게 나왔고, dropout을 사용했을 때 val acc가 비교적 높게 나왔다. 이 말은 dropout을 사용하는 것이 train acc와 val acc를 줄이는 (overfitting을 방지하는) regularization 효과를 충분히 낼 수 있다는 뜻이다.

 

dropout는 확률적으로 일정 output의 값들을 날리며 regularization을 도모하고 혹시 모를 성능 상승을 기대 할 수 있다. 일정 output을 없애는 논리는 이후에 배울 stochastic forward pass (dropconnect)의 기반이 되기도 한다. 이번 과제의 CIFAR-10 분류에는 그닥 좋은 성능 상승이 보이지는 않았다. 그래도 batch normalization이 2015년에 나왔는데, dropout은 2014년에 나온것을 보면 2014년에는 상당히 획기적인 방법이었을것이라는 생각이 들었다.

 

논문을 보면 L1, L2 regularization은 모델의 layer가 많아질수록 weight도 많아지고, 이에 따라 regularization에 사용되는 연산, 그리고 역전파를 통해 weight의 grads를 계산하는 연산도 많아지는데 dropout을 통해 layer가 많아져도 연산 부담이 적게 regularization 효과를 볼 수 있다고 한다.

 

또 신기한점은 이 논리를 생명체의 생식에서 생각해냈다는게 많이 신기하다. 생명체 중 인간인 경우 탄생할 때에 부에서 23개, 모에서 23개의 염색체를 받아 46개의 염색체로 생명체가 탄생하는데, 여기서 부, 모가 각각 줄 수 있는 염색체 46개중 절반을 날리고 23개를 준다는 데에서 착안한 방법이라고 한다. 확실히 염색체의 경우의 수 때문에 같은 인간이더라도 무수하게 많은 다른 특징을 가진 사람들이 발생했기에, 그리고 부모가 같더라도 자식들이 천차만별로 다르기에 염색체를 dropout 한다는 것이 더 다양한 조합을 만드는 데에 도움이 되었을 것이다.