티스토리 뷰

훈련용 데이터에 대해서는 정확도가 높아지지만, 테스트 데이터에 대해서 정확도가 낮아진다.

 

Overfitting : 학습데이터에 너무 최적화되어 weight 값이 잡히고, 이후 학습 데이터가 아닌 새로운 데이터에는 올바른 값을 내보내지 못하는 형상. 매개변수에 비해 상대적으로 훈련 데이터 수가 적을 때 일어난다.

 

Regularization : 데이터에 너무 과적합되어 모델이 피팅되었으니, 이를 좀 덜 적합하게 하고, 이후 새로운 데이터에도 일반적으로 들어맞는 모델을 만들어야 한다. 이 때, 과적합이 아닌 일반성을 띄게 해주는 기법

 

 

파라미터 : 훈련 데이터의 정보를 담는 슬롯

 

정보의 슬롯이 많아서 필요없는 특수한 정보 (MNIST에서의 예는 어떤 사람의 특유의 필체 같은 것 , 사실은 숫자의 모양만 알면 됨) 같은것이 너무 많이 들어가 일반적인 데이터는 판단을 못하게 되는 것입니다. 사실 파라미터가 많다는 것은 학습용 데이터가 적다는 이야기도 됩니다.

 

즉 학습용 데이터를 늘리거나, 뉴럴 네트워크를 단순화 시키던가 하면 오버피팅을 방지할 수 있습니다.

 

 

하지만 이런 방법 외에도 레귤라이제이션이라고 뉴럴 네트워크에 규제를 가해서 부수적이고 우연, 특수한 정보는 담지 않도록 만드는 방법도 있습니다.

 

책에서는 Weight Decay 와 Drop bit이 나옵니다.

 

L2-regularization : 새로운 손실함수 = 기존 손실함수 / 1/2 * ㅅ * (가중치의 제곱의 합)  --> 큰 가중치는 많이 낮추고, 작은 가중치는 적게 낮춘다. ( 큰건 중요하고 적은건 별로면 두가지가 균형이 맞게 되는것과 비슷함 )

 

람다 ㅅ 에 따라서 패널티를 생각하는데, 극단적으로 람다가 0이라고 하면 패널티가 없다고 하는 것과 같습니다.

        weight_decay = 0
        for idx in range(1, self.hidden_layer_num + 2): # 다음 아파인층에서
            W = self.params['W' + str(idx)] #웨이트 다 더하고
            weight_decay += 0.5 * self.weight_decay_lambda * np.sum(W ** 2) # 1/2 * 람다 *제곱의 합

        return self.last_layer.forward(y, t) + weight_decay # = 손실함수 

 

    def gradient(self, x, t):
        """기울기를 구한다(오차역전파법).

        Parameters
        ----------
        x : 입력 데이터
        t : 정답 레이블
        
        Returns
        -------
        각 층의 기울기를 담은 딕셔너리(dictionary) 변수
            grads['W1']、grads['W2']、... 각 층의 가중치
            grads['b1']、grads['b2']、... 각 층의 편향
        """
        # forward
        self.loss(x, t)

        # backward
        dout = 1
        dout = self.last_layer.backward(dout)

        layers = list(self.layers.values())
        layers.reverse()
        for layer in layers:
            dout = layer.backward(dout)

        # 결과 저장
        grads = {}
        for idx in range(1, self.hidden_layer_num+2): # 아래는 크로스 엔트로피 미분 + 람다* 아래는 엘투패널티 미분[웨이트 매트릭스 거의 그 자체였음]
            grads['W' + str(idx)] = self.layers['Affine' + str(idx)].dW + self.weight_decay_lambda * self.layers['Affine' + str(idx)].W # 
            grads['b' + str(idx)] = self.layers['Affine' + str(idx)].db # 편향은 미분해봤자 0이니깐 크로스엔트로피 미분만 생각함

        return grads

 

L1-regularization : 새로운 손실함수 = 기존함수 + ㅅ *(가중치의 절대값의 합) --> 큰 가중치나 작은 가중치나 동일하게 낮춰줍니다. (작은 가중치는 결국 0이되어서 날라가고, 큰 가중치들만 남아있게 됩니다. 중요한정보만 살리고 별로인건 날린다는 의미와 비슷합니다. ) 

 

두 레귤레이션은 정보를 날리게 하는 것에 의미가 있습니다. 

 

 

 

 

Dropout : 뉴런을 무작위로 선택해 삭제하여 신호전달을 차단합니다.

Dropout : 뉴런을 무작위로 선택해 삭제하여 신호전달을 차단합니다.

 

마찬가지로 오버피팅을 방지하기 위해서 사용합니다.

Dropout도 층입니다. (순전파 역전파 존재)

 

class Dropout:
    """
    http://arxiv.org/abs/1207.0580
    """
    def __init__(self, dropout_ratio=0.5): # 몇 %만큼 죽이고 학습을 시킨다.
        self.dropout_ratio = dropout_ratio
        self.mask = None

    def forward(self, x, train_flg=True):#훈련할때는 뉴런들을 랜덤하게 죽이면서 학습
        if train_flg:
            self.mask = np.random.rand(*x.shape) > self.dropout_ratio#rand는 0~1사이의 수를 랜덤하게 데이터 뽑는것   // 셀프.마스크 는 드롭아웃레이트보다 큰 값은 트루, 아닌값은 폴스인 트루폴스로 이루어진 행렬이된다.
            return x * self.mask
        else:#훈련아닐때는 죽이지않는다.
            return x * (1.0 - self.dropout_ratio)

    def backward(self, dout):
        return dout * self.mask

dropout층에서는 흘려보낼 미분을 구하는게 목적 ( 학습시킬 파라미터가 없음 ) 

 

sigmoid relu softmax 와 같음

 

affine bath-nomalization 은 학습 시킴

댓글
최근에 올라온 글
최근에 달린 댓글
250x250