오버피팅

- 신경망이 훈련 데이터에만 지나치게 적응되어 그 외의 데이터에는 제대로 대응하지 못하는 상태

- 기계학습은 범용 성능을 지향하기 때문에, 아직 보지 못한 데이터가 주어져도 바르게 식별해내는 모델이 바람직함

 

 

6.4.1 오버피팅

 

오버피팅은 주로 두 경우에서 일어남

  • 매개변수가 많고 표현력이 많은 모델
  • 훈련데이터가 적음

다음은 일부러 두 요건을 충족하여 오버피팅을 일으켰을 때이다. 본래 60,000개인 MNIST 데이터넷의 훈련 데이터 중 100개 ,300개, 1000개만 사용하고, 7층 네트워크를 사용해 네트워크의 복잡성을 높였다. 각 층의 뉴런은 100개, 활성화 함수는 ReLU이다. 

각각 앞에서부터 100개, 300개, 1000개이다. 데이터수가 적을수록 훈련 데이터와 시험 데이터의 간극이 커지는 것을 확인할 수 있다.

 

 

6.4.2 가중치 감소

 

오버피팅 억제용으로 가중치 감소(weight decay)라는 것이 있다. 

학습 과정에서 큰 가중치에 대해서는 그에 상응하는 큰 페널티를 부과하여 오버피팅을 억제하는 방법이다. 원래 오버피팅은 가중치 매개변수의 값이 커서 발생하는 경우가 많기 때문이다.

 

신경망 학습은 손실 함수의 값을 줄이도록 되어있다. 그렇기 때문에 역으로 손실 함수가 커진다면 가중치를 줄일 수 있다.

x는 가중치, f는 손실함수

예를 들어 가중치의 제곱 norm (L2 norm)을 손실함수에 더한다. 가중치를 W라고 하면 L2 norm에 따른 가중치는

이 되고, 이를 손실 함수에 더한다. (λ는 정규화의 세기를 조절하는 하이퍼파라미터, λ를 크게 설정할 수록 큰 가중치에 대한 페널티가 커진다.) 

 

def loss(self, x, t):
"""손실 함수를 구한다.

Parameters
----------
x : 입력 데이터
t : 정답 레이블 

Returns
-------
손실 함수의 값
"""
	y = self.predict(x)
	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)

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

가중치 감소는 모든 가중치 각각의 손실 함수에 위 값을 더한다. 따라서 가중치의 기울기를 구하는 계산에서는 그동안의 오차역전파법에 따른 결과의 정규화 항을 미분한 λW를 더한다.

    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

        return grads

+ Recent posts