1. Overfitting & Underfitting
Overfitting : Train data에 대해서 과도하게 학습 & Test data에 대해서는 잘 동작 X
- Overfitting은 학습 데이터(Training Set)에 대해 과하게 학습된 상황
- 따라서 학습 데이터 이외의 데이터(Test Set)에 대해선 모델이 잘 동작하지 못함
- 학습 데이터가 부족하거나, 데이터의 특성에 비해 모델이 너무 복잡한 경우 발생
- Training Set에 대한 loss는 계속 떨어지는데, Test Set에 대한 loss는 감소하다가 다시 증가
Underfitting : Train data 조차도 학습 X 할 정도로 부족하게 학습
- Underfitting(과소적합)은 이미 있는 Train set도 학습을 하지 못한 상태를 의미
- Overfitting과 반대되는 상태를 의미
- Underfitting이 발생하는 이유
- 학습 반복 횟수가 너무 적음
- 데이터의 특성에 비해 모델이 너무 간단함
- 데이터 양이 너무 적음
Errors
- $y$ : True target
- $\hat {y}$ : Predicted output
- $h(x)$ : model의 출력
- $y$ : 정답
- Squared Error : model 출력과 정답과의 차이를 제곱하여 출력
- Binary Error : model의 출력과 정답이 다르면 1을 출력
- Data sample에서 발생하는 모든 sample들의 pointwise error들을 모두 합하면 : overall error를 계산 = Loss function
- $E_{train}$ : 모델을 주어진 data set에 맞추어 학습하는데 사용하는 error
- 주어진 sample에서 model parameter를 최적화 하도록 사용
- $E_{general}$ 을 approximation 하는데 적합하지 않음
- $E_{test}$ : training data와 overlap이 되지 않도록, 전체 Data Set에서 일부 sample을 따로 빼서 Test Sample을 정의 & 해당 Test Sample에서 나타나는 error
- 이 error가 real world에서 적용할 때 나타나는 $E_{general}$를 표현
- GOAL: $E_{test}$ 가 0으로 근사하도록 하여 $E_{general}$ 또한 0으로 근사할 수 있다는 기대를 갖게 하는 것이 목적
- $E_{test} \approx E_{train}$
- 우리가 학습한 Model이 일반적인 성능을 제공할 수 있도록 하는 것 : Variance가 작도록 설계
- Failure: Overfitting이 발생 (High Variance)
- Solution: regularization, more data
- $E_{train} \approx 0$
- Model의 학습이 잘 되고 있다 (정확도가 올라가고 있다)
- 편차, Bias가 줄어들고 있다
- Failure: Underfitting이 발생 (High Bias)
- Solution: optimization, more complex model
- $E_{test} \approx E_{train}$
- Bias가 높을 경우: 너무 Simple한 Model이 전체 Concept을 표현하지 못함
- Variance가 높을 경우: 작은 변화 혹은 noise에 민감하게 모델이 과도하게 반응
- Model Generality: Variance를 낮춰야 함 (overfitting)
- Model Accuarcy: Bias를 낮춰야 함 (underfitting)
- Bias, Variance는 서로 Trade - off 관계
- Complex Model: Overfitting occurs, Variance 증가, Bias 감소
- Simple Model: Underfitting occurs, Variance 감소, Bias 증가
- Generalization Error를 줄이는 것이 목적
2. Solution
Curse of Dimension
- 입력 Data / Feature의 차원이 증가한다면 동일한 분석력을 유지하기 위해서는 지수적으로 sample의 숫자가 늘어나야 함
- Model의 복잡도 증가 속도 > Data Set sample 수 : Overfitting이 발생하기 쉽다
Solution
- Data Augmentation (증가)
- Regularization (규제화)
- Weight Decay
- Dropout
- Normalization
- Batch Normalization
- Early Stopping
- Ensemble
💡 잠깐!
Regularization이라는 말은 '정규화'라고도 불리며 Normalization과 혼동되는 경우가 많다.
또 이 normalization은 표준화(Standardization)와도 자주 헷갈리는 개념이다.
이들의 개념(차이)을 정리하자면,
- 정규화 Normalization은 데이터의 분포가 정규분포에 가깝게 만드는 것, 즉 범위(scale)를 0~1 사이 값으로 바꾸는 것
- 표준화 Standardization은 데이터가 표준 정규분포에 가깝게 만드는 것, 즉 평균이 0이고 분산이 1이 되도록 scaling 하는 것
- 정칙화 Regularization은 오버피팅을 방지하기 위해 weight에 penalty를 부여하는 것이라고 할 수 있다.
- Cross-validation (CV)
- k-fold cross-validation : model을 generalize 하는데 도움이 된다
- Training Set을 k개의 Group으로 구분
- k-1개의 Group을 training, 1개의 Group을 validation에 사용
- Training : model parameter를 fitting하는데 사용
- Validation : model optimization하는데 사용
3. Regularization - Weight Decay
Regularization
모델의 과적합을 방지하기 위해 모델의 복잡성을 줄이는 방식
- Weight Decay
- Dropout
Weight Decay
학습과정에서 큰 파라미터에 대해서는 큰 Penalty를 부여하여 파라미터가 너무 커지는 것을 방지한다
Loss Function에 Penalty Term을 추가하여 구현한다
Regularization Expression
$Loss(\theta, \lambda | X, Y) = Error(\theta | X, Y) + \lambda Penalty(\theta)$
- Error Function: Squared_Error, Cross_Entropy, Logistic, Hinge Loss 등
- Penalty: $L_{0}, L_{1}, L_{2}, L_{infinite}$
- $\theta$는 Model Parameter로 훈련 과정에서 최적화됨
- $\lambda$는 규제의 정도를 의미
- Hyper Parameter(Tuning Parameter)로 사용자가 최적의 성능을 얻기 위해 결정
- $\alpha$가 0으로 갈 경우: Model Parameter를 자유롭게 결정 가능
- Error Function의 최소화
- 학습 데이터 적합을 더 개선할 수 있음 (Train Loss를 줄임)
- 제약이 적음 -> 모델이 복잡해짐 -> Overfitting
- $\alpha$가 무한대로 갈 경우: 비용함수를 최소화하기 위해서는 Model Parameter를 0으로 보내야 함
- Model parameter $\theta$ 감소
- Model Parameter의 값을 작게 해 Overfitting을 방지할 수 있음
- 제약이 강함 -> 모델이 단순해짐 -> Underfitting
- L2 Regularization: $Penalty(\theta) = \theta_{1}^{2} + \theta_{2}^{2} + \cdots + \theta_{p}^{2} $
- Model Parameter의 제곱에 대해 penalty를 부여하는 방식
- 상관관계가 높은 변수들이 존재할 때 효과적인 규제 방법
- 두 변수 중 하나의 변수의 회귀 계수 값을 크게 감소
- 규제가 강해질 수록 각 Model Parameter가 0으로 수렴 (0이 되지는 않음)
- Ridge: L2 Regularization + Regression
- L1 Regularization: $Penalty(\theta) = \left|\theta_{1} \right| + \left|\theta_{2} \right| + \cdots + \left|\theta_{p} \right| $
- Model Parameter의 절댓값에 대해 penalty를 부여하는 방식
- 중요한 변수만 선택하고 나머지는 제거할 때 유용한 규제 방법
- 두 변수 중 더 중요한 변수만 남기고 나머지 변수의 회귀 계수 값을 0으로 만듦
- 규제가 강해질 수록 각 Model Parameter가 0으로 접근하다가 0이 된다 (Feature Selection = 변수 선택이 가능)
- Lasso: L1 Regularization + Regression
4. Regularization - Dropout
Dropout
딥러닝에서 사용되는 정규화기법이며, 과적합을 방지하기 위해 개발됨
모델의 일부 Neuron을 랜덤하게 제거 후 학습을 진행
- 모델이 특정 뉴런에 과도하게 의존하는 것을 방지
- 전체적으로 더욱 일반화(generalization)된 모델을 생성 가능
모델 훈련 과정에서 노드를 임의로 삭제하여 출력이 일부 노드에만 의존하는 것을 방지하여 더 안정적인 예측이 가능
- 훈련 과정에서 매 Feed Forward 계산에서 $p$의 비율로 노드를 삭제하고, 그 대신 각 출력을 $\frac {1} {1-p}$만큼 스케일하여 계산
- 예측할 때는 모든 노드를 그대로 사용
DropOut 동작방식
- 랜덤하게 선택한 일부 뉴런을 'Turn OFF'
- 훈련량에 따라 적용할 비율을 정하는데, 많은 경우 0.5로 설정
- 학습시에만 적용되고, Test or Prediction시에는 사용되지 않음
입력 데이터의 예측 변수에 Noise를 주고, 모델의 표현 능력을 증가
Dropout Code Implementation
PyTorch 에서는 nn.Dropout Class를 이용하여 간단히 Dropout Layer를 추가함
- super().__init__() VS super(nn.Module, self).__init__()
파이썬 3에서 super() 함수는 현재 클래스와 그 부모 클래스를 자동으로 찾아, 부모 클래스의 생성자를 호출합니다.
따라서, super(DropoutModel, self).__init__()와 super().__init__()는 기능적으로 동일합니다.
import torch
import torch.nn as nn
import torchvision
import torch.nn.functional as F
from torchvision import transforms
from torch.utils.data.dataloader import DataLoader
nn.Dropout(p=0.5)
# Dropout(p=0.5, inplace=False)
class DropoutModel(nn.Module):
def __init__(self):
super().__init__()
self.layer1 = nn.Linear(784, 1200)
self.dropout1 = nn.Dropout(0.5)
self.layer2 = nn.Linear(1200, 1200)
self.dropout2 = nn.Dropout(0.5)
self.layer3 = nn.Linear(1200, 10)
def forward(self, x):
x = F.relu(self.layer1(x))
x = self.dropout1(x)
x = F.relu(self.layer2(x))
x = self.dropout2
return self.layer3(x)
5. Normalization
Normalization (정규화)
- Data Normalization
- In-Layer Normalization
신경망 계층의 입력으로 들어가는 데이터의 분포를 일정하게 맞추어 주는 과정
안정적으로 빠른 학습을 위해 주로 사용함
Data Normalization (Data Preprocessing)
- 입력 계층에 들어가는 주어진 데이터(X)를 정규화하는 과정
- 모델 훈련의 일부가 아니라 전처리의 일부
- MinMax Normalization: 데이터의 최소값 0, 최대값1로 정규화
- Standardization: 데이터의 평균0, 표준편차 1로 정규화
In - Layer Normalization (계층 내 정규화)
신경망 내부에서 한 계층에서 다음 계층으로 전달되는 입력을 정규화
- Batch Normalization
- Layer Normalization
- Weight Normalization
Batch Normalization (계층 정규화)
- Mini Batch 내에서 각 변수가 같은 분포를 갖도록 정규화
- Across - Sample
- 주로 이미지분석 (CNN)에 사용
Layer Normalization (계층 내 정규화)
- 하나의 표본 내에서 변수들이 같은 분포를 갖도록 정규화
- Across - Variable
- 주로 텍스트분석(RNN)에 사용
Weight Normalization (가중치 정규화)
- 데이터 대신에 모델의 가중치를 정규화
6. Augmentation
Augmentation
데이터의 핵심 특징은 간직한 채 Noise를 더하여 데이터셋을 확장
- 주로 새로운 이미지를 생성하는데 사용
- 이미지 분류 모델의 성능을 향상시키는 기술
- CNN 모델의 성능을 높이고 Overfitting 극복
Augmentation 기법
- Rotation
- Flipping
- Shifting
- RandomHorizontalFilp / RandomVerticalFilp: Flip의 확률을 조절
- RandomHorizontalFlip(): 좌우반전, 수평으로 뒤집음
- RandomVerticalFilp(): 상하반전, 수직으로 뒤집음
- Parameter: P (기본값 0.5 = 50%)
- RandomAffine
- 이미지의 Center를 유지하면서 affine transform(회전, 이동)을 진행
- RandomRotation과 같이 degree를 받아서 회전을 시키지만, Affine Space에서 변형
- translation=(a,b)를 받아서 horizontal shift와 vertical shift를 주어진 범위내에서 랜덤하게 실행
- $-image \; width \times a < dx < image \; width \times a$
- $-image \; height \times b < dy < image \; height \times b$
- shear과 같이 기울이는 옵션도 존재
- RandomRotation
- Input Parameter: degree
- sequence를 입력 시: (min, max)내에서 랜덤하게 degree 결정
- single float를 입력 시: (-input, +input) 범위 내에서 랜덤하게 degree를 결정
- center option으로 회전의 중심점을 지정 가능
- ColorJitter
- brightness: 밝기 조절 (0~1)
- contrast: 대비 조절 (0~1)
- saturation: 채도 조절 (0~1)
- hue: 색상 조절 (-0.5 ~ 0.5)
Code Implementation
import torch
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
# Image Load 및 PyTorch Tensor로 변환
image_path = "test.png"
image = Image.open(image_path).convert("RGB")
image = transforms.ToTensor()(image)
# Data Augmentation을 위한 변환 정의
data_transform = transforms.Compose(
[
transforms.RandomRotation(degrees=20),
transforms.RandomHorizontalFlip(),
transforms.RandomVerticalFlip(),
transforms.RandomAffine(degrees=0, translate=(0.2, 0.2)),
transforms.ColorJitter(brightness=(0.7, 1.3)),
]
)
# 증강된 이미지를 시각화
show_aug_image_batch(image, data_transform, n_images=4)
Augmentation Text
- 단어 생략
- 단어 교환
- 단어 이동
Augmentation의 효과
- Overfitting 방지
- 모델이 훈련 데이터의 다양한 변형에 대해 학습할 수 있도록 하여 과적합을 방지
- 성능 향상
- 더 많은 데이터로 학습할 수록 성능이 향상됨
- 데이터 증가
- 데이터셋 확장을 통한 데이터 증가
- 불균형 해소
- 분류 작업시 Class 불균형 문제를 해결
7. Early Stopping
Early Stopping
- Validation Error(검증손실)가 더 이상 개선되지 않을 때 학습을 중단시킴
- Overfitting을 방지
- Epoch이 증가할수록 Overfitting이 될 가능성이 높음
- Epoch이 감소할수록 Underfitting이 될 가능성이 높음
- Training Time을 단축
Code Implementation
EarlyStopping(monitor='val_loss', min_delta=0, patience=0, verbose=0, mode='auto')
- patience: 평가지표가 연속으로 좋아지지 않았을때 stop하기 위한 최소 횟수
- delta: 최소로 좋아져야 하는 결과지표 크기 (해당값 미만일 경우 좋아지지 않았다고 판단)
- verbose: 중간 결과 출력여부
Early Stopping 구현 단계
- 모델의 성능을 평가하기 위한 검증 데이터셋(Validation DataSet) 선정
- 최적의 성능을 가진 모델을 저장하기 위한 변수 초기화
- 학습을 중지하기 위한 조기 종료 조건 설정
- 학습 과정에서 검증 데이터셋의 손실 (Loss)를 기록
- 검증 데이터셋의 손실이 이전보다 증가하는 경우, 조기 종료 조건을 확인하여 학습 중지
- early_stopping_epochs: Validation Loss가 해당 value만큼 연속으로 개선되지(감소하지) 않았을 때 early stop
- best_loss: 현재까지 관찰된 가장 좋은(낮은) Loss
- early_stop_counter: Validation Loss가 연속으로 best_loss보다 높은 횟수
import torch
import torch.nn as nn
import torch.optim as optim
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(10, 20)
self.fc2 = nn.Linear(20, 2)
def forward(self, x):
x = torch.relu(self.fc1(x))
x = self.fc2(x)
return x
model = Net() # 모델 초기화
criterion = nn.CrossEntropyLoss # 손실 함수 초기화
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9) # 옵티마이저 초기화
# 조기 종료 변수 초기화
early_stopping_epochs = 5
best_loss = float("inf") # 양의 무한대
early_stop_counter = 0
# train loop
epochs = 100
for epoch in range(epochs):
# model train
model.train()
train_loss = 0.0
for data, target in train_loader:
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
train_loss += loss.item() * data.size(0) # loss는 모든 data sample에서 발생하는 loss들의 합
# Validation
model.eval()
valid_loss = 0.0
with torch.no_grad():
for data, target in valid_loader:
output = model(data)
loss = criterion(output, target)
valid_loss += loss.item() * data.size(0)
# Validation DataSet의 Loss가 이전보다 증가하는 경우
if valid_loss > best_loss:
early_stop_counter += 1
else:
best_loss = valid_loss
early_stop_counter = 0
# early stopping 조건 확인 -> Validation Loss가 연속으로 early_stopping_epoch동안 개선되지 않았을 때 조기종료
if early_stop_counter >= early_stopping_epochs:
print("Early Stopping")
break