Resource: Learning Transferable Visual Models From Natual Language Supervision
Vision과 Langauge를 결합한 모델, OVOD를 위해서라면 매우 자세한 분석이 필요한, 해당 Task의 근간이 되는 모델이다.
본 포스트에서는 하나하나 자세히 파해쳐보며 CLIP을 이해하려고 한다.
때문에 이번 리뷰는 조금 길고 양이 많아질 수 있다.
저자들은 SOTA vision system이 보통 a fixed set of predetermined object categories를 예측하도록 학습된다고 말한다. 즉, ImageNet처럼 미리 정해진 라벨 집합 내에서만 분류하는 방식이다.
이 방식은 문제가 있는데, 새로운 개념을 인식하려면 매번 추가 라벨링 데이터가 필요하다는 것이다.
구현 관점에서 보면 기존 supervised classifier는 마지막 classification Head가 특정 클래스 수에 묶여 있다.
CLIP의 대안은 이미지를 사람이 붙인 고정 클래스 라벨이 아니라, 웹에 자연스럽게 존재하는 텍스트와 함께 학습한다는 아이디어이다.
여기서 중요한 전환은 라벨이 class id가 아니라 natural language인 것이다.
CLIP 구현의 핵심 pre-training task로는, 이미지와 텍스트를 각각 encoder에 넣고, 같은 쌍의 image-caption은 가깝게, 다른 쌍은 멀게 만드는 contrastive learning 구조이다.
image -> image encoder -> image embedding
text -> text encoder -> text embedding
같은 pair: similarity 높게
다른 pair: similarity 낮게
CLIP의 성능은 구조만의 승리가 아닌, 웹 규모의 image-text supervision을 잘 먹는 학습 목표를 설계한 결과이다.
"natural language is used to reference learned visual concepts"
이 부분이 zero-shot의 핵심이다. 예를 들어 ImageNet 분류를 할 때도 classifier Head를 새로 학습하지 않고, 클래스 이름을 문장 prompt로 바꾼다.
이미지 embedding과 각 text embedding의 similarity를 비교해서 가장 가까운 텍스트를 예측 클래스로 삼는 식이다.
CLIP은 단순 이미지 분류 모델이라기보다, 자연어를 인터페이스로 쓰는 범용 visual representation model에 가깝다.
"Pre-training methods which learn directly from raw text have revolutionized NLP."
핵심은 "raw text"이다. 사람이 정답 라벨을 붙인 데이터가 아니라, 인터넷에 이미 존재하는 텍스트를 대규모로 학습해서 NLP가 발전한 것이다.
여기서 저자들이 염두에 둔 모델들은 GPT, BERT, T5 계열이다. 이 모델들은 특정 태스크 전용 구조를 처음부터 만들기보다는, 먼저 거대한 텍스트 corpus에서 일반적인 언어 표현을 학습한다.
논문은 이어 "Task-agnostic objectives"를 강조한다. 예를 들어
다음 단어 예측: autoregressive language modeling
가려진 단어 예측: masked language modeling
이런 목표는 특정 downstream task, 예를 들어 감성분석이나 번역, QA에 직접 묶여 있지 않다.
그런데도 대규모 학습을 하면 여러 태스크로 잘 전이된다.
CLIP은 바로 이 질문을 vision으로 가져온다.
image-text data로 pre-training을 하면, 다양한 vision task 로 zero-shot transfer가 가능할까?
저자들은 NLP에서 "text-to-text" 인터페이스가 중요했다고 말한다. 모든 문제를 텍스트 입력, 텍스트 출력으로 바꾸면 task마다 별도 head를 만들 필요가 줄어든다.
이게 CLIP에서는 다음과 같이 대응된다.
기존 vision:
image -> encoder -> fixed classifier head -> class id
CLIP:
image -> image encoder -> embedding
text prompt -> text encoder -> embedding
similarity 비교 -> prediction
즉, CLIP은 vision task의 출력 공간을 '고정된 클래스 index'가 아니라, '자연어 문장'으로 열어둔다. 이게 나중에 zero-shot classification의 기반이 된다.
ImageNet 1000-class classifier를 예로 들자면, 새로 학습하는 대신 "a photo of a dog", "a photo of a truck", "a photo of a starwberry" 등과 같은 텍스트를 text encoder로 넣고, 이미지와 가장 잘 맞는 문장을 고르는 방식이다.
논문은 NLP의 성공과 대비해서 vision분야를 조금은 비판적으로 본다.
비판 대상은 ImageNet 자체라기보다는, 정해진 라벨셋에 의존하는 학습 관습이다. ImageNet은 훌륭하지만, 1000개 클래스라는 closed set이다.
자연어는 훨씬 더 넓은 개념 공간을 표현할 수 있지만, 기존 vision model은 라벨셋이 모델의 세계를 제한한다.
"Could scalable pre-training methods which learn directly from web text result in a similar breakthrough in computer vision?"
이 문장이 introduction의 핵심이라고 봐도 무방하다. CLIP논문 전체는 이 질문에 대한 실험적인 답변인 것이다.
Mori et al., Quanttoni et al., Srivastava & Salakhutdinov, Joulin et al., Li et al., 등을 언급한다.
즉, 이미지와 텍스트를 같이 학습하려는 시도는 전부터 꾸준히 있었다. 예를 들어 Joulin et al.은 이미지 caption의 단어를 예측하게 해서 image representation을 학습했다.
하지만 성능은 충분하지 않았다. 논문은 예시로 Li et al.의 zero-shot ImageNet 정확도가 "only 11.5%"라고 말한다. 당시 SOTA나 고전적 supervised 방식에 비해 너무 낮았기 때문에, 자연어 supervision은 흥미로운 proof-of-concept에 머물렀던 것이다.
여기서 논문은 Instagram hashtag, JFT-300M과 같은 대규모 weakly supervised 학습을 언급한다.
이런 방법들은 데이터 규모가 크고 성능도 좋았지만, 여전히 supervision이 제한되어 있었다.
기존 모델들은 마지막에 고정된 softmax classifier를 둔다. 이러면 새로운 클래스를 자연어 즉석에서 넣을 수가 없다. CLIP의 text encoder는 이 한계를 깬다.
Static softmax:
weight matrix shape = [num_classes, dim]
num_classes가 고정됨
CLIP zero-shot classifier:
class text를 그때그때 encoding
새로운 class description도 즉석에서 추가 가능
기존 Natural Language Supervision 연구들은 보통 10만~20만 장 수준의 이미지로 실험했다. 하지만 대규모 weak supervision 연구들은 수백만~수십억 장의 데이터를 사용했다. CLIP은 이 간극을 메우고자 하는데, 이 때 등장하는 이름이 바로 CLIP이다.
CLIP, for Contrastive Language-Image Pre-Training
CLIP의 novelty는 "갑자기 완전 새로운 loss를 발명한 것"이 아닌, contrastive image-text learning을 웹 규모로 밀어붙이고 zero-shot interface까지 체계화했다는 것에 가깝다.

Figure 1은 CLIP 전체 아이디어를 [학습 단계 분류기 생성 zero-shot 예측] 으로 압축한 그림이다.
기존 이미지 분류 모델은 보통 [ image image encoder linear classifier class probability ] 과정을 거친다.
예를 들어 ImageNet이면 마지막 classifier가 1000개 클래스에 고정된다.
CLIP은 다르다.
image -> image encoder -> image embedding
text -> text encoder -> text embedding
image embedding과 text embedding의 similarity 비교
즉, CLIP은 "이미지 1000개 class 중 하나로 분류"하도록 바로 학습하지 않고, 이미지와 자연어 설명을 같은 embedding 공간에 정렬하도록 학습한다.
Figure 1 의 왼쪽 패널은 학습 과정이다.
데이터셋에 이러한 pair가 있다고 가정하자.
I1: image 1
T1: image 1에 붙은 text
I2: image 2
T2: image 2에 붙은 text
I3: image 3
T3: image 3에 붙은 text
예를 들어 그림에는 "Pepper the aussie pup"과 같은 caption이 보인다. 중요한 것은 이미지와 텍스트가 한 쌍이라는 것이다.
각각 Encoder에 들어간다.
I1 -> Image Encoder -> image embedding i1
T1 -> Text Encoder -> text embedding t1
여기서 대각선이 정답이다.
I1·T1 = image 1과 text 1의 matching score
I2·T2 = image 2와 text 2의 matching score
I3·T3 = image 3과 text 3의 matching score
나머지는 오답 pair이다.
CLIP은 정답 pair의 similarity는 크게, 오답 pair의 similarity는 작게 만들도록 학습한다. 이것이 바로 contrastive learning이다.
조금 더 직관적으로 표현해보자면 다음과 같다.
image_features = image_encoder(images)
text_features = text_encoder(texts)
image_features = normalize(image_features)
text_features = normalize(text_features)
logits = image_features @ text_features.T
정답 label은 단순한데, , batch에서 image의 정답 text는 text i이기 때문이다.
index 0: image[0] = 강아지 사진 text[0] = "a photo of a dog" index 1: image[1] = 자동차 사진 text[1] = "a photo of a car" index 2: image[2] = 새 사진 text[2] = "a photo of a bird" index 3: image[3] = 피자 사진 text[3] = "a photo of a pizza"여기서
image[0]의 정답 텍스트는text[0]이다.image[1]의 정답 텍스트는text[1]이고,image[2]의 정답 텍스트는text[2]이다. "batch에서 image i의 정답 text는 text i라는 말이 이 말이다."image[0]의 정답 = text[0] image[1]의 정답 = text[1] image[2]의 정답 = text[2] image[3]의 정답 = text[3]
학습 loss는 보통 양방향으로 간다.
image -> text: 이 이미지에 맞는 텍스트는 무엇인가?
text -> image: 이 텍스트에 맞는 이미지는 무엇인가?
구현 부분에서는 핵심이 보이는데,
loss_i = cross_entropy(logits, labels)
loss_t = cross_entropy(logits.T, labels)
loss = (loss_i + loss_t) / 2
CLIP은 caption을 생성하는 모델도 아니고, autoregressive하게 텍스트를 생성하는 모델도, 단어를 직접 예측하는 모델도 아니다. 이미지와 텍스트가 서로 맞는지 비교하는 모델인 것이다.
우측 상단 패널은 학습이 끝난 뒤 downstream dataset에 적용하는 과정이다.
예를 들어 우리가 분류하려는 클래스가 plane, car, dog, bird, 라고 해보자.
기존 supervised model이라면, 이 class 개수에 상응하는 classifier head를 새로 붙이고 학습해야 한다.
하지만 CLIP은 class name을 자연어 문장으로 바꾼다.
"a photo of a plane.""a photo of a car.""a photo of a dog.""a photo of a bird."Figure 1에서는 template이 이렇게 나온다.
"A photo of a {object}."
자연어로 바꾼 class name을 {object} 에 넣고 text encoder에 통과시킨다.
"a photo of a plane" -> Text Encoder -> t_plane"a photo of a car -> Text Encoder -> t_car"a photo of a dog" -> Text Encoder -> t_dog"a photo of a bird" -> Text Encoder -> t_bird이 text embedding들이 곧 classifier weight처럼 작동하는데, 논문 캡션에서는 이를 text encoder가 zero-shot linear classifier를 "synthesizes" 한다고 표현한다.
전에도 언급했지만, 여기서 중요한 점은 classifier가 고정되어 있지 않다는 것이다. class를 바꾸고 싶으면 text prompt만 바꾸면 된다.
"a photo of a tumor""a satellite photo of a harbor""a blurry image of a handwritten digit"이런 식으로 새로운 class description을 넣을 수 있다. 이것이 바로 CLIP의 zero-shot 능력의 핷미이다.
우측 하단은 실제 예측 단계이다.
새로운 이미지가 들어온다고 해보자.
그리고 아까 만든 class text embeddings와 similarity를 계산한다.
image · t_plane
image · t_car
image · t_dog
image · t_bird
가장 높은 score를 가진 class가 바로 예측 결과이다.
예를 들어 그림에서는 "A photo of a dog."이 가장 잘 맞는 텍스트로 선택되는 구조를 보여준다.
image_feature = image_encoder(image)
image_feature = normalize(image_feature)
logits = image_feature @ text_features.T
prediction = logits.argmax(dim=-1)
여기서 text_features.T가 사실상 classifier matrix 역할을 한다.
Figure 1의 진짜 의미
Figure 1은 기존 모델은 class label을 직접 예측하지만, CLIP은 image와 text를 같은 공간에 놓고, text를 classifier로 사용한다는 것이다
그래서 CLIP은 학습 때 본 class에만 국한되지 않는다. 자연어로 표현할 수 있는 개념이면 어느 정도 비교 대상이 될 수 있다.
그래서 말하고자 하는건?
**CLIP은 vision model을 고정 라벨 분류기에서 벗어나게 하고, 자연어를 통해 열린 개념 공간으로 transfer할 수 있게 만든 image-text contrastive pre-training 방법이다.
"learning perception from supervision contained in natural langauge."
perception은 단순 classification accuracy가 아닌, 이미지 안의 object, attribute 등을 이해하는 시각적 능력 전체를 말한다. 그 perception을 사람이 정리한 class label이 아니라 자연어 안에 들어 있는 supervision으로부터 배운다는 것이다.
예를 들어 기존 supervised classification에서는 이미지 하나가 보통 레이블은 그저 단어 dog와 같이 주어진다.
하지만 자연어 supervision에서는 이미지가 다음과 같이 존재할 수 있다.
a brown dog jumping over a log in the snow.
이 문장에는 그저 dog보다 훨씬 더 많은 정보를 담고 있어, 자연어는 단일 class id보다 훨씬 더 풍부한 supervision이라는 것이다.
왜 "Natural Language Supervision" 이라는 표현을 쓰지?
연구진들은 이 분야의 용어가 약간은 모순된다고 말한다. 어떤 연구는 image-text pair로 학습하면서도 자기 방법을
unsupervised라고 부르고, 어떠한 연구는self-supervised, 어떤 연구는weakly supervised라고 부른다.
논문에서는 이 차이를 크게 보지 않으며, 그저 이 계열의 연구들은 모두 이미지를 설명하는 텍스트를 학습 신호로 사용한다는 것이다.
참고로 CLIP은 완전한 unsupervised learning이 아니다. 이미지 옆에 붙은 텍스트가 모델에게 의미를 부여하기 때문인데, 다만 ImageNet처럼 사람이 정제한1-of-N label도 아니다.기존 supervised label과 다른 것은?
강아지 사진: label-"dog"이런 구조가 기존 img classification dataset인데, 이 label은 ML에 매우 편리하다. class index 하나로 바꿀 수도 있고, CEL를 걸기도 매우 쉽다.
하지만 정보량이 매우 제한적인데, 이미지 안에 강아지 외에도 나무, 사람 등이 있을 수 있지만, label은 하나만 남긴다.
반면 자연어는 더 지저분하지만 정보량이 풍부하다. CLIP은 이 풍부한 텍스트를 따로 처리하지 않고 그대로 학습에 사용한다.
저자들이 강하게 말하는 장점 중 하나는 자연어 supervision은 annotation을 꼭 "machine learning compatible format"으로 만들 필요가 없다는 것이다.
기존 데이터셋 구축에서는
위 흐름을 따르는데, 논문에서는 이 방식을 "1-of-N majority vote gold label"이라고 부른다.
이 방식은 깔끔할 수는 있어도 문제가 있는데,
1. class set이 미리 정해져야 함.
2. 새로운 class 추가하려면 다시 labeling 해야함.
3. 이미지의 풍부한 의미가 하나의 label로 압축됨.
4. Annotation 비용이 꽤 큼
자연어 supervision은 이 과정을 우회한다. 웹에는 이미 이미지와 텍스트가 함께 존재한다. 웹에 존재하는 그러한 데이터는 사람이 ML 데이터셋을 만들기 위해 따로 붙인 label은 아니지만, 이미지에 대하나 의미 정보를 담고 있다.
저자들이 논문에서 말하는 강점은 두 가지로, 첫 번째는 scale이다.
ImageNet식 annotation은 비용이 크다. 사람이 이미지를 보고 class label을 붙여야 하기 때문인데, 그저 인터넷에 대량으로 존재하는 자연어를 CLIP이 image-text pair를 supervision으로 사용한 것이다.
두 번째 강점은 representation을 language와 연결하는 것이다.
이 부분이 CLIP의 핵심인데, 저자들은 자연어로 학습하면 모델이 representation만 배우는 것이 아닌, 그 representation을 language와 연결한다는 것이다.
일반적인 self-supervised vision model을 예로 들어보면, SimCLR, MoCo 같은 모델은 좋은 image representation을 배울 수 있다.
하지만 이 representation은 자연어와 직접 연결되어 있지 않아 downstream task에 쓰려면 보통 linear probe나 fine-tuning이 필요하다.
반면 CLIP은 처음부터 image와 text를 같은 embedding space에 놓는다. 때문에 학습 이후 text가 classifier 역할을 할 수 있는 것이다.
때문에 CLIP은 representation learning과 language grounding을 동시에 한다.
OVOD와의 연결
OVOD에서는 정해진 class맘ㄴ detect하는 것이 목표가 아닌, 학습 때 보지 못한 class도 자연어 이름이나 설명을 통해 탐지하고 싶은 것이다.
기존 detector는 보통 [region feature fixed classifier known classes] 구조로 이루어져 있는데, CLIP의 개념을 도입하면 다음과 같다.
[region feature text embedding과 similarity 비교]
즉, class weight을 고정 parameter로 두는 대신, text encoder가 만든 embedding을 분류기로 쓰는 것이다.
다만 CLIP 자체는 image-level model로, BBOX 를 직접 예측하지는 않아, region-level detection 구조에 이식하는 방법을 사용한다.
CLIP이 정제된 class label 대신 웹에 존재하는 자연어를 supervision으로 사용하고, 이를 통해 visual representation을 language space와 직접 연결함으로써 scalable learning과 flexible zero-shot transfer를 가능하게 만든다.
CLIP이 자연어 supervision을 제대로 검증하기 위해서는, 기존 image-text dataset으로는 너무 작거나 품질이 부족했기 때문에, 저자들은 웹 규모의 400M image-text dataset을 직접 만들었다.
MS-COCO, Visual Genome, YFCC100M 데이터셋을 기존에 사용하였지만, 방금 말한 이유 등으로 인해 natural language supervision의 강점 scale을 제대로 실험할 수 없었다.
자연어 supervision의 장점은 인터넷에 엄청난 image-text pair가 있는 것인데, COCO나 Visual Genome만 보면 그 잠재력을 과소평가한다.
단순히 인터넷의 공개 source에서 많이 긁어온 것이 아닌, 넓은 visual concept를 포함하도록 query 기반으로 수집을 진행했다. 이렇게 만들어진 400M image-text dataset을 WIT, WebImageText라고 부른다.
즉, 다양한 단어나 개념을 query로 두고, query가 text에 포함된 image-text pair를 수집한 것이다.
(그렇다고 한 query가 데이터셋을 과도하게 지배하지 않도록 최대 20,000 image-text pair로 제한하였다.)
중요한 점은 이 query들이 학습 label은 아니다. query는 데이터 수집을 위한 장치일 뿐, 실제 학습은 여전히 image-text pair 단위로 한다.
2.2 의 핵심
1. COCO/Visual Genome만으로는 CLIP 논문의 scale을 재현하기 어렵다.
2. image-text pair는 많기만 하면 안 되고, text가 실제 자연어 설명이어야 한다.
3. 흔한 개념에 데이터가 쏠리지 않게 balancing 또는 sampling 전략이 필요하다.
4. query는 label이 아니라 dataset coverage를 넓히기 위한 도구다.
5. CLIP 성능은 architecture만이 아니라 WIT 같은 대규모 데이터 구축에 크게 의존한다.
OVOD에서는 3번과 4번이 특히 중요한데, Open-vocabulary를 잘하기 위해서는 학습 데이터가 특정 closed category에만 몰려 있으면 안되기 때문이다.
2.2의 핵심은 CLIP의 성능이 단순 contrastive loss에서 나온 것이 아닌, 자연어 supervision의 장점이 드러날 만큼 크고 다양한 image-text dataset을 직접 구축한 데에서 나온다는 것이다.
CLIP이 왜 caption generation이 아닌, contrastive image-text matching을 선택했을까?
기존 방식처럼 이미지에서 caption을 직접 예측하려고 하면 너무 비싸고 어렵다. 같은 이미지에도 가능한 설명 문장이 너무 많아, 시각 개념을 배우기보다는 "문장을 정확히 생성하는 문제"에 computation이 많이 든다는 것이다.
때문에 저자들은 image CNN과 text Transformer를 함께 학습해서 caption을 예측하려 했지만, scale up이 비효율적이었다고 한다.
CLIP의 학습 목표는 다음과 같은데,
image_features = image_encoder(images)
text_features = text_encoder(texts)
image_embeddings = normalize(image_projection(image_features))
text_embeddings = normalize(text_projection(text_features))
logits = image_embeddings @ text_embeddings.T
logits = logits * exp(temperature)
labels = arange(batch_size)
loss_i = cross_entropy(logits, labels)
loss_t = cross_entropy(logits.T, labels)
loss = (loss_i + loss_t) / 2
여기서 이전에 양방향 loss를 설명했을 때와 같이, loss_i는 이미지 기준으로 맞는 텍스트를 찾는 loss, loss_t는 텍스트 기준으로 맞는 이미지를 찾는 loss인데, 저자들은 이를 symmetric cross entropy loss라고 부른다.
CLIP은 꽤 단순히 설계되었는데, 저자들은 대규모 데이터셋을 사용하기 때문에 overfitting이 큰 문제가 아니라고 보고, 여러 복잡한 과정들을 제거한다.
때문에 CLIP은 큰 데이터 + 단순한 contrastive objective + 두 개의 encoder alignment라고 보면 되겠다.
재현 관점에서의 2.3 Checklist ✅
1. image encoder와 text encoder를 준비한다.
2. 각각의 출력을 같은 embedding dimension으로 projection한다.
3. embedding을 L2 normalize한다.
4. batch 안의 모든 image-text similarity matrix를 만든다.
5. diagonal을 정답으로 두고 symmetric cross entropy를 건다.
6. temperature/logit scale은 학습 가능한 parameter로 둔다.
참고로 L2 Norm을 하는 이유는 CLIP이 Embedding의 Norm(크기)가 아니라, 방향(Direction)으로 image-text 의미 정렬을 학습하게 만들기 위함이다.
CLIP은 "벡터의 크기가 큰가?"가 아닌, "이미지 벡터와 텍스트 벡터가 같은 방향을 보고 있는지"를 학습한다.
L2 Normalization은 CLIP이 embedding의 크기 꼼수가 아니라 image-text 의미 방향의 정렬을 학습하게 하고, dot-product를 코사인 유사도로 바꿔 contrastive learning을 안정화한다.
그렇다면 image/text encoder는 어떠한 구조로 만들었고, 어떻게 scale 하는 걸까?
이제 CLIP은 image encoder, text encoder 두 개로 구성된다는 것도, 두 feature를 같은 multimodal embedding space로 projection해서 유사도를 계산하는 것도 안다.
먼저저자들은 image encoder로 ResNet과 ViT 계열을 사용한다.
ResNet 먼저 알아보자.
기본은 ResNet-50이다. 다만 원래 ResNet을 그대로 쓰지는 않고, 몇 가지를 추가한다.
여기서 가장 눈에 띄는 것은 attention pooling이다.
일반 ResNet은 마지막 feature Map을 GAP으로 하나의 vector로 만드는데, CLIP은 이 부분을 attention pooling으로 바꾼다.
즉, 모든 spatial location을 단순 평균내는 대신, attention을 통해 더 유연하게 image representation을 만든다. CLIP이 image-text alignment를 해야하니, 단순 classification보다는 풍부한 Global representation이 더 필요했을 가능성이 있다.
ViT는 이미지를 패치로 나누고, 각 패치를 토큰처럼 Transformer에 넣는 구조이다.
CLIP에서는 ViT구조를 거의 그대로 사용하지만, patch embedding과 position embedding을 더한 뒤 LN을 추가하는 정도의 수정만 한다.
text encoder에서는 transformer를 사용한다.
이에 대한 디테일을 살펴보자면 다음과 같다.
텍스트는 lower-cased BPE로 tokenize된다고 한다. 문장 앞뒤에는 special token을 붙인다.
[SOS] text tokens [EOS]
CLIP은 나지막 layerdptj [EOS] 토큰 위치의 activation을 text feature로 사용한다.
왜[EOS]를 쓰냐면, casual/masked self-attention 구조에서 [EOS]의 위치는 앞의 전체 문맥을 본 토큰이기 때문이다. 때문에 문장 전체의 요약 representation처럼 사용할 수 있다.
여기서 잠시 BPE가 무엇인지 😰...
BPE는 Byte Pair Encoding으로, NLP에서 자주 사용되는 subword tokenization 방식이라고 한다.
텍스트를 소문자한 뒤에, BPE 방식으로 token id sequence로 바꾼다.BPE가 필요한 이유
모델은 문자열을 그대로 이해하지 못해, 텍스트를 숫자 토큰으로 바꾼다.
가장 단순한 방법으로 단어 단위 tokenization이 있는데, 이걸 전부 완전한 단어 vocabulary에 넣으면 크기가 너무 커지기 때문이다.
BPE는 중간 지점으로, 단어를 너무 잘게 character로만 쪼개지도 않고, 완전한 단어로만 보지도 않는다. 자주 나오는 조각은 하나의 토큰으로 만들고, 회귀 단어는 작은 subword 조각들로 쪼갠다.
BPE는 대충 이런 식으로 vocabulary를 만든다.l o w l o w e r n e w e s t w i d e s t그 다음, corpus에서 가장 자주 같이 등장하는 인접 쌍을 찾아, merge한다.
논문은 text encoder에 masked self-attention을 사용했다고 한다.
이것은 GPT류 Language Model이 미래 token을 보지 않는 attention 구조이다.
다만 CLIP이 language modeling을 직접 수행한다는 것은 아니고, 나중에 pre-trained language model initialization이나 auxiliary language modeling objective를 붙일 가능성을 남겨두기 위해 이런 구조를 유지했다고 한다.
즉, CLIP의 text encoder는 Transformer이지만, 학습 목표는 여전히 caption generation이 아닌, image-text contrastive learning이다.
image encoder와 text encoder의 출력 dimension은 다를 수 있다. 때문에 각각 linear projection을 통해 같은 embedding dimension d_e로 보낸다.
CLIP에서의 Linear projection
img encoder와 text encoder의 출력 차원이 다음과 같다고 가정하자.
- image encoder output: 2048
- text encoder output: 512
그런데 이 둘의 유사도를 계산하려면 같은 차원이어야 한다. dot product를 하려면 차원이 같아야 하므로, 둘 다 같은
d_e로 보내보자.
때문에 CLIP은 각각 linear projection을 둔다.I_f = image_encoder(I) # [n, d_i] T_f = text_encoder(T) # [n, d_t] I_e = I_f @ W_i # [n, d_e] T_e = T_f @ W_t # [n, d_e]논문의 Figure 3에서는 다음과 같이 나온다.
I_e = l2_normalize(np.dot(I_f, W_i), axis=1) T_e = l2_normalize(np.dot(T_f, W_t), axis=1)여기서
W_i,W_t가 바로 linear projection matrix이다.
linear라는 말은 변환이 행렬곱으로 이루어진다는 말로, bias를 포함하면 NN에서는y=xW+b로 표현 가능하겠다.
이후 L2 Norm을 하고 코사인 유사도를 계산한다.
similarity = normalized_image_embedding @ normalized_text_embedding
여기서 중요한 점은 CLIP이 복잡한 fusion module을 쓰지 않는다는 것이다. image와 text를 중간에서 섞는 것이 아닌, 각자 encoder를 통과한 뒤 같은 공간에서 비교하는 것이다.
저자들은 모델을 키울 때 image encoder와 text encoder를 똑같이 키우지 않는다.
ResNet image encoder는 세 방향(width, depth, resolution)을 함께 키운다.
이는 EfficientNet식 scaling 아이디어와 비슷한데, 모델을 키울 때 width만 늘리거나 depth만 늘리는 것보다 여러 축을 같이 늘리는 것이 더 좋다는 관점이다.
반면 text encoder는 주로 width만 키운다. depth는 키우지 않는다.
이유는 CLIP 성능이 text encoder capacity보다 image encoder capacity에 더 민감했다고 보기 때문이다.
그 이유로 "CLIP's performance [is] less sensitive to the capacity of the text encoder"라고 언급하는데, 이 관찰은 별도의 상세 ablation table로 제시되지는 않고, 저자들의 경험적 판단으로 보인다.
이것은 중요한 관찰인데, CLIP에서 text는 물론 중요하지만, vision task 성능을 올리는 데에는 image encoder scale이 크게 작용했다는 뜻이다.
저자들은 총 8개의 모델을 학습한다.
논문에서 모든 모델은 32 Epochs로 학습했다고 한다.
Optimizer로는 Adam을 사용했으며, decoupled weight decay를 적용했다. lr은 cosine scheduler로 감소시켰다.
여기서 decoupled weight decay는 AdamW 스타일이라고 보면 된다. 일반 L2 Regularization과 다르게 weight decay를 optimizer update에서 분리해서 적용하는 방식이다.
CLIP loss에서 similarity logits은 teperature로 scaling 된다.
logits = image_embedding @ text_embedding.T
logits = logits * exp(t)
논문에서는 temperature τ를 고정 hyperparameter로 두지 않고, learnable parameter로 둔다. 초기값은 0.07에 해당하도록 설정했다.
왜 learnable temperature가 좋은가?
contrastive learning에서는 batch size, embedding quality, dataset noise에 따라 적절한 softmax sharpness가 달라질 수 있다.
temperature가 너무 낮으면 다음과 같은 가능성이 있다.
- 모델의 과확신
- hard negative에 과민
- 학습 불안정
반대로 temperature가 너무 높으면
- positive와 negative 구분이 약함
- gradient signal이 흐릿함
- 학습이 느려짐
때문에 CLIP은 temperature를 고정하지 않고 학습하게 만든다. 다만 너무 커지면 불안정해질 수 있어, logit scale이 100을 넘지 않도록 clip했다고 설명한다.
logit_scale = nn.Parameter(torch.ones([]) * np.log(1 / 0.07)) logit_scale = logit_scale.exp().clamp(max=100)
논문에서 가장 눈에 띄는 설정 중 하나는 "minibatch size of 32,768"이다.
CLIP이 contrastive learning에서는 batch size가 중요하다. 왜냐하면 batch 안의 다른 sample들이 negative pair가 되기 때문이다.
batch가 크면 클수록 한 번의 update에서 훨씬 많은 negative pair를 보게 된다. CLILP이 23,768이라는 큰 batch size를 쓴 이유도 여기있다.