z [논문 리뷰] mixup : Beyond Empirical Risk Minimization
본문 바로가기

Others

[논문 리뷰] mixup : Beyond Empirical Risk Minimization

728x90

시작하면서..

최근 학부연구생으로 연구실에 들어갔는데 cifar100에 대해 성능을 최대한 끌어올리는 과제를 받았습니다. 그래서 가장 보편적인 resnet부터 densnet 까지 사용해서 결과를 봐봤는데 test accuracy에 대해 75퍼를 넘기기가 힘들었습니다.
어느정도 한계를 느꼈고 paperswithcode에 가서 cifar 100 dataset에 대한 sota 모델이 뭐가있는지 봐봤습니다.
모델의 resolution, width, depth 비를 적절하게 학습하는 EfficientNet이 SOTA model인 듯 보였습니다만, 저의 눈을 사로잡았던건 바로 manifold mixup 이었습니다.
manifold mixup을 공부하기 전에 mixup 논문을 읽어보았습니다.

Abstract

Large Deep Neural Network는 강력하지만 adversarial examples에 대해 굉장히 민감합니다. 이로 인해 바람직 하지 않은 결과가 도출되기도 합니다.
논문에서는 이를 완화시키기 위해 mixup을 제시합니다.
mixup은 example pair를 convex combination 한 걸로 train 합니다.

Convex Combination : 점들을 linear combination 할 때 계수가 양수이고 계수의 합을 1로 제한한 경우
A point of the form \(\theta_1 x_1+\theta_2 x_2 +...+\theta_k x_k\) with \(\theta_1 + ...+ \theta_k = 1\), \(\theta_i \geq 0\)

Introduction

DNN의 successful application에서는 두가지 공통점이 존재합니다.

  • training data에 대해 average error minimize(ERM)
  • SOTA의 size는 training examples의 수에 따라 선형으로 증가.

하지만 충격적이게도 classical result (Vapnik & Chervonenkis, 1971)는 모델의 크기가 훈련 데이터의 수에 따라 증가하지 않아야 ERM의 수렴이 보장된다는 것을 알려줍니다.
(모델의 크기는 parameter의 수 or VC complexity로 측정됩니다.)

ERM을 통해 학습된 Neural Net은 adversarial examples에 의해 drastically change 합니다.
그럼 ERM의 대안에는 뭐가 있을까요?

ERM의 alternative로 VRM이 있습니다.
VRM의 train 방식은 ERM과 비슷하지만 data에 대해서 다릅니다. 이는 평소에 잘 알려진 "Data Augmentation"을 의미합니다.
VRM은 주변의 데이터로 vincinity distribution을 학습 가능합니다. 이로 인해 추가적인 examples에 대해 결론을 이끌어 낼 수 있습니다. 그리고 Data Augmentation은 인접한 examples는 same class라고 가정합니다.

$$
\tilde x = \lambda x_i + (1-\lambda)x_j,
$$
where x_i,x_j are raw input vectors


$$
\tilde y = \lambda y_i + (1-\lambda)y_j,
$$
where x_i,x_j are one hot label encodings


mixup은 사전지식에 linear interpolation을 통해 training distribution을 확장시킵니다. 구헌 또한 간단합니다.

mixup은 Network의 corrupt labeling에 대한 학습, facing adversarial examples에 대한 robustness를 증가시켜주고, speech, tablur에 대해서 generalization을 improve 해줍니다. 그리고 GAN을 학습하는데 있어서 안정하게 해줍니다.

From Empirical Risk Minimization to mixup

supervised learning의 목적은 feature vector \(X\)와 target vector \(Y\) 사이의 관계를 잘 표현하는 function \(f\in F\)를 찾는 것 입니다.
이를 위해 먼저 loss function \(l\)을 지정합니다. 그리고 data distribution \(P\)에 대해서 loss function \(l\)의 average를 최소화 해줍니다.
$$
R(f) = \int l(f(x),y)dP(x,y)
$$
위는 expected risk를 의미합니다. 하지만 저희는 distribution \(P\)를 알 수 없는 경우가 대다수 입니다. 그래서 training data \(D = {(x_i,x_j)}^n_{i=1}\)로 근사시켜야 합니다. 이를 empirical distribution이라고 가정합니다.
$$
P_\delta = {1 \above 1pt n}\sum^n_{i=1}\delta(x=x_i,y= y_i),
$$
위의 정의된 \(R(f)\) 식에 근사한 empirical distribution을 대입하면 empirical risk를 얻을 수 있습니다.
이는 mini batch에서의 Loss를 구하고 average 취하는 것과 동일한 형태입니다.
$$
R_\delta (f)= {1 \above 1pt n}\sum^n_{i=1}l(f(x_i),y_i)
$$
위의 가정대로 구해진 empirical risk를 최소화 하는 것을 Empirical Risk Minimization (ERM)이라 합니다.
하지만 empirical risk를 최소화하기 위해서는 training data를 memorize를 해야하는데 Memorization은 바람직하지 않은 결과를 초래한다고 합니다.

하지만 여기에서 naive하게 측정한 \(P_\delta\)는 근사될 수 있는 choices가 굉장히 많이 있습니다. 이 다양한 choices들 중 하나를 이용해서 Vicinal Risk Minimization(VRM)을 설명 할 수 있습니다.

$$
P_v(\tilde x,\tilde y) = {1 \above 1pt n}\sum^n_{i=1}v(\tilde x,\tilde y|x_i,y_i)
$$
\(v(\tilde x,\tilde y|x_i,y_i)\)에서 \(x_i,y_i\)는 training feature-target pair이고 ,\(\tilde x,\tilde y\)는 virtual feature-target vector를 의미합니다. (Data Augmentation으로부터 만들어진.)

논문에서의 mixup은 아래처럼 정의 될 수 있습니다.

$$
\tilde x = \lambda x_i + (1-\lambda)x_j,\
\tilde y = \lambda y_i + (1-\lambda)y_j
$$
여기에서 \(\lambda\) 값은 베타분포로 부터 추출 됩니다.

 

https://images.velog.io/images/yhyj1001/post/1651db4e-1848-4868-ad51-3fc0c70f6d90/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-03-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.01.44.png)

 

mixup 구현과 mixup의 효과에 대한 fig. 1.

code 부분에 "y1, y2 should be one-hot vectors"라고 적혀있는데, 파이토치는 구현 할 때는 one hot vectors를 통해 훈련하려면 골치 아파집니다. 그리고 저 loader 2개를 사용하는 것 보다는 하나로 구현 하는게 더 나을 수도 있습니다.

그래서 좀 다른 방식으로 구현을 해보고자 합니다.

아래와 같이 하면 좀 더 효율적으로 구현 할 수 있습니다.



def mixup_criterion(criterion, pred, y_a, y_b, lam):
    return lam * criterion(pred, y_a) + (1 - lam) * criterion(pred, y_b)

def mixup_data(x, y, alpha=1.0, use_cuda=True):
    '''Returns mixed inputs, pairs of targets, and lambda'''
    if alpha > 0:
        lambda = np.random.beta(alpha, alpha)
    else:
        lambda = 1

    batch_size = x.size()[0]
    if use_cuda:
        index = torch.randperm(batch_size).to(DEVICE) # 주어진 수 내 랜덤하게 자연수 생성
    else:
        index = torch.randperm(batch_size)

    mixed_x = lam * x + (1 - lam) * x[index, :]
    y_a, y_b = y, y[index]
    return mixed_x, y_a, y_b, lam

# train 부분
for epoch in range(epochs):
  losses = []
  print("{}/{} Epochs".format(epoch+1, epochs))
  # mixup 사용해보기
  for x,y in tqdm(train_loader):

    batch_size = x.size(0)

    x = x.to(DEVICE)
    y = y.to(DEVICE)

    x, targets_a, targets_b, lambda = mixup_data(x, y,1, USE_CUDA)

    outputs = model(x)

    loss = mixup_criterion(criterion, outputs, targets_a, targets_b, lambda)

    losses.append(loss.item())


    optim.zero_grad()
    loss.backward()

    optim.step()

  train_loss = np.mean(losses)
  print("Loss is : ",train_loss)
  all_loss.append(train_loss)
728x90