반응형

논문 배경 설명

  • Fine-tuning Image Transformers using Learnable Memory은 2022년 CVPR에 제출된 Google 논문이다.
  • memory token 개념을 사용하여, ViT에서 과거 task에 대한 정보를 저장하여, 성능을 유지하고, 새로운 task에 대한 학습을 진행할 수 있는 방법을 소개했다. 
  • 저자들은 지속 & 확장 가능한 memory 개념으로 소개하는데, 만약 진짜라면, external memory 개념으로 탈부착 가능한 memory가 될 수도 있지 않을까? 하는 생각이 든다. 

 

Abstract

  • 이 논문에서는 Vision Transformer model에 학습 가능한 memory token을 넣은 새로운 ViT 모델을 소개한다.
  • 이 모델의 방법에서는 하나의 task에서 학습한 parameter들을 새로운 task 학습에서 활용 가능하다.
  • 이를 위해, 각 layer들에 특정 dataset에 대한 contextual 정보를 제공하는 "memory token"이라는  learnable embedding vector들을 도입하였다. 
  • 이러한 간단한 변형은 transfer learning에서 단순 head만을 fine-tuning 하는 것보다 큰 성능 향상을 보이고, 연산 비용이 매우 큰 full fine-tuning에 비교해서도 약간의 성능 차이만 보인다. (약간 낮다.)
  • 또한, 이 논문에서는 computation 재사용으로 새로운 downstream task들에 사용가능한 attention-masking 방법을 소개한다.

 

Introduction

[배경]

  • ViT 모델은 일반적으로 대량의 데이터들을 통해 학습되고, 다양한 downstream task에서 성능 향상을 위해 fine-tuning 하는 방법을 사용한다. 
  • 높은 정확도를 위해, 전체 모델을 목적에 맞는 task에 fine-tuning하는 것이 가장 좋은 방법이다.

[문제]

  • 하지만, 일반적으로 Transformer 기반 모델들은 많은 수의 parameter로 구성되어 있기 때문에, fine-tuning 과정에 연산 cost가 크고, 특히, 전체 모델 fine-tuning 방법은 learning rate에 민감하다는 문제가 있다. 

[소개]

  • 이 논문에서는 transformer의 각 layer에 learnable token을 새로 추가하여, pre-trained model을 구성하는 새로운 방법을 소개한다. 
  • 새로운 token들은 최종 prediction 성능 향상에 사용될 수 있는 contextual 정보들을 포함한 영구적 memory처럼 동작한다.
  • 또한, 이러한 token은 pixel 기반 patch부터 최종 concept 수준까지 다양한 수준의 추상화 개념을 나타낼 수 있다. (pixel 정보부터 다양한 문맥 정보까지 모두 포함할 수 있다.)

[결과]

  • 새로운 방법은 downstream task에서 기존 head를 fine-tuning한 모델보다, 큰 성능 향상을 보였다. 
  • 또한, 이러한 아키텍처 디자인은 약간의 computing cost 증가만으로, 새로운 taksk를 학습하면서도, 기존 task에 대한 성능을 유지할 수 있게 한다. (기존 모델들은 새로운 task를 학습하면, 이전 task에 대한 성능이 떨어짐)
  • 이를 위해, 적절한 attention masking이라는 새로운 방법을 소개하여, 과거 task에 대한 정보를 memory에 저장하는 방식을 사용한다. 이러한 방식은 continual learning의 개념처럼, 계속하여 새로운 기능을 더하여 다양한 task에 모두 활용 가능한 하나의 모델로 활용될 수 있다.

 

Memory Model

  • Base mode로는 original ViT 논문의 구조를 그대로 사용한다. (다만, 이 논문에서는 classification model들만을 고려하기 때문에, decoder는 사용하지 않는다. )
  • 일반적인 image transformer의 input은 다음과 같다. (Epos : positional embedding, Xcls : class token)

  • 논문에서는 새로운 memory 정보를 더하기 위해, 이 input에 m개의 learning embedding(Emem)을 concatenate해준다.

  • 즉, N+1+m token이 Transformer encoder layer들의 input으로 사용된다.
  • 각 layer들은 일반 ViT의 layer들과 거의 비슷하다. 유일하게 다른 점은 self attention module의 처음 N+1 token들만 output으로 보낸다는 점이다. (m개의 token들은 다음 layer로 보내지 않음)
  • 따라서, l번 layer의 output은 N+1개의 token을 가진 y_l로 명명하면, 연속적인 layer들은 모두 아래와 같은 pattern의 input을 받는다. (전 layer에서 token N+1개와 memory token m개)

  • 전체 network 구조는 아래와 같다. 

 

[Fine-tuning with full attention]

  • 이 모델에서 memory의 주된 용도는 fine-tuning에서의 활용이다.
  • 이를 위해, randomly-initialized memory token을 제시하고, gradient descent를 활용하여 memory token을 학습한다. 
  • 이 방법은 좋은 결과를 보여주지만, 이렇게 학습된 model은 hidden activation들의 변화가 일어나, 과거 task에 더 이상 활용 불가능하다.

[Attention masking for computation reuse]

  • 새로운 task만을 위한 fine-tuning에서는 문제가 되지 않지만, 앞선 task의 성능을 유지하면서, 새로운 task를 학습하고 싶은 경우에는 활용 불가능하다.
  • 이 논문에서는 기존 dataset class token을 유지하면서, 새로운 dataset class token에 대한 memory 구조를 사용한다. 
  • 결과적으로, parameter들과 computation을 reuse 하여 동일 input에 대한 multiple task들을 처리할 수 있다. 
  • 이를 위해, original class token 및 input patch들이 새로운 dataset이 사용하는 memory token 및 new class token에 활용되지 않도록 막는 attention mask를 사용한다.  (attention mask의 동작은 아래와 같다. 아래 그림처럼, 해당하는 학습에 대한 class token만 유지하고, 다른 class들은 masking 한다. 별표가 mask)
  • 각 task의 head는 각 dataset token에 연결된다. 

[model concatenation]

  • Attention masking은 새로운 task 확장을 위한 memory 추가에 이용될 수 있다.
  • 새로운 dataset에 대한 model 학습 시에는 attention masking을 이용하여 이전 dataset들에 대한 참조를 막고, 새로운 dataset에 대해 학습하는 방법을 사용한다. 
  • 아래 그림처럼, 각기 독립적으로 학습된 memory를 연결하여, 모델을 구성한다. 

Experiments

[실험 setup]

  • ViT-B/32 base transformer model을 base 모델로 사용하였고, ViT original paper에서 제공된 Imagenet-21K pretrained model을 사용했다. (80M parameters)
  • orginal ViT의 fine-tuning 방법을 따라, cosine learning reate schedule 등의 fine-tuning setup을 그대로 사용했다. 
  • batch size는 512이고, 20000 step의 fine-tuning을 진행했다. 
  • SGD를 사용했고, gradient clipping을 사용했다. 5-step의 linear rate warmup도 했다.
  • Memory는 N(0,0.02)로 initialization 시켰다. 
  • 성능 측정을 위한 dataset으로는 CIFAR-100, i-Naturalist, Places-365, SUN-397을 사용했다. 

 

[실험 모델: Baseline fine-tuning]

 

Full fine-tuning

  • 전체 model을 fine-tuning 함. 가장 expensive 하고, 각 task가 전체 model이 필요하기 때문에, 실용성이 가장 떨어짐. overfitting 가능성이나, learning rate에 민감함. 

Head-only fine-tuning

  • classifier의 head만 fine-tuning 함. 이 방식은 pre-trained의 mmbedding을 재활용함. 가장 큰 장점은 parameter들과 compute를 재사용할 수 있다는 것.

Head + Class token

  • head와 class token을 fine-tuning함. 이 방식에서는 input token attention이 새로운 class token에 따라 바뀌면서, 연산 재사용이 불가능함. 

[실험 모델: memory fine-tuning]

 

Memory + head + class token

  • memory fine-tuning 모델로 부르는, 논문에서 소개된 모델임. 1,2,5,10,20 cell에 대한 실험을 진행함. 각 layer에서 20개 이상에서는 더 이상 성능 향상이 일어나지 않음. cell 5개가 알맞았음. 

Memory with attention mask

  • head-only fine-tuning과 Head + Class token의 장점을 결합한 방법. Head + Class token보다 높은 성능을 보이고, full-attention fine-tuning보다는 약간 낮은 성능을 보임. 이 방법의 가장 큰 장점은 독립적으로 다양한 task를 fine-tuning 할 수 있다는 것이고, 여러 연산을 하나의 모델로 모을 수 있다는 것.

 

[Transfer Learning 성능 비교]

 

  • full fine-tuning은 learning rate에 민감하다. large learning tate에서 큰 성능 저하를 일으켜, 이 부분에서는 memory와 head-only fine-tuning이 오히려 더 좋은 성능을 보인다. 
  • 아래 그림에서 확인할 수 있듯, memory를 이용한 방법들이 다른 방식의 fine-tuning보다 좋은 성능을 보인다. 

  • 각 fine-tuning의 가장 optimal learning rate에서의 성능을 비교해 보았을 때, 결과는 아래 표와 같다. 
  • 많은 데이터셋에서 5~20 cell 사이의 memory fine-tuning이 좋은 성능을 보인다. 

 

Conclusion & Limitation

  • 이 논문에서는 memory 구조를 transformer model에 결합한 새로운 방법을 제안했다.
  • memory를 사용한 새로운 모델은 fine-tuning에서 좋은 성능을 보였고, 다양한 task 학습을 가능하게 했다.
  • memory yoken은 attention model의 중요한 부분으로, lifetime and continuous learning에 중요한 요소가 될 것으로 생각된다. 
  • 몇 가지 한계와 future work를 소개한다.

[scaling memory]

  • 저자들은 memory token이 특정 숫자를 넘어가면, 성능 향상이 줄어드는 것을 발견했다. 
  • 한 가지 가능한 방법은 Top-K memory token만 참조하도록 제한을 거는 것이다. 이러한 방법은 불필요한 token들의 참조를 막아, background noise 등을 제거할 수 있을 것이다.

[combining episodic memory with learnable memory]

  • Episodic memory와 함께 사용하는 방법도 생각해 볼 수 있다.

[incremetal model extension]

  • 논문에서는 multiple attention masking model이 독립적으로 학습되어 하나의 모델로 합쳐지는 방법을 사용하였다. 하지만, 순차적인 학습으로 인한 중간 메모리 축적으로 생기는 이점(아마, 각기 다른 학습 간의 시너지를 의미하는 것 같음)은 커리큘럼 학습에 중요하고, 이것이 향후 연구의 주제가 될 것이다. 

 

논문 총평

  • 매우 아이디어가 간단하고, 아이디어에 대한 실험 결과가 매우 명확한 논문이다. 
  • 과거에 Knowledge distilliation을 잠시 파본 기억이 있는데, CNN 기반에서 distillation이 매우 어렵다고 생각했었는데, ViT 기반에서 memory token 개념을 사용하여 해결한 것이 매우 인상적이다. (그 후론 CNN 기반에서 방법을 찾아본 적이 없어서, 비슷한 아이디어가 있는지는 모르겠다.)
  • 다만, 실제 데이터에서 잘 working 하는지는 직접 실험을 해봐야 판단이 가능할 것 같다.

 

Reference

Sandler, M., Zhmoginov, A., Vladymyrov, M., & Jackson, A. (2022). Fine-tuning image transformers using learnable memory. In Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (pp. 12155-12164).

반응형

MobileViT 배경 설명

  • MobileViT은 2022년 Apple에서 ICLR 2022에 제출한 논문이다. (Apple이여서, mobile에 대한 CNN이 더욱 필요했을 것이다.)
  • CNN에서 mobilenet이 나왔듯, ViT에서도 light cost에 초점을 맞춘 논문이 등장하였다.

 

Abstract

  • mobile 환경에서 구동 가능할 정도의 가벼운 vision task CNN 모델이 등장하였었다. (mobilenet) 
  • 하지만, CNN과 달리 ViT는 최근 많은 vision task에 사용됨에도 불구하고, global representation들을 활용하기 위한 self-attention 구조를 사용하기 때문에, CNN에 비해 모델이 무겁다.
  • 이 논문에서는 CNN과 ViT를 결합하여 mobile vision task에서 구동 가능한 가벼운 ViT 모델을 만들 수 있는가? 에 대한 답을 제시한다. 
  • 이를 위해, 가볍고, 좋은 성능을 내고, 다양한 용도로 사용할 수 있는 MobileViT를 소개한다. 
  • 실험에서는 MobileViT가 다양한 task와 dataset들에서 CNN과 ViT 기반의 모델보다 압도적인 성능을 보여준다.

 

Introduction

[배경]

  • ViT의 소개 이후로, ViT의 연구 트랜드는 model의 parameter의 양을 늘리면서, 좋은 성능의 모델을 만들어내는 것이었다. (LLM처럼...)
  • 하지만, 이런 모델 크기의 증가는 model의 용량 증가와 속도 저하등을 일으킨다. 
  • 실생활에서는 mobile 기기 같은 제한된 H/W에서 구동되어야 하는 task들이 많이 존재하기 때문에, 가볍고 빠른 모델에 대한 요구사항이 있다. 
  • 이를 위해, ViT의 parameter 개수를 줄이면, 오히려, 가벼운 CNN들보다도 좋지 않은 성능을 보여준다. 따라서, 어떻게좋은 성능을 유지하면서 가벼운 ViT를 만들 것인지에 대한 심도 깊은 고민이 필요하다.

[CNN + ViT]

  • 일반적으로 ViT는 CNN에 많은 wieght를 필요로 하고, optimize가 어렵다. 예를 들어, ViT 기반의 segmentation network는 345 million의 parameter가 필요한데, 비슷한 성능의 CNN은 59 million으로, ViT 기반이 비효율적이다. 이것은 ViT가 CNN의 특성인 image specific inductive bias가 부족하기 때문이다.
  • 좋은 성능의 ViT 모델을 위해서라면, convolution과 transformer의 하이브리드 방법을 채택하는 것이 효과적일 수 있다.
  •  하지만, 기존 시도된 하이브리드 방법들은 아직 매우 큰 model size를 가지고 있고, data augmentation에 민감하다는 단점이 있다. 

[MobileViT]

  • 이 논문에서는 제한된 H/W 리소스에서도 효과적으로 좋은 성능을 보이는 ViT 모델을 만들고자 한다. 
  • 모델의 효율성 측정을 위해 보통 사용되는 FLops는 mobile 장비 등에서 성능 측정에는 충분하지 않다. 이는 FLOPs는 memory access나 parallelism 정도, platform 특성등을 고려하지 않기 때문이다. 
  • 따라서, 논문에서는 FLOPs을 optimize 하기보다는, light weight, general-purpose, low latency에 초점을 맞췄다.  
  • 이 논문에서는 CNN의 spatial inductive bias와 ViT의 global processing에 장점들을 결합가능한 MobileViT model을 소개한다.
  • 특히, local 정보와 global 정보를 모두 encoding 할 수 있는 MobileViT block은 효과적인 representation을 포함한 feature를 만들 수 있게 해 준다.

 

MobileViT : A light-weight Transformer

  • 일반적인 ViT model에서는 (H X W X C) 크기의 이미지를 P 사이즈의 patch들로 자르고, flatten 하고, projection 하여, (N X d) 크기의 inter patch representation으로 만든다.  이때, comnputational cost는 O(N*N*d)이다. (N: number of patch)
  • 이러한 ViT 구조의 모델들은 CNN에 내재된 spatial inductive bias를 무시하기 때문에, CNN에 비해 더 많은 parameter를 필요로 한다. 
  • 또한, 이런 구조들의 모델은 L2 regularization이나, overfitting을 피하기 위해 많은 data augmentation이 필요한 등 optimization이 어렵다. 

 
[MobileViT 아키텍처]
 
MiobileViT의 핵심 아이디어는 Transformer를 convolution으로 사용하여 global representation들을 학습하는 것이다. 
 

  • MobileViT block 
    • MobileViT block은 model이 input의 local과 global 정보를 적은 paramter 안에 모두 담을 수 있도록 하는 것이 목적이다. 
    • 우선 MobileViT는 (n X n) 개의 convolutional layer와 (1 X 1) convolution을 수행해 준다. 이로 인해, local representation을 포함하게 된다. 
    • global representation을 학습하기 위해, 앞서 covolutional layer의 output을 flatten 하고 겹치지 않도록, patch로 나눠준다. 그러고 나서, 이 patch들을 input으로 Transformer에 넣어준다. 
    • 이로 인해, 아래 그림처럼, local 정보를 포함하면서, global 정보까지 포함할 수 있는 feature가 완성되게 된다.

 

  • Light Weight
    • MobileViT는 image specific inductive bias를 사용할 수 있기 때문에, 일반 ViT에 비해 훨씬 더 가벼운 모델로 학습이 가능하다. (dimension 등을 줄일 수 있음)
  • Computational Cost
    • MobileViT와 ViT의 computational cost를 비교하면, 각각 O(N*N*P*d)와 O(N*N*d)로 이론적으로는 MobileViT가 더 비효율적으로 보인다. 하지만, 실제로는 MobileViT가 DeIT ImageNet-1K image classification에서 2배 적은 FLOPs으로 1.8% 좋은 성능을 낼 정도로 더 효과적이다.
    • 이것은 더 가벼운 모델로 학습이 가능하기 때문이다. 

 
[Multi-scale sampler for training efficiency]

  • 일반적으로 ViT 기반의 모델들은 fine-tuning 시에 다양한 스케일의 representation들을 학습한다. 이 과정에서 Positional embedding을 사용하는데, 이는 input size에 기반하여 interpolation이 필요하고, interpolation 방법에 따라 성능에 영향을 미치게 된다. 
  • CNN과 마찬가지로, MobileViT에서도 이러한 positional embedding이 필요가 없다. 
  • MobileViT에서 이러한 다양한 스케일의 representation들을 학습하기 위해, batch size를 변경시키는 방법을 사용했다. 다양한 spatial resolutions set을 만들어 놓고, 각 bach 시, resoluton을 무작위로 뽑고, 해당 resolution에 따라 batch size를 유동적으로 변경하여 학습했다. (small spatial resolution에는 많은 batch) 
  • 이러한 학습 방법은 더 빠른 optimize가 가능하도록 하였다. 

 

실험 결과

  • MobileViT 모델을 scratch부터 ImageNet-1K classification dataset으로 학습했다.
  • multi-scale sampler로 각각 (160,160), (192,192), (256,256), (288,288), (320,320) 해상도를 사용했다. 
  • 성능 측정은 top-1 accuracy로 진행했다. 

[CNN과 비교]

  • MobileViT가 CNN 기반의 MobileNet 등의 light-weight CNN이나, ResNet 등의 일반적인 CNN의 성능을 압도했다.

[ViT 비교]

  • ViT와 비교해서도 좋은 성능을 보인다. 특히, DataAugmentation에 따라 성능이 크게 바뀌는 다른 모델들과 달리, Basic Augmentation만으로도 다른 ViT보다 좋은 성능을 보인다. 

 
 

총평

  • 매우 아이디어가 간단하고, 효과적인 것 같다.
  • 논문 내용만 보면, 장점만 많아서, 진짜인지 직접 돌려보고 싶다. 

 

Reference

Mehta, S., & Rastegari, M. (2021). Mobilevit: light-weight, general-purpose, and mobile-friendly vision transformer. arXiv preprint arXiv:2110.02178.

반응형

DETR 배경 설명

  • DETR은 2020년 Facebook AI 팀에 의해 발표된 논문이다. 
  • Transformer를 Object Detection 분야에 최초로 적용한 논문이다.

 

Abstract

  • 이 논문에서는 한 번에 물체의 위치와 classification을 진행할 수 있는 DETR이라는 새로운 네트워크를 소개한다.
  • 기존에 Object Detection에서 존재하던 NMS(Non-maximum suppression)이나, anchor box 생성 같은 manual 작업들을 제거한 detection pipeline을 구성하였다.
  • DETR의 주요 아이디어는 bipartite matching을 통한 unique predictions를 강제하는 "set-based global loss"와 transformer의 encoder-decoder 구조이다.
  • object query가 있을 때, DETR은 object들과 전체적 이미지의 context 간의 관계를 추론하고, 이 정보를 기반으로 최종 예측을 병렬적으로 수행한다.
  • 새로운 모델은 구조적으로 간단하고, 별도의 라이브러리를 사용하지 않는다는 장점이 있다.
  • DETR은 accuracy와 run-time 측면에서 Faster R-CNN 기반의 최적화된 모델들에 버금갈 정도의 좋은 성능을 보인다. 

 

Introduction

[배경]

  • 기존 Object detection 방법들은 미리 구성해 놓은 anchor box를 이용하여, 많은 object들의 후보군을 만들어 놓고, 이를 regression과 classification을 통해, 예측하고, 비슷한 예측결과를 지우는(NMS) 과정들을 통해 진행된다.
  • 이러한 과정을 간단하게 하기 위해, 이 논문에서는 이미지에서 직접 물체의 위치를 추론하는 방법으로 접근하고자 한다.
  • 이미 음성인식등의 다른 분야에서는 이러한 end-to-end 방식이 성공을 거두었지만, object detection 분야에서는 이러한 시도들이 prior knowledge를 다른 방식으로 사용하거나, 성능 상에서 경쟁력이 없었다. 

[소개]

  • 이를 위해, 이 논문에서는 object detection의 학습 과정을 direct set prediction problem으로 접근한다. 
  • 논문에서는 transformer의 encoder-decoder 구조를 사용하였다. transformer의 self-attention 메커니즘은 비슷한 예측들을 제거하는데 적절한 constraints가 될 것이다. (아마, NMS를 대체할 수 있을 것이다.)
  • DETR은 모든 object를 한번에 예측하고, 예측값과 ground-truth object들 간의 bipartite matching을 이용한 set loss function을 통해 end-to-end로 학습된다.
  • 이를 통해서, 기존 object detection에서 prior knowledge를 담은 anchor box나 NMS 등을 제거할 수 있었다. 

[기존 set prediction과의 비교]

  • 기존의 direct set prediction과 비교하면, DETR은 bipartite maching loss와 transformer를 이용한 parallel decoding의 결합이 차이다. 
  • 기존 방식들은 RNN 방식에 의존하여, 예측 object들의 배열에 의존하는 것에 반해, DETR은 transformer를 이용한 parallel 연산으로 예측 object들의 배열에 의존하지 않는다.

[실험]

  • DETR을 가장 많이 사용되는 object detection의 dataset인 COCO에서 Faster R-CNN 기반의 좋은 성능 모델들과 비교해 보았다.
  • 최근(그 당시) 모델들은 최초 Faster R-CNN에서 구조 변화를 통해 성능이 크게 향상되었음에도 불구하고, DETR은 그들과 필적할만한 좋은 성능을 보였다.
  • 조금 더 상세하게는, DETR은 large object들에 대해서는 더 좋은 성능을, small object들에 대해서는 더 낮은 성능을 보였다. 

 

 

DETR Model

  • DETR의 핵심요소는 (1) 예측과 ground truth 간의 unique matching을 만들어주는 set prediction loss와 (2) object 집합들을 예측하고, 그들 사이의 관계를 modeling 하는 아키텍처이다. 

[object detection set prediction loss]

<1번째 : matching 구하기>

  • 첫 번째로, DETR은 고정된 개수 N개에 대한 예측을 한다. 이때, N은 일반적인 이미지의 object 개수보다 큰 숫자이다. 
  • 이러한 구조의 학습과정에서 주요 이슈는 예측된 object를 ground truth와 어떻게 비교하냐이다. 이를 위해, 예측과 ground truth 간에 최적의 matching을 만드는 loss를 사용하였다.
  • y가 object들의 ground truth이고, y는 no object의 class도 가질 수 있다고 할 때, 예측과 ground truth 간의 bipartite matching을 갖는 조합을 찾기 위해 아래 식을 계산한다.

  • 위 식에서 L_match는 pair-wise matching cost인데, 이 는 class의 prediction과 예측과 ground-truth 간의 box 차이를 모두 고려한 cost이다.
  • 이러한 방식은 기존 detector들의 방식의 anchor 등과 유사한데, 그들과의 차이점은 기존 detector에서는 비슷한 예측들이 많이 존재하는데, matching loss에서는 1대 1 매칭이 된다는 것이다.

<2번째 : loss 구하기>

  • 두 번째로, 앞서 구했던 전체 matching 쌍들에 대해 Hungarian loss function을 계산한다. 이때의 loss는 일반적인 object detection의 loss와 비슷하게, class prediction에 대한 loss와 box loss의 합이다. 

  • 위의 식에서 우선 no object class의 matching cost는 prediction의 영향을 받지 않는다. (상수이기 때문에 학습 과정에서 영향을 미치지 않는다.)
  • 위의 식에서 box loss를 구성할 때, 기존 object detection의 box loss와 달리, loss의 scale에 대한 이슈가 있다. (기존에는 anchor에 대한 상대적 위치를 loss로 썼기 때문에) 이를 해결하기 위해, box loss로 주로 사용되는 L1 loss 뿐 아니라, IoU loss를 추가적으로 사용했다. 
  • 따라서 box loss는 아래와 같다. 

 

 

[DETR 아키텍처]

  • DETR의 전체 아키텍처는 아래 그림에서 보이는 것처럼 매우 간단하다. 

  • DETR은 크게 3가지 주요 구조로 구성되어 있다. (1) compact feature를 뽑기 위한 CNN backbone (2) encoder-decoder transformer (3) 최종 예측을 위한 feed forward network(FFN)
  • DETR은 Pytorch로 50줄 미만으로 inference code를 짤 수 있을 만큼 간단하다.
  • Backbone : 이미지를 CNN backbone을 통과시켜, feature를 얻는다. 일반적으로 2048 X (H/32) X (W/32) shape의 feature를 뽑았다.
  • Transformer encoder : 우선 1X1 convolution을 통해, channel dimension을 줄여줬다. encoder의 input으로 sequence 값이 필요하기 때문에, spatial 부분(H와 W)을 HW개의 sequence로 만들었다. encoder는 일반적인 transformer의 encoder이다. transformer 구조는 배열 순서에 무관하게 연산되기 때문에, 고정된 positional encoding 값을 더해서 이를 보충했다.
  • Transformer decoder : decoder도 일반적인 transformer의 구조를 따랐다. 조금 다른 점은 DETR은 N개 object를 병렬적으로 각 decoder layer에서 연산하였다는 점이다. decoder도 마찬가지로 배열 순서에 무관하게 연산되기 때문에, positional encoding을 decoder의 각 attention layer에 추가하여 연산한다. decoder에 의해 N개의 object query들은 output embedding으로 변환되고, 각각 독립적으로 FFN에 의해 box coordinate와 class label을 예측하게 된다. 
  • FFN : 최종 prediction은 ReLU activation을 사용하는 3개의 layer에 의해 연산된다. FFN은 box의 중심 좌표와 height, width와 class label을 예측한다. 최종 N개의 결과가 나오는데, 이중 no object를 제외하고, 나머지들이 DETR의 최종 예측이 된다. 
  • Auxiliary decoding loss : auxiliary loss를 사용하는 것이 decoder의 학습 중 각 class의 정확한 object 개수를 추정하는 데에 도움이 된다는 것을 발견했다.  모든 prediction FFN은 parameter를 공유한다. 

 

 

Experiments

  • COCO dataset에서 Faster-RCNN 기반의 최근(그 당시) object detection model과 필적할 정도의 좋은 성능을 보인다. 

  • 그밖에 encoder size나, selt-attention, segmentation에 적 등의 실험이 있다. 논문을 참조 바란다.

 

Reference

Carion, Nicolas, et al. "End-to-end object detection with transformers." European conference on computer vision. Cham: Springer International Publishing, 2020.

 

 

총평

  • Transformer가 당연(?)하게도 OD 분야에 적용되었다. 2020년에 발표되어 늦은 감이 있지만, 지금이라도 읽어서 다행이다.
  • Object Detection을 처음 접했을 때, anchor box를 사용하는 것과 NMS를 사용하는 것이 매우 비효율적이라고 생각하면서도 어쩔 수 없다고 생각하였는데, 결국 해결되는 것 같다. 
  • OD 논문을 열심히 읽어야겠다.
반응형

NaViT 배경 설명

  • NaViT은 Google DeepMind에서 2023년 7월(리뷰 시점에서 1달 전)에 나온 논문이다. 
  • Model 크기에 맞게 Input size를 조정하던 기존의 CNN 구조에서 벗어나, ViT로 다양한 resolution의 input을 학습하고자 하였다. 

 

Abstact

  • computer vision model에서 이미지 처리 전에 고정된 이미지 resoultion은 최적이 아님에도 불구하고, 보편적으로 사용된다.
  • ViT 같은 모델은 flexible한 sequence-based modeling을 제공하기 때문에, input sequence 길이를 가변적으로 사용 가능하다.
  • 이 논문에서는 ViT의 특징을 이용한, 학습과정에서 무작위의 resolution과 aspect ratio을 다룰 수 있도록 하는 sequence packing을 사용했다. 
  • 이 논문에서는 large-scale의 supervised 및 contrastive image-text pretraining을 통해 모델의 효과성을 보여준다.
  • 또한, 이 모델은 image, video classification이나, object detection, semantic segment등에 transfer 되어, 성능 향상에 사용될 수 있다.
  • inference time에서, input resolution의 유연성은 time cost와 performance의 trade-off 사이에서 최적을 찾을 수 있게 한다.

 

Introduction

[배경]

  • ViT는 간단하고, flexible, scalable 하며, 기존 CNN의 대체로 사용할 수 있다. 
  • ViT는 input image들을 resize 하고, 고정된 aspec ratio의 patch들로 잘라서, 모델의 input으로 사용한다.
  • 최근 고정된 aspect ratio을 사용하는 것을 대체할 방법을 제시하는 논문들이 등장하고 있다. 
  • FliexiViT는 다양한 patch size를 하나의 architecture에서 다룬다. 이것은 각 training step에서 patch size를 random sampling 하고, reszing algorithm이 초기 convolutional embedding이 다양한 patch size를 다룰 수 있게 하기 때문이다. (이 논문도 읽어 봐야겠다.)

[소개]

  • 이 논문에서 다른 이미지들에서의 여러 patch들이, single sequence로 묶여 처리하는 NaViT라는 모델을 소개한다. 논문의 아이디어는 NLP에서 다양한 example들을 singlel sequence로 처리하는 example packing에서 영감을 받았다.
  • NaViT은 다음과 같은 장점이 있다.
  • 학습 과정에서 training cost를 줄이기 위해, resolution을 randomly sampling 한다.
  • NaViT는 다양한 resolutons에서 좋은 성능을 보이고, cost-performance가 smooth 한 trade-off를 제공한다.
  • 고정된 batch shape은 aspect-ratio preserving resoltion sampling이나, variable token dropping rates, adaptive computation 등의 새로운 아이디어를 이끈다.
  • 동일한  computational cost 내에서, NaViT는 ViT를 능가하는 성능을 보인다.  이는 NaViT 한정된 computational cost 내에서 더 많은 양의 training example을 처리할 수 있기 때문이다.
  • 향상된 efficiency는 fine-tuning process에서도 이어진다. NaViT는 pre-training과 fine-tuning에서 다양한 resolution으로 학습되었기 때문에, 무작위 resolution으로 평가하였을 때, NaViT는 더욱 효과적이다. 

 

Method

  • 기존 딥러닝 모델들은 fixed 된 이미지 사이즈를 사용한다. 이를 위해, 이미지를 resizing 하거나, padding을 하는데, 성능이 떨어지고, 비효율적이다.
  • 한편, Language Modeling에서는 example packing(다양한 example들을 하나의 sequence에 묶어서 학습을 가속화함)을 이용하여, 고정된 sequence length의 한계를 넘는다. 
  • 이 논문에서는 image를 token으로 대하여, ViT도 같은 방법으로 효과를 볼 수 있음을 보여준다. 이를 Patch n'Pack이라 명명한다. 또, 이미지가 native resolution으로 학습될 수 있기 때문에, 이 모델을 NaViT로 명명한다.

[구조 변화]

  • NaViT는 ViT를 기반으로 만들어졌다. Patch n'Pack을 가능하게 하기 위해, 몇 가지의 구조적 변화를 주었다.

1. Masked self attention and masked pooling

  • example들이 서로 겹치는 것을 막기 위해, self-attention masked를 추가하였다.
  • 마찬가지로, encode 최상단의 masked pooling은 token을 pooling 하는 것을 목표로 한다. sequence 내의 각 example은 single vector representation으로 표현된다. 

2. Factorized & fractional positional embeddings

  • 무작위 resolution과 aspect ratio를 다루기 위해, factorized position embeddings를 제안한다. 
  • factorized position embeddings에서는 embeddings을 x방향과 y방향으로 decomposition 하고, 각각 합해진다.
  • 2개의 스키마를 고려하였는데, absolute embeddings와 factional embeddings이다. 특히, fractional embeddings는 상대적 거리이기 때문에, 이미지 사이즈와 무관하지만, original aspect ratio가 깨질 수 있다. 
  • 학습한 embedding과 sinusoidal embeddings, NeRF를 사용하여 학습된 Foueier positional embeddings을 고려한다.

 
[Training changes] 

  • Patch n' pack을 이용하여 학습과정에서 몇가지 새로운 테크닉을 사용할 수 있다. 

1. Continuous Token Dropping

  • Token dropping (학습 과정에서 input patch를 무작위로 빼는 것)은 학습을 빠르게 하기 위해 고안되었다. 
  • 기존 Token dropping에서는 모든 example들에서 동일한 비율로 token이 drop 되지만,  continuous token dropping은 이미지마다 drop 비율이 달라질 수 있다.
  • 이로 인해, 학습이 빨라지고(처리 token 양이 줄기 때문) , 학습 시에 완전 이미지(drop 안 한 이미지)도 같이 학습할 수 있다는 장점이 있다.

2. Resolution sampling

  • NaViT은 original image의 aspect ratio를 유지하면서, random sampling 된 사이즈를 이용한다. 
  • original ViT에서는 작은 이미지를 통해 throughput이 커지면, performance도 증가하는 특징을 가지고 있다. 
  • NaviT은 다양한 resolution을 학습 시에 사용하기 때문에, 높은 throughput과 큰 이미지로 학습이 모두 포함되기 때문에, original ViT보다 성능 향상을 보인다. 

 
[Efficiency of NaViT]

  • NaViT의 computational cost에 대한 장이다.

1. Self attention cost

  • 원래 이미지의 patch를 자를수록 computational cost가 매우 증가하지만(quadratic 하게), Transformer의 hidden dimension이 늘리면, computational cost가 original image를 한 번에 처리하는 것보다 아주 조금만 늘어난다.
  • 매우 긴 sequence를 사용하면, memory cost가 많아, 속도가 느려지는 현상이 있는데,  memory-efficient 방법을 사용하여 이 문제를 해결하였다.

 
2. Packing, and sequence-level padding

  • prediction을 위한 최종 sequence length는 동일해야 한다. 
  • 길이를 맞추기 위해, example들을 perfect combination 하는 것이 아닌, fixed length가 되도록, 더해서 맞추거나, padding을 사용한다. 
  • padding 되는 toekn은 전체의 2% 이하이기 때문에, 간단한 방법으로 충분하다.

 
3. Padding examples and the contrastive loss

  • per-token loss가 직관적이지만, 많은 computer vision model들은 example 단위의 loss를 구한다. 
  • 이를 도입하기 위해서는 example 개수의 max를 정해놓고, 그 이상은 drop 하는 방법을 사용한다. 그런데, 이럼 학습 시에 아무것도 학습하지 않지만, computational cost를 낭비하는 상황이 발생한다.
  • contrastive learning은 이 상황에 취약한데, time과 memory의 loss computational scale이 quadratic 하게 증가한다.
  • 이를 방지하기 위해, chunked contrastive loss라는 방법을 사용하는데, softmax 계산을 위해 모든 데이터를 모으는 것이 아닌, local device subset에 각각 데이터를 모으고, global softmax normalization을 위한 통계값만 뽑는 형식이다.
  • 이로 인해, 최대 example 수를 늘릴 수 있다.  

 
 

Experiments

  • NaViT은 기본적으로 original ViT을 따랐다. 
  • NaViT을 2개 setup으로 학습했다. classification training으로 JFT-4B를 사용했고(sigmoid cross-entropy loss 사용), contrastive language-image training으로 WebLI를 사용(contrastive image-text loss 사용)했다.
  • FLAX  library를 이용했고, JAX로 구현했다. 

 
[Improved Training Efficiency and performance]

  • 동일 computational cost에서 NaViT은 ViT을 능가한다. 
  • 동일 성능(Accuracy)을 위해, NaViT은 ViT보다 4배 이상의 빠르게 학습되었다.  

 

 
[variable resolution의 장점]

  • variable-resolution pre-training : fixed image로 학습한 최고의 결과도 variable resolution과 동일할 정도로, variable resolution이 우위에 있다.
  • variable-resolution fine-tuning : variable resolution으로 fine-tuning 한 게 성능이 더 좋고, fine-tuning을 low resolution으로 했더라도, higher resolution에 대한 성능을 유지하는 것을 보여준다. 

 
 

Reference

Dehghani, Mostafa, et al. "Patch n'Pack: NaViT, a Vision Transformer for any Aspect Ratio and Resolution." arXiv preprint arXiv:2307.06304 (2023).
 
 

논문 총평

  • 아이디어가 매우 간단하고, 직관적이여서 좋았다. 
  • 사실 아이디어도 중요하지만, 소스가 JAX로 짜놨다고해서, 코드를 한 번 보고 싶다!
반응형

Transformer는 사실, NLP 분야뿐만 아니라, 다양한 분야에서 많이 사용되기 때문에, 그만큼 구현 소스를 쉽게 찾을 수 있다. 나도, Transformer를 자주 사용하지만, 라이브러리에서 읽어오는 형태로 사용하기 때문에, 그 상세 구조에 대해서는 대략적으로만 알고 있다. 이번 기회에 Transformer를 pytorch로 직접 짜보면서 그 구조를 정확히 이해하고자 한다.

 

Full source : https://github.com/daehwichoi/transformer-pytorch/blob/main/model/transformer.py

 

구현 방향

  • 사실, pytorch로 Transformer를 구현한 사례는 google 검색만 해도 굉장히 많이 나온다. 하지만, original transformer를 직접 구현해보고 싶어서, 논문을 그대로 구현하는데 초점을 맞췄다. 
  • 모델 학습을 위한 layer(Dropout 등)나, dataloader는 task마다 다르고, 구현 목적이 Transformer 모델을 구현하는 것이기 때문에, 모델 구현만 진행했다.

 

참고 자료

  • Transformer 논문 내, 구조 설명 부분

2023.05.08 - [NLP 논문] - Transformer (Attention Is All You Need) - (1) 리뷰

 

Transformer (Attention Is All You Need) - (1) 리뷰

Transformer 배경 설명 Transformer는 Google Brain이 2017년 "Attention is All You Need"라는 논문에서 제안된 딥러닝 모델이다. Transformer는 기존 자연어 처리 분야에서 주로 사용되던 RNN, LSTM 같은 순환 신경망 모

devhwi.tistory.com

 

 

구조 설명

  • Transformer는 크게 Encoder 부분과 Decoder 부분, input&output embedding, postional encoding으로 나뉜다.
  • Encoder 부분은 N개의 Encoder가 연결된 구조로 구성되어 있고, Decoder도 N개의 Decoder가 연결된 구조로 구성되어 있다.
  • Ecoder는 크게, Multi-Head Attention(self-attention)과 redidual 부분(residual add  & layer norm), Feed Forward로 구성되어 있다. 
  • Decoder는 크게, Masked-Multi-Head Attention(self-attention)과 resiedidual 부분(residual add  & layer norm), Multi-Head Attention(encoder-decoder attention), Feed Forward로 구성되어 있다.

 

구현 내용 설명

(순서는 내가 구현한 순서이다.)

1. Multi-Head Attention

[Sacled Dot-Product Attention]

  • Multi-Head Attention의 핵심은 scaled_dot_product_attention이다.
  • scaled_dot_product는 Query, Key, Value가 있을 때, Query와 Key의 Transpose의 Matmul(Dot Product)를 통해, similarity를 계산하고, similarity 기반으로 Value 값을 참조한다.
  • Scaled Dot-product는 Network 여러 부분에서 사용되지만, Decoder 부분에서는 masking 처리를 해야 하는 부분이 있기 때문에, mask부분을 포함해서 함께 구현했다.

    def scaled_dot_product_attention(self, q, k, v, mask=None):
        d_k = k.size()[-1]
        k_transpose = torch.transpose(k, 3, 2)

        output = torch.matmul(q, k_transpose)
        output = output / math.sqrt(d_k)
        if mask is not None:
            output = output.masked_fill(mask.unsqueeze(1).unsqueeze(-1), 0)

        output = F.softmax(output, -1)
        output = torch.matmul(output, v)

        return output

[Multi-Head Attention]

  • Multi-Head Attention은 scaled Dot-Product Attention을 query에 해당하는 value 값들을 참조하기 위해 사용하는데, query, key, value를 그대로 사용하는 것이 아니라, 여러 개의 head로 나누고, query, key, value를 linear projection 한 후, 사용한다. 
  • Scaled Dot-Product Attention 이후, 각 head의 value 값을 concat하고, linear layer을 거쳐 output을 낸다.
  • 주의할 점은, sequence의 순서가 중요하기 때문에, contiguous를 사용해서, 순서를 유지한다는 점이다.

class MultiHeadAttention(nn.Module):
    def __init__(self, dim_num=512, head_num=8):
        super().__init__()
        self.head_num = head_num
        self.dim_num = dim_num

        self.query_embed = nn.Linear(dim_num, dim_num)
        self.key_embed = nn.Linear(dim_num, dim_num)
        self.value_embed = nn.Linear(dim_num, dim_num)
        self.output_embed = nn.Linear(dim_num, dim_num)

    def scaled_dot_product_attention(self, q, k, v, mask=None):
    ...
    
    def forward(self, q, k, v, mask=None):
        batch_size = q.size()[0]

        # 순서 유지 때문에 view 후 transpose 사용
        q = self.query_embed(q).view(batch_size, -1, self.head_num, self.dim_num // self.head_num).transpose(1, 2)
        k = self.key_embed(k).view(batch_size, -1, self.head_num, self.dim_num // self.head_num).transpose(1, 2)
        v = self.value_embed(v).view(batch_size, -1, self.head_num, self.dim_num // self.head_num).transpose(1, 2)

        output = self.scaled_dot_product_attention(q, k, v, mask)
        batch_num, head_num, seq_num, hidden_num = output.size()
        output = torch.transpose(output, 1, 2).contiguous().view((batch_size, -1, hidden_num * self.head_num))

        return output

 

2. Residual Add & Layer Norm

[Layer Norm]

  • Layer Norm은 dimension layer 방향으로 평균을 빼고, 표준 편차로 나누는 Normalization 기법이다.
  • 이 부분은 nn.LayerNorm을 통해, 구현할 수 있다. 
   def layer_norm(self, input):
        mean = torch.mean(input, dim=-1, keepdim=True)
        std = torch.std(input, dim=-1, keepdim=True)
        output = (input - mean) / std
        return output

[Add & Layer Norm]

  • 이전 층의 output을 layer norm을 통해, normalization 한 후, residual 값을 더해준다.
class AddLayerNorm(nn.Module):
    def __init__(self):
        super().__init__()

    def layer_norm(self, input):
    ...

    def forward(self, input, residual):
        return residual + self.layer_norm(input)

 

3. Feed Forward

  • Feed Forward는 Fully Connected Layer → Relu →  Fully Connected Layer로 구성되어 있다.

class FeedForward(nn.Module):
    def __init__(self, dim_num=512):
        super().__init__()
        self.layer1 = nn.Linear(dim_num, dim_num * 4)
        self.layer2 = nn.Linear(dim_num * 4, dim_num)

    def forward(self, input):
        output = self.layer1(input)
        output = self.layer2(F.relu(output))

        return output

 

4. Encoder

  • Encoder는 Multi-Head Attention → Residual Add & Layer Norm → Feed Forward → Residual Add & Layer Norm 순으로 구성되어 있다. 
  • Encoder는 단순히, 앞서 선언했던, sub layer들을 연결하는 방식으로 구현했다.

class Encoder(nn.Module):
    def __init__(self, dim_num=512):
        super().__init__()
        self.multihead = MultiHeadAttention(dim_num=dim_num)
        self.residual_layer1 = AddLayerNorm()
        self.feed_forward = FeedForward(dim_num=dim_num)
        self.residual_layer2 = AddLayerNorm()

    def forward(self, q, k, v):
        multihead_output = self.multihead(q, k, v)
        residual1_output = self.residual_layer1(multihead_output, q)
        feedforward_output = self.feed_forward(residual1_output)
        output = self.residual_layer2(feedforward_output, residual1_output)

        return output

 

5. Decoder

  • Decoder는 Masked Multi-Head Attention → Residual Add & Layer Norm → Multi-Head Attention → Residual Add & Layer Norm Feed Forward → Residual Add & Layer Norm 순으로 구성되어 있다.
  • Encoder와 마찬가지로, 앞서 구현해놓은 sub-layer를 연결하면 되지만, 중간 Multi-Head Attention은 Query와 Key를 Encoder의 Output을 사용하기 때문에, 이 점을 명시해야 한다.
  • Decoder는 Ecoder와 다르게, masking을 이용하여, mask를 인자로 받는 것도 주의해야 한다.

class Decoder(nn.Module):
    def __init__(self, dim_num=512):
        super().__init__()

        self.masked_multihead = MultiHeadAttention(dim_num=dim_num)
        self.residual_layer1 = AddLayerNorm()
        self.multihead = MultiHeadAttention(dim_num=dim_num)
        self.residual_layer2 = AddLayerNorm()
        self.feed_forward = FeedForward(dim_num=dim_num)
        self.residual_layer3 = AddLayerNorm()

    def forward(self, o_q, o_k, o_v, encoder_output, mask):
        masked_multihead_output = self.masked_multihead(o_q, o_k, o_v, mask)
        residual1_output = self.residual_layer1(masked_multihead_output, o_q)
        multihead_output = self.multihead(encoder_output, encoder_output, residual1_output, mask)
        residual2_output = self.residual_layer2(multihead_output, residual1_output)
        feedforward_output = self.feed_forward(residual2_output)
        output = self.residual_layer3(feedforward_output, residual2_output)

        return output

 

6. Transformer

  • 전체 Transformer는 Input Embedding, Positional Encoding, Output Embedding, N개의 encoder와 N개의 decoder로 구성되어 있다. 

[positional_encoding]

  • positinal encoding은 짝수번째 token과 홀수번째 token이 각기 다른 식을 따른다. 아래 식에서 i는 hidden dimension 방향의 index이고, pos는 positional 방향(몇 번째 seq인지)을 의미한다.
  • positional encoding은 크게, 두 부분에서 사용되는데, Input과 Output의 sequence length 길이가 다를 수 있기 때문에, 이것을 인자로 받는 형태로 구현했다.
  • 마지막에 self.register_buffer는 추후, model parameter 학습 시, psotional encoding이 학습되지 않도록 막아주기 위한 용도이다. 

    def position_encoding(self, position_max_length=100):
        position = torch.arange(0, position_max_length, dtype=torch.float).unsqueeze(1)
        pe = torch.zeros(position_max_length, self.hidden_dim)
        div_term = torch.pow(torch.ones(self.hidden_dim // 2).fill_(10000),
                             torch.arange(0, self.hidden_dim, 2) / torch.tensor(self.hidden_dim, dtype=torch.float32))
        pe[:, 0::2] = torch.sin(position / div_term)
        pe[:, 1::2] = torch.cos(position / div_term)
        pe = pe.unsqueeze(0)
        self.register_buffer('pe', pe)

        return pe

 

[input & output Embedding]

  • Embedding은 nn.Embedding을 통해, 쉽게 구현할 수 있다.
  • Embedding의 첫 번째 인자는 input 데이터의 total word 개수, 두 번째 인자는 hidden dimension의 수이다.
  • total_word_num은 sequence dictionary에 존재하는 unique value의 개수를 의미한다. (전체 단어가 아님을 주의)
  • 사실 편의를 위해, 공통 total_word_num을 사용했는데, 번역과 같은 경우, input의 단어 개수와 output의 단어 개수가 다를 수 있어, task에 따라서는 다른 인자를 받는 게 맞다.
 self.input_data_embed = nn.Embedding(total_word_num, self.hidden_dim)
 self.output_data_embed = nn.Embedding(total_word_num, self.hidden_dim)

 

[Transformer]

  • Transformer의 Encoder 부분은 앞서 구현했던, Encoder를 N번 반복하는 구조로 구현되어 있다. 
  • Encoder 부분에 들어가는 query, key, value는 문장의 embedding 한 값으로 모두 같고, (참조를 위한 query와 key가 비효율적이다.) 전번째 encoder의 결과가 다음 encoder의 query, key, value가 된다.
  • Decoder 부분도 비슷하지만, Encoder의 output이 사용된다는 점, Decoder 단에서는 다음 sequence를 볼 수 없기 때문에, 그 부분을 처리하기 위한 mask가 존재한다는 점이 다르다. 
  • Decoder에 masking으로 0 값을 넣어주었지만, 실제 학습해서는 매우 작은 값을 넣어주는 것이 학습 측면에서 유리하다고 한다.
  • Encoder 부분과 Decoder 부분을 모두 거치면, 목적에 맞는 fully connected layer를 연결하여, output을 낸다. 
class Transformer(nn.Module):
    def __init__(self, encoder_num=6, decoder_num=6, hidden_dim=512, max_encoder_seq_length=100,
                 max_decoder_seq_length=100):
        super().__init__()

        self.encoder_num = encoder_num
        self.hidden_dim = hidden_dim
        self.max_encoder_seq_length = max_encoder_seq_length
        self.max_decoder_seq_length = max_decoder_seq_length

        self.input_data_embed = nn.Embedding(max_seq_length, self.hidden_dim)
        self.Encoders = [Encoder(dim_num=hidden_dim) for _ in range(encoder_num)]

        self.output_data_embed = nn.Embedding(max_seq_length, self.hidden_dim)
        self.Decoders = [Decoder(dim_num=hidden_dim) for _ in range(decoder_num)]

        self.last_linear_layer = nn.Linear(self.hidden_dim, max_seq_length)

    def position_encoding(self, position_max_length=100):
    ...

    def forward(self, input, output, mask):

        input_embed = self.input_data_embed(input)
        input_embed += self.position_encoding(self.max_encoder_seq_length)
        q, k, v = input_embed, input_embed, input_embed

        for encoder in self.Encoders:
            encoder_output = encoder(q, k, v)
            q = encoder_output
            k = encoder_output
            v = encoder_output

        output_embed = self.output_data_embed(output)
        output += self.position_encoding(self.max_decoder_seq_length)
        output_embed = output_embed.masked_fill(mask.unsqueeze(-1), 0)
        d_q, d_k, d_v = output_embed, output_embed, output_embed

        for decoder in self.Decoders:
            decoder_output = decoder(d_q, d_k, d_v, encoder_output, mask)
            d_q = decoder_output
            d_k = decoder_output
            d_v = decoder_output

        output = F.softmax(self.last_linear_layer(decoder_output), dim=-1)
        return output

 

총평

  • 실제 NLP 단어 예측 등, 데이터셋을 넣어보기 위해, dataloader와 학습 등을 연결해 봐야겠다.
  • 특정 task를 풀기 위해, 데이터셋을 처리하기 위한 model을 짜는 것도 좋지만, 가끔은 논문을 그대로 구현해 보는 것도 좋을 것 같다. 특히, 그림과 글만 보고 구현을 하려고 하니, 내가 정확하게 알지 못했던 부분, 특히 머리로 이해하고 넘어간 부분을 완전히 알게 된 것 같아 좋다. 
반응형

GPT-1 배경 설명

  • GPT는 최근 가장 유명한 딥러닝 모델 중 하나다. GPT-1은 2018년 OpenAI에서 발표한 자연어 생성 모델로 다양한 자연어 처리 Task에서도 좋은 성능을 보여준다. 
  • GPT-1은 2017년에 나온 Transformer 아키텍쳐를 기반으로 만들어졌다. 
  • 개인적인 생각으로는 이 논문이 과거 모델 중심의 딥러닝 발전 방향에서 지금의 학습 & 데이터 중심의 방향으로 변하는 계기가 되지 않았나 싶다.  

Abstract

  • 자연어 처리는 이전까지(GPT-1 생성까지) 다양한 분야에서 발전을 이뤘다. 
  • 하지만, labeling 되지 않은 corpora(말뭉치) 데이터는 풍부하지만, 특정 자연어 처리 task 들을 학습하기 위한 label 데이터는 많지 않다.
  • "GPT-1"에서는 다양한 labeling되지 않은 다양한 텍스트 데이터들을 통해, 언어 모델을 "generativew pre-training" 하고,  각 task에 맞는 discriminative fine-tuning"을 하는 구조를 제안한다. 
  •  "GPT-1"에서는 fine-tuning 과정에서 "task-aware input transformation"을 사용해서 model 구조를 최소한으로 바꾸면서 효과적인 fine-tuning을 가능하게 한다고 한다. (뒤에서 무슨 말인지 확인해 보자)
  • "GPT-1"은 12개 task 중 9개 task에서, 애초에 그 목적으로 학습한 모델들을 넘어서 SOTA를 달성했다고 한다. 

Introduction

  • 기존 딥러닝 모델들에서 학습이 까다로웠던 이유는 labeling 된 데이터를 수집하는데 한계가 있기 때문이다. (기존 딥러닝 모델들이 실생활에 적용하기 까다로운 이유이기도 했다.)
  • 단순, 특정 task 학습을 위한 labeling된 데이터뿐 아니라, 풍부한 unlabeled 데이터를 함께 사용해서 언어 모델을 학습하는 것은 다양한 text의 representation을 학습하여 언어 모델의 성능을 향상할 수 있다. (word embedding 등등)
  • 하지만, unlabeled text에서 word-level의 information을 학습하는 것은 2가지 어려움이 있다. 
    • transfer를 위한 좋은 text representations을 뽑기 위해, 어떻게 학습하는 것이 효율적인지 알 수 없다.
    • 이렇게 학습된 representations들을 target task에 전달하기 위해 가장 효율적인 방법이 무엇인지 알 수 없다. 
  • 이 논문에서는, 언어 모델 학습을 위해 unsupervised pre-training과 supervised fine-tuning을 잘 조합해서 언어 모델의 성능을 향상 시킬 수 있는 방법을 제시한다.
  • GPT-1의 목표는 조금의 task adaptation만으로 광범위한 task들을 커버할 수 있는 universal representation들을 학습하는 것이다. 
  • GPT-1의 학습은 2가지 과정으로 진행된다.
    1. language modeling을 통해서 unlabeled 데이터를 모델에 학습한다.
    2. supervised 학습을 이용해서, target task에 맞도록 모델의 파라미터를 tuning 한다. 
  • 이를 위해, GPT-1에서는 "Transformer"를 이용한다. (Transformer의 메모리 제약이 적다는 점이 다양한 task에 적합하다고 한다.) 
  • GPT-1은 12개의 자연어 처리 task들 중 9개에서 SOTA를 달성할 정도로 광범위하고, 좋은 성능을 보인다. 

Framework

  • GPT의 학습은 Introduction에 언급하대로 1) unsupervised learning으로 unlabeled 데이터의 pre-training 하는 과정과 2) Task에 맞는 labeld 데이터로 fine-tuning하는 과정으로 진행된다.
  • Unsupervised pre-training 과정

Unlabeled 데이터로 모델을 pre-training하는 과정에서는, 일반적인 language model의 objective function을 따른다. (이전 단어들을 통해, 다음 단어들을 추측할 확률이 높도록 학습)

 

k: context window, T_i : i번째 Text의 단어 수, N: 문서 수  

 

 이 Paper에서는 multi-layer Transformer decoder를 SGD를 이용해서 pre-training을 학습했다고 한다. 

이 Paper에서 사용한 모델은 Transformer의 Decoder 부분만을 사용해서 학습한 방식을 따랐다고 한다. (Generating wikipedia by summarizing long sequences)

U: tokens들의 context vector, W_e : Token Embedding Matrix, W_p: position embedding matrix, n: layer 개수

→ pre-training 과정을 요약하자면, Transformer의 Decoder 모델을 이용하여, 일반적인 언어모델 학습(이전 단어들로 다음 단어를 잘 추정하도록 학습) 한다. 이 과정은 별도의 Labeling이 필요 없이, 단어 간의 context 정보를 Mapping 할 수 있도록 해준다. 

 

  • Supervised fine-tuning 과정

Unsupervised pre-training 과정 후에, 각 task에 맞는 역할을 수행하도록 parameter를 fine-tuning 하는 과정이다. fine tuning 된 모델의 마지막 단에 linear layer를 하나 추가해서, task에 목적에 맞는 학습을 진행한다.

Labeled 데이터가 y이고, pretrained transformer의 마지막 block의 값이 h_l일 때, objective function은 다음과 같다.

즉, pre-training 된 모델 마지막 부분에 layer를 추가적으로 달아서, 원하는 task의 objective function을 따르도록 학습하면 된다는 것이다.

GPT에서는 (1) supervied model의 일반화 향상 (2) 빠른 convergence를 위해, 추가적으로 auxiliary objective를 추가해서 학습한다. 

C : labeled 데이터

Task에 맞는 supervised 모델을 학습하면서, labeled 데이터를 이용해서 language model 학습을 같이 진행한다. (이론상으로는 pre-training 과정에서는 labeled 데이터는 사용하지 않은 상태이다.)  

 

  • Task-specific input transformations
  • Text Classification처럼 간단한 Task 들은 위처럼 fine-tuning을 진행하면 된다. 하지만, 몇 가지 다른 Task들은 fine-tuning 시, input을 조금 변형해서 넣어줘야 한다.
  • 특히, pre-training 단계에서는 order 적 개념을 학습한다. (전 단어들로 다음 단어를 추정하는 등.. ) 이러한 order 관계가 필요 없는 task들에서는 input을 order 형으로 변형해 주는 과정이 필요하다.
  • 이 부분은 모델을 최소한으로 건들면서, 다양한 Task들을 커버하기 위한 방법이다. 

 

Task  Input 구성 방법
Textual Entailment premise와 hypothesis 간 delimiter tocken($)를 사용함
Similarity 각각 독립적으로 Transformer에 넣은 뒤, 두 feature를 element-wise add하여 final linear layer의 input feature로 넣음
Question Answering & Commonsense Reasoning context, answer를 붙여서 input을 구성한 뒤, 각 question들을 각각 linear layer에 태운 뒤, softmax 함수에서 normalization을 한다.

Experiments

→ 아무래도, 논문 자체가 실용성에 초점을 맞추고 있다 보니, 학습 부분을 자세히 설명해 놓았다. 자세한 내용은 논문을 직접 참고하는 게 좋을 것 같다. 

  • Unsupervised Pre-training Setup 
    • Dataset : Unsupervised Pre-training을 위해, BooksCorpus dataset을 사용했다. 
    • Model : original transformer 모델을 따랐다. transformer의 12 layer의 decoder를 이용하였다. position-wise feed-forward 네트워크로 3072 dimmension의 inner states를 사용했다. Optimizer로는 Adam, Learning rate는 2.5e-4로 학습했다. L2 regularization도 도입했고, Gaussian Error Linear Unit을 activation function으로 사용했다고 한다. 기존 Transformer 논문과 달리, siunsoidal을 사용하지 않고 position embeddings을 사용했다. Tokenizer로는 spaCy를 사용했다. 
  • 실험 결과

→ 이 부분에서 각 Task의 사전 결과들에 대한 자세한 부분(모델 & 학습 데이터 & 성능이 의미하는 바)에 대해서 세세하게 잘 알지 못해서, 이 부분은 논문을 직접 참조하는 편이 좋을 것 같다. 

 

전체적으로 다양한 NLP 분야의 task에서 좋은 성능을 거두었다.(12개 task들 중, 9개에서 SOTA 성능이다.) 

 

 

Conclusion 

  • 이 논문에서는 unlabeled 데이터로 pre-training을 진행하고, 각 task에 맞는 labeled 데이터를 통해 supervised learning으로 좋은 성능을 보여주는 학습 방법에 대해 제시한다. 
  • Pre-training 단계에서는 다양한 word 간의 관계와 long-range dependencies 등이 학습되고, 이 정보들이 Fine-tuning 과정을 통해, 각 task들의 학습에 유용하게 사용된다.
  • 이러한 학습 방법은 12개의 NLP task 중 9개에서 SOTA를 기록할 정도로 powerful 하다. 

출처

Improving Language Understanding with Unsupervised Learning (lec Radford, Karthik Narasimhan, Tim Salimans, and Ilya Sutskever)

 

총평

이 논문에서는 복잡한 수식이나, 새로운 모델을 제시한 것은 아니다. 하지만, NLP 분야에서 unsupervised 방법으로 pre-training 하고, supervised 방법으로 모델을 학습하는 개념을 장착시켜, 현재의 Chat-GPT까지 만들 정도로 NLP 분야의 매우 중요한 이정표가 된 것 같다. 

반응형

Transformer 배경 설명

  • Transformer는 Google Brain이 2017년 "Attention is All You Need"라는 논문에서 제안된 딥러닝 모델이다.  
  • Transformer는 기존 자연어 처리 분야에서 주로 사용되던 RNN, LSTM 같은 순환 신경망 모델 중심의 처리 방법의 대안을 제공하여, 현재는 자연어 처리 분야에서 가장 널리 사용되는 모델 중 하나가 되었다.

사전 지식

  • 기존의 순환 신경망을 사용한 자연어 처리는 아래와 같이 Encoder를 이용해서 Context를 생성하고, Decoder를 따르는 구조를 가졌다. 

Abstract

  • 기존의(당시) 자연어 처리 분야의 논문에서는 Encoder와 Decoder에 복잡한 순환 모델이나 CNN 구조를 적용하는 방법이 지배적 이었다. 
  • 이 논문에서는 Transformer라는 Attention 메커니즘만 사용한 모델을 제안한다.
  • 실험에서 Transformer는 기존 모델에 비해 병렬적으로 학습하여, 더 빠른 시간에 학습하였음에도, 번역 분야에서 압도적인 성능을 보여준다. 

Introduction

  • 순환 모델에서는 일반적으로 Sequence를 처리하기 위해, 각 시간축을 따라 데이터를 참조한다. (즉, t 지점의 Feature를 생성하기 위해서는 t-1 까지의 값을 모두 참조해야한다.)
  • 이러한 구조는 전시점의 데이터들을 함께 필요로하기 때문에, 긴 sequence를 처리할 때(Sequential computation), 메모리 제약이 많이 걸린다. (학습 시, 병렬 처리가 어렵다.)
  • Sequential computation을 효율적으로 수행하기 위해, 여러 방법(Factorization trick, Conditional computation, 보통은 참조하는 시간 값을 줄이거나 뽑는 방법을 사용함) 등의 방법이 나왔지만, 근본적인 순환 모델의 한계(Sequential 구조때문에 메모리 제약이 큼, 병렬 처리가 어려움)는 극복하지 못한다. 
  • 이 논문에서는 순환 모델이 아닌, 전체를 Attention 메커니즘으로 처리하여, input과 output간 global 의존성을 모델링하는 "Transformer" 구조를 제안한다.  

Background 

  • Sequential computation을 줄이기 위해, CNN을 사용한 여러 논문들이 있었지만, 이 구조들로는 Input과 Output의 관계를  모델링하기는 어려움.
    • Transformer에는 "Multi-Head Attention" 메커니즘을 사용해서 여러 sequence의 Attention을 독립적으로 계산하고, 이를 결합해서, input과 output간 global 의존성을 모델링한다. 
  • "Self-attention" ("infra-attention"이라고도 함, input sequence의 각 위치에서 다른 위치들과의 상관 관계를 계산하는 기법)을 사용함. 
  • "End-to-end memory network" 구조로 구성된다. 

 

Model Architecture

  • 기본적으로, Transformer의 Encoder와 Decoder의 각 Layer들은 1) self-attention과 2) point-wise fully connected layer들로 구성된다.

  • Encoder
    •  Encoder는 동일한 6개의 layer들로 구성되어 있다. (그림에서 N=6)
    • 각 layer들은 2개의 sub layer들로 구성되어 있고, 각각 multi-header self-attention layer와 position-wise fully connected layer이다. 
    • 각 sub-layer들에는 residual connection을 연결해주었고, Layer Normalization(각 시점마다의 Normalization을 수행, 각 시점마다의 데이터 분포가 달라지는 것을 방지해줌)을 처리했다.
  • Decoder
    • Decoder도 동일한 6개의 layer들로 구성되어 있다.
    • Encoder의 2개의 sub layer(multi-header self-attention layer와 position-wise fully connected layer)에 추가적으로 encoder들의 output에 multi-head attention을 처리해줄 layer를 추가하여, Decoder의 각 layer를 구성한다. 
    • Encoder와 마찬가지로 각 sub-layer들에는 residual connection과 Layer Normalization 과정이 포함된다.
    • Decoder는 후속 데이터를 참조하면 안되기 때문에(실제 데이터에는 후속 데이터를 볼 수 없기 때문), self-attention sub-layer를 개조하여,  masking을 구현했다.
  • Transformer에서 사용되는 Attention
  • Scaled Dot-Product Attention : Query와 Key 사이의 유사도에 기반하여 Attention을 구하는 방식을 사용한다. 유사도 계산은 Attention Function에서 자주 사용하는 Dot Product를 기반해서 구한다. (빠르고, 공간 효율적이여서) scaling factor인 sqrt(d_k)를 나눠주는 이유는 d_k가 큰 값을 가질 때, Dot Product 값이 너무 커져서, Gradient가 매우 작아질 수 있기 떄문이다. 

→ 의미 : Query가 Key와 얼마나 유사한지에 따라 Value에 Attention을 가하겠다. (유사할수록 많이)

 

  • Multi-Head Attention : Query, Key, Value를 그냥 사용하는 것보다 각각 학습된 Weight들을 곱해준(Linearly Projection) 값을 사용하는 것이 효율적이라고 한다.(논문에서) Query, Key, Value를 Linearly Projection한 값으로 Scaled Dot-Product Attention을 구한 후, 각 값들을 concatenate 하고, 다시 그것에 Weight를 곱해서 Multi-Head Attention을 구한다.  

  • Transformer에서 Attention은 어떻게 사용되나?
    • Transformer에는 3가지 방식으로 multi-head attention을 사용한다. 
      1. "Encoder-Decoder Attention" : Decoder의 이전 시전 값과 현재 시점 값으로 구한 self-attention 값을 query로, Encoder들의 output을 이용하여 key, value를 구해서 multi-head attention을 적용한다. Decoder의 각 위치가 Input Sequence의 모든 위치들을 참조하도록 도와준다. 
      2. Encoder는 self-attention layer들을 가지고 있다. Key, Query, Value는 모두 Encoder의 전 Layer의 Output이다. Encoder의 각 위치가 다른 위치들의 값을 참조하도록 도와준다.  
      3. Decoder 단에도 self-attention layer들이 있다. Decoder의 각 위치가 다른 포지션을 참조하도록 해준다. (다만, 다음 시점의 데이터들은 참조하면 안되기 때문에 masking한다. )
    • 특히, 2,3번의 self-attention은 RNN을 사용하지 않고도, Sequence 데이터 처리에서 다른 시점의 데이터들을 참조할 수 있도록 한다. 
    • Attention을 정리하면 다음과 같다. 

Attention 인자 의미
1. Encoder-Decoder Attention Q : Decoder 단의 Vector
K : Encoder 단의 Vector
V : Encoder 단의 Vector
현시점의 Decoder의 Vector 값이 Encoder 단에서의 Vector 값과의 유사도 만큼, Encoder 값을 참조하는 가중치를 조정하겠다는 의미
2. Encoder Self-Attention Q : Encoder단의 Vector
K : Encoder 단의 Vector
V : Encoder 단의 Vector
현시점의 Encoder의 Vector 값과, Sequence 내 다른 Encoder 단의 Vector 값과 유사도를 측정하여 참조하는 가중치를 조정하겠다는 의미 → Sequence 내 다른 값도 함께 참조 가능 (RNN 기능을 self-attention으로 구현)
3. Decoder Self-Attention Q : Decoder 단의 Vector
K : Decoder 단의 Vector
V : Decoder 단의 Vector
현시점의 Decoder 의 Vector 값과, 이전 시점의 Decoder Vector 값과 유사도를 측정하여 참조하는 가중치를 조정하겠다는 의미 → Sequence 내 다른 Decoder 값도 함께 참조 가능
  • Position-wise Feed-Forward Networks : 앞서 말한대로, Encoder의 2번째, Decoder의 3번째 sub-layer는아래와 같은 fully-connected layer와 Relu로 구성되어 있다. 

  • Embeddings and Softmax : Embedding으로는 학습된 Embedding을 사용함. Decoder Output을 다음 Token의 확률로 변환하기 위해 Linear Transformation과 Softmax를 이용한다. 
  • Position Encoding : Input Sequence의 단어 위치 정보를 Embedding에 추가해서, 단어의 순서 정보를 이용할 수 있도록 Position Encoding을 사용. Position Encoding을 단어의 Embedding Vector에 더해서 사용.

Results

  • 기계 번역 : WMT 2014 English-to-German translation, English-to-French translation에서 State-of-the-arts 달성
  • 영어 문장 구문 분석 : 언어 모델의 일반화를 위한 실험, Task 튜닝 없이도 거의 SOTA에 근접한 성능 달성

 

출처

Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., ... & Polosukhin, I. (2017). Attention is all you need. In Advances in neural information processing systems (pp. 5998-6008).

+ Recent posts