5-2 과적합과 과소적합
– 학습 곡선을 통해 과적합 및 과소적합 학습
과적합: 모델이 훈련 세트에서는 잘 수행되지만 검증 세트에서는 제대로 수행되지 않는 경우.
언더피팅: 트레이닝 세트와 검증 세트의 성능 차이가 크지 않지만 둘 다 성능이 좋지 않은 경우.
트레이닝 세트 크기와 과적합 및 과소적합 분석
첫 번째 곡선: 과적합(높은 분산)
두 번째 곡선: 과소적합(높은 왜곡)
세 번째 곡선: 과적합과 과소적합 간의 절충점 찾기
에포크 플롯과 손실 함수를 사용한 과적합 및 과소적합 분석
왼쪽 패널: 검증 세트의 손실 및 훈련 세트의 손실
(스위트 스팟 이후 훈련 세트로 모델을 계속 훈련시키면 모델이 과대적합됩니다)
(최적점 이전에 학습을 중단하면 모델이 과소적합됩니다.
)
오른쪽 패널: 세로축 손실 대신 정확도
모델 복잡성 플롯 및 손실 함수를 사용한 과적합 및 과소적합 분석
– 적절한 편향-분산 트레이드오프를 선택합니다.
언더피팅 모델: 편향
과적합 모델: 분산이 큽니다.
과소적합 모델과 과적합 모델 사이의 관계: 바이어스-분산 트레이드오프
1. 검증 손실을 기록하는 변수 추가
def __init__(self, learning_rate=0.1, l1=0, l2=0):
self.w = None
self.b = None
self.losses = ()
self.val_losses = ()
self.w_history = ()
self.lr = learning_rate
2. 유효성 검사 세트를 가져오기 위해 fit() 메서드에 매개 변수를 추가합니다.
def fit(self, x, y, epochs=100, x_val=None, y_val=None):
self.w = np.ones(x.shape(1)) # 가중치를 초기화합니다.
self.b = 0 # 절편을 초기화합니다.
self.w_history.append(self.w.copy()) # 가중치를 기록합니다.
np.random.seed(42) # 랜덤 시드를 지정합니다.
for i in range(epochs): # epochs만큼 반복합니다.
loss = 0
# 인덱스를 섞습니다
indexes = np.random.permutation(np.arange(len(x)))
for i in indexes: # 모든 샘플에 대해 반복합니다
z = self.forpass(x(i)) # 정방향 계산
a = self.activation(z) # 활성화 함수 적용
err = -(y(i) - a) # 오차 계산
w_grad, b_grad = self.backprop(x(i), err) # 역방향 계산
# 그래디언트에서 페널티 항의 미분 값을 더합니다
w_grad += self.l1 * np.sign(self.w) + self.l2 * self.w
self.w -= self.lr * w_grad # 가중치 업데이트
self.b -= self.lr * b_grad # 절편 업데이트
# 가중치를 기록합니다.
self.w_history.append(self.w.copy())
# 안전한 로그 계산을 위해 클리핑한 후 손실을 누적합니다
a = np.clip(a, 1e-10, 1-1e-10)
loss += -(y(i)*np.log(a)+(1-y(i))*np.log(1-a))
# 에포크마다 평균 손실을 저장합니다
self.losses.append(loss/len(y) + self.reg_loss())
# 검증 세트에 대한 손실을 계산합니다
self.update_val_loss(x_val, y_val)
3. 검증 손실 계산
def update_val_loss(self, x_val, y_val):
if x_val is None:
return
val_loss = 0
for i in range(len(x_val)):
z = self.forpass(x_val(i)) # 정방향 계산
a = self.activation(z) # 활성화 함수 적용
a = np.clip(a, 1e-10, 1-1e-10)
val_loss += -(y_val(i)*np.log(a)+(1-y_val(i))*np.log(1-a))
self.val_losses.append(val_loss/len(y_val) + self.reg_loss())
4. 모델 교육
layer3 = SingleLayer()
layer3.fit(x_train_scaled, y_train, x_val=x_val_scaled, y_val=y_val)
5. 손실 값을 플로팅하여 에포크 수를 나타냅니다.
plt.ylim(0, 0.3)
plt.plot(layer3.losses)
plt.plot(layer3.val_losses)
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(('train_loss', 'val_loss'))
plt.show()
6. 운동을 일찍 중단하라
layer4 = SingleLayer()
layer4.fit(x_train_scaled, y_train, epochs=20)
layer4.score(x_val_scaled, y_val)
##출력: 0.989010989010989
5-3 조절 방법을 익히고 단층 신경망에 적용
– 체중조절(regulation) : 체중의 값이 증가하지 않도록 제한하는 기술
두 차트 중 매끄러운 것이 더 나은 성능을 보입니다.
-> 상자로 표시된 샘플 데이터를 더 잘 나타내기 때문입니다.
모델이 몇 가지 데이터 포인트에 고정되어 있으면 새 데이터에 적응할 수 없기 때문에 성능이 좋다고 말할 수 없습니다.
– L1 규정
가중치의 절대값인 L1 놈을 손실함수에 더한다.
L1 규범
로지스틱 손실 함수에 L1 정규화 적용
조절 정도를 제어하는 매개변수 a를 곱하고 더합니다.
– L1 규제의 차별화
L1 제어를 적용한 손실함수 도출
가중치 업데이트 표현식에 적용됨
w_grad += alpha * np.sign(w)
알파: 규제 하이퍼파라미터
np.sign(): 배열 요소의 부호를 반환합니다.
우리는 절편을 제어하지 않습니다 -> 절편은 가중치와 다르게 모델에 영향을 미치기 때문입니다.
회귀 모델 + L1 규칙 = 올가미 모델
– L2 규제
가중치에 대한 L2 놈의 제곱을 손실 함수에 더합니다.
L2 규범
손실 함수의 제곱 + L2 놈 = L2 조절
– L2 조절의 차별화
L2 체계는 가중치 자체가 기울기 계산에 들어가기 때문에 가중치의 부호만 사용하는 L1 체계보다 약간 더 효율적입니다.
w_grad += alpha * w
회귀 모델에 L2 regularization을 적용한 것이 Ridge 모델(Ridge)
Ridge 모델은 Scikit-Learn에서 sklearn.linear_model.Ridge 클래스로 제공됩니다.
SGDClassifier 클래스에서 패널티 매개변수를 l2로 지정하여 추가할 수 있습니다.
– L1 및 L2 규정 요약
※ 내용