NeuroWhAI의 잡블로그

[Rust] 드롭아웃(Dropout) - '밑바닥부터 시작하는 딥러닝' 6장 본문

개발 및 공부/알고리즘

[Rust] 드롭아웃(Dropout) - '밑바닥부터 시작하는 딥러닝' 6장

NeuroWhAI 2018. 7. 31. 20:02


※ 실제로 동작하는 전체 소스코드는 GitHub에서 보실 수 있습니다.


(가중치 초기화 방법들(Xavier, He)은 코드로 구현은 하였지만 글은 넘어갑니다.)

드롭아웃은 오버피팅(과적합)을 방지하기 위해서 순전파시 일정 확률로 특정 출력값을 0으로 만들고
역전파시에도 기울기의 해당 부분들을 0으로 만들어서 보냅니다.
보통 일정 확률로 신경망의 뉴런을 비활성화한다 혹은 끈다고 설명합니다.
학습이 좀 느려진다는 단점은 있지만 쉽게 과적합을 어느정도 이겨낼 수 있습니다.
비슷하게 배치정규화라는 놈도 과적합을 방지해주지만 이건 학습 속도가 훨씬 빠릅니다.

아래 코드는 드롭아웃 계층을 어떻게 구현했는지만 넣어놨습니다.

코드:
impl Layer for Dropout {
    fn forward(&mut self, x: &Matrix<f32>) -> Matrix<f32> {
        if self.train_flag {
            let rand_matrix = Matrix::from_fn(x.rows(), x.cols(), |_, _| rand::random::<f32>());
            self.mask = PartialMatrix::le(&rand_matrix, self.dropout_ratio);
            
            let mut out = utils::copy_matrix(x);
            self.mask.set(&mut out, 0.0);
            
            out
        }
        else {
            x * (1.0 - self.dropout_ratio)
        }
    }
    
    fn backward(&mut self, dout: &Matrix<f32>) -> Matrix<f32> {
        let mut masked_dout = utils::copy_matrix(dout);
        self.mask.set(&mut masked_dout, 0.0);
        
        masked_dout
    }
}

결과:
[Optimizer - SGD]
Loss: 490.0664, Acc: 0.196, Test Acc: 0.222
Loss: 383.53577, Acc: 0.703, Test Acc: 0.678
Loss: 210.64793, Acc: 0.806, Test Acc: 0.792
...
Loss: 67.24843, Acc: 0.908, Test Acc: 0.901
Loss: 66.1453, Acc: 0.911, Test Acc: 0.902
Loss: 65.10284, Acc: 0.914, Test Acc: 0.905
Final test acc: 0.916
[With dropout]
Loss: 493.32635, Acc: 0.122, Test Acc: 0.13
Loss: 456.39633, Acc: 0.562, Test Acc: 0.536
Loss: 332.7797, Acc: 0.719, Test Acc: 0.699
...
Loss: 81.6619, Acc: 0.9, Test Acc: 0.902
Loss: 80.01616, Acc: 0.902, Test Acc: 0.905
Loss: 78.53487, Acc: 0.905, Test Acc: 0.905
Final test acc: 0.908

뭔가 오히려 드롭아웃을 사용한게 최종 정확도가 더 떨어지는데

가중치가 랜덤으로 초기화 되는거랑 학습 속도가 떨어지는 특성 때문에 그럴겁니다.

주목해야 할 부분은 드롭아웃을 사용했을땐 학습 정확도와 테스트 정확도의 차이가 별로 크지 않다는거죠!



Comments