1. 금일 목표
- 체크포인트 모델 저장
- F1-score Metric 을 구현 or 코드
- Gradient Accumulation을 적용
- 다양한 스케쥴러 적용 및 비교
- Label smoothing, Focal Loss, F1 Loss 등 활용
- 위 사항별 성능 비교
2. 진행사항
1) 체크포인트 모델 저장
if epoch_val_loss < best_val_loss:
print("New best model for val loss! saving the model..")
torch.save(model.state_dict(), os.path.join(f'{path}/{epoch:03}_loss_{epoch_val_loss:4.2}.pt'))
best_val_loss = epoch_val_loss
if epoch_val_f1 > best_val_f1:
print("New best model for val f1! saving the model..")
torch.save(model.state_dict(), os.path.join(f'{path}/{epoch:03}_f1_{epoch_val_f1:4.2}.pt'))
best_val_f1 = epoch_val_f1
# 가장 성능이 좋은 모델을 따로 저장해 나중에 불러옴
best_model = f'{path}/{epoch:03}_f1_{epoch_val_f1:4.2}.pt'
2) F1-score Metric 을 구현 or 코드
from sklearn.metrics import f1_score
epoch_f1 += f1_score(output.argmax(dim=1).cpu(), label.cpu(), average='macro') / len(train_loader)
3) Gradient Accumulation을 적용, 다양한 스케쥴러 적용 및 비교
- Scheduler
- StepLR: 특정 Step 마다 LR 감소
- CosineAnnealingLR: Cosine 함수 형태처럼 LR을 급격히 변경
- ReduceLROnPlateau: 더 이상 성능 향상이 없을 때 LR 감소
# batch size가 32인 경우 NUM_ACCUM을 4로 설정하면 128batch만큼 진행된 후 optimizer 파라미터를 업데이트 합니다.
NUM_ACCUM = 4
gamma = 0.7 # step_size만큼의 epoch가 진행되면 기존의 lr에 gamma값을 곱해 새로운 lr 생성
scheduler = StepLR(optimizer, step_size=5, gamma=gamma)
lrs = []
for epoch in range(epochs):
for i, data in enumerate(tqdm(train_loader,leave=True)):
model.train()
inputs, label = data
inputs = inputs['image'].to(device)
label = label.to(device)
output = model(inputs)
loss = criterion(output, label)
loss.backward()
if i % NUM_ACCUM == 0:
optimizer.step()
optimizer.zero_grad()
lrs.append(optimizer.param_groups[0]["lr"]) # lr 확인을 위해 담아줌
scheduler.step()
4) Label smoothing, Focal Loss, F1 Loss 등 활용
- Focal Loss
Focal Loss는 one-stage detector에서 클래스 불균형 문제를 해결하기 위해 제안된 loss function으로 cross-entropy loss에 인자를 하나 추가한 것입니다. 해당 인자를 modulating factor이라 하며, easy example의 영향을 감소시키고 hard example에 집중하도록 합니다. $\gamma$는 하이퍼 파라미터로 easy/hard example의 가중치를 조절할 수 있습니다. example이 잘못 분류됐으면 $p_t$는 낮은 값을 가지게 되어 modulating factor($1-p_t$)은 1에 가까운 값을 갖게 되고 loss는 가중치에 영향을 거의 받지 않게 됩니다.
- Label smoothing
잘못된 loss 의 영향을 줄이기 위하여 label 을 0또는 1이 아니라 smooth 하게 부여하는 아이디어로, hard target을 soft target으로 바꾸어 모델의 over confidence 문제를 해결하는데 사용됩니다.
아래 크로스 엔트로피 loss의 $y(k)$에 위의 $y(k)'$를 대입해줍니다.
그 결과 아래와 같은 결과가 나오게 됩니다.
class LabelSmoothingLoss(nn.Module):
def __init__(self, classes, smoothing=0.0, dim=-1):
super(LabelSmoothingLoss, self).__init__()
self.confidence = 1.0 - smoothing
self.smoothing = smoothing
self.cls = classes
self.dim = dim
def forward(self, pred, target):
pred = pred.log_softmax(dim=self.dim)
with torch.no_grad():
# true_dist = pred.data.clone()
true_dist = torch.zeros_like(pred)
true_dist.fill_(self.smoothing / (self.cls - 1))
true_dist.scatter_(1, target.data.unsqueeze(1), self.confidence)
return torch.mean(torch.sum(-true_dist * pred, dim=self.dim))
- F1 Loss
Metric으로 사용되는 f1을 활용해 loss function으로 사용합니다. 성능이 진짜로 잘나오는지 실험예정입니다.
class F1_Loss(nn.Module):
def __init__(self, epsilon=1e-7):
super().__init__()
self.epsilon = epsilon
def forward(self, y_pred, y_true,):
assert y_pred.ndim == 2
assert y_true.ndim == 1
y_true = F.one_hot(y_true, 2).to(torch.float32)
y_pred = F.softmax(y_pred, dim=1)
tp = (y_true * y_pred).sum(dim=0).to(torch.float32)
tn = ((1 - y_true) * (1 - y_pred)).sum(dim=0).to(torch.float32)
fp = ((1 - y_true) * y_pred).sum(dim=0).to(torch.float32)
fn = (y_true * (1 - y_pred)).sum(dim=0).to(torch.float32)
precision = tp / (tp + fp + self.epsilon)
recall = tp / (tp + fn + self.epsilon)
f1 = 2* (precision*recall) / (precision + recall + self.epsilon)
f1 = f1.clamp(min=self.epsilon, max=1-self.epsilon)
return 1 - f1.mean()
5) 성능 비교
- EfficientNet-b3
- EfficientNet-b3 + scheduler
- 표기오류. lr=0.0001에서 시작.
- EfficientNet-b3 + scheduler + Gradient Accumulation
- 표기오류. lr=0.0001에서 시작.
- EfficientNet-b3 + Centercrop
- ResNet18 best loss
- ResNet18 best f1 score
3. 피어세션 정리
https://hackmd.io/C9fuGkS6RlSAT1wKbhHO5g
4. 학습 회고
centercrop을 적용해 보았지만 성능이 오히려 떨어졌습니다. 또한 Gradient Accumulation, 스케쥴러 모두 적용해 보았지만 파라미터를 잘못 설정했는지 성능은 나아지지 않았습니다. 데이터 불균형 문제를 해결하기 위해 다른 방법을 더 찾아보고 다른 모델을 사용하여 실험해봐야 할 것 같습니다.
'네이버 부스트캠프 > LEVEL-1' 카테고리의 다른 글
[부스트캠프][P-stage][WK05] P-stage level1 결산 및 개인회고 (0) | 2021.09.04 |
---|---|
[부스트캠프][P-stage][WK04 / Day5] Image Classification 5 (0) | 2021.08.27 |
[부스트캠프][P-stage][WK04 / Day3] Image Classification 3 (0) | 2021.08.27 |
[부스트캠프][P-stage][WK04 / Day2] Image Classification 2 (0) | 2021.08.27 |
[부스트캠프][P-stage][WK04 / Day1] Image Classification 1 (0) | 2021.08.27 |