본문 바로가기

인공지능

[코스모스 7주차] Self-Supervised Learning

일단 self-supervised learning이 뭐냐면 이미지의 라벨 없이 이미지만 가지고 학습을 하는 것이다. self로 task를 정해서 supervision방식으로 모델을 학습하기 때문에 self-supervised라고 한다.  대량의 이미지를 가지고도 모델 학습이 가능하다. 이렇게 학습하게 된다면 이미지 라벨에 구애받지 않고 이미지의 feature을 잘 뽑아낼 수 있는 encoder을 학습시킬 수 있다.

1. Pretext tasks from image transformations

이 파트는 그냥 간단한 self-supervised learning인데, 이미지를 변형을 시켜 -> 그리고 우리가 원하는 태스크를 진행시켜 -> 우리는 변형 전의 그림을 알겠지? 그럼 이게 label이 되어서 학습이 진행되는 것이다. 그리고 나서 이 모델을 뭐... 다른 downstream task에 사용을 한다. 이를 하는 이유는? 바로 데이터에서 유용한 특징을 추출하기 위함이다. 막 회전시키고 이런거 볼 때 인간은 기본적으로 물체에 대한 이해도가 있기 때문에 똑바로 있는지 뒤집혀있는지 이런 걸 알거 아닙니까... 이를 딥러닝에 적용을 시키면 기본적인 물체에 대한 이해도를 심어주기 위해서 이런 pretext task를 진행한다는 것을 알 수가 있겠다. 여기에서 중요한 점은 이 모델이 잘 훈련이 되었는지 판단하는 기준이 pretext task를 얼마나 잘 수행하냐를 보는게 아니라 이 모델을 downstream task에 적용했을 때 얼마나 좋은 성능이 나는 지가 중요하다고 한다. 

머 여기에 종류가... 회전 예측하는 거랑 patch 위치 추정하는 거랑 jigsaw puzzle 맞추는거랑 이미지 부분 가려가지고 추정하는 방법이나 색깔 예측하는 것 등 괴애애앵장히 다양하게 있다. 

이렇게 task를 진행한 모델은 weight를 freeze시키고 뒤에 fc를 붙여서 fine-tuning을 시키거나 데이터의 label을 1~10%만 붙여서 semi supervised learning을 시키거나 imagenet으로 학습한 모델을 transfer-learning 시켜서 다른 dataset을 평가하거나 한다고 한다. 

그런데 이런 task의 문제는 ... 특정 pretext task로 진행한 모델은 그 task에만 치중, 즉 학습된 특징이 일반적이지 않을 수 있다는 단점이 존재한다. 따라서 더어어 일반화 할 수 있는 특징을 찾는 task를 진행을 하게 된다. 

그래서 새로운 방식이 등장한다!

 

2. Contrastive Representation Learning

기본적인 contrastive representation learning의 개념은 우선 유사한 이미지들은 positive sample들로 벡터 상에서 가까운 거리에 위치할 것이고 다른 클래스나 카테고리의 사진은 negative sample들로 멀리에 위치하도록 훈련하는 것이다. 그래서 우리의 목표는 일단 positive한 set과 negative한 set을 구별하는 것이 목표라고 할 수 있겠다. 

이때 set을 어떻게 구성하냐! 라고 하면 같은 이미지에 여러가지 데이터 증강을 통해서 새로운 데이터를 생성해내고, 생성된 이미지들은 원본 이미지들과 positive 쌍일 것이다. 하지만 다른 이미지에서 변형된 이미지는 negative 쌍이라고 할 수 있겠다. 이때 원본 이미지를 anchor라고 한다. 그리고 이 쌍들을 잘 구별해나가는 방식으로 학습해나간다. 증강 방식에는 뭐.. 돌리기라던지 뒤집기라던지 노이즈를 씌우던지 크롭을 하던지 아주 다양한 방식이 있겠다. 

 

그리고 여기에서 사용하는 loss함수는 infoNCE를 사용하는데 분자는 positive sample에 대한 서로의 유사도이고, 분모는 전체 데이터셋에 관한 서로의 유사도라고 할 수 있겠다. 

 

이는 다중클래스에서 cross entropy를 계산한 것과 같이 되는데, 여기에서 우선 positive pair의 sim을 높여주는 것이 우리의 목표이다. 그리고 lower bound를 높여주는 방식으로 진행이 된다. 하...여기에서 상호정보량이 무엇이냐... 이는 결합확률밀도함수 p(x,y)와 주변확률밀도함수의 곱 p(x)p(y)의 kl divergence라고 한다. 즉 둘이 같으면 독립이라는 뜻이니까 0이 되는데, 0이 되면 상관관계가 없다는 뜻이고 높은 양의 값을 가질 수록 독립이 아니라는 뜻이니까 상호정보량이 많아진다라고 한다. 발표때 왜 몰랐지...MI[f(x), f(x+)] >= -L + log(N)이라는 식이 무얼 의미할까~? lower bound를 높여주는 것을 의미한다. 이는 데이터 개수? N이 커질 수록 상호정보량의 boundary가 높아지고 L가 작아질 수록 boundary가 높아진다. 이렇게 간접적으로 positive쌍의 상호정보량이 많아지도록 학습을 하는 것이다. 

 

이제 본격적으로 SimCLR에 대해 서술하도록 하겠다. 

짜잔

논문에서 나온 구조인데 x라는 데이터셋을 각각 2번 augmentation을 시켜서 두개의 positive한 이미지를 얻는다. 그리고 만들어진 두 이미지에 f(x)를 적용하게 된다. 이는 인코더이고 보통 ResNet-50이라고 한다. 그리고 projection head라고 불리는 g(x), Linear - BN - ReLU - Linear - BN를 적용하게 된다. 이때 projection head가 뭐냐!! 가 self-supervised learning관점에서 굉장히 중요한 포인트이다. 

우선 벡터의 차원을 줄여준다. 이는 연산량을 줄여준다는 의미로도 볼 수 있다. projection head를 통해 나온 벡터들의 simularity가 높아지도록 학습을 하는데, 이 때 얻은 output vector은 encoder만 거친 벡터보다 시각적인 특징을 잘 표현하지 못한다고 한다. 이가 의미하는 바는 contrastive learning을 통해 학습한 정보들이 projection head를 거치면서 소실되기 때문이라고 하는데 실험의 결과에 따르면 projection head를 거친 vector이 rotation이나 gaussian noise, sobel filtering등의 정보를 많이 담고 있지 않는 것을 볼 수 있다. 이는 projection head가 단지 contrastive learning을 위해서 존재하는, 그러니까 encoder이 더 이미지의 특성들을 잘 뽑아낼 수 있도록 존재하는 존재라고? 생각하면 될 것 같다. 

지선생의 추가설명을 들어보자면 비선형 projection이 선형 projection보다 유리하다는 가설이 있다. 이는 contrastive loss에 의해 정보가 손실될 수 있고, projection은 데이터의 핵심적인 특징만 포착하는데 중점을 두어 encoder의 성능 향상에 도움이 된다. 

SimCLR

 

그리고 mini-batch training이 어떻게 진행이 되냐면 우선 positive쌍들이 차례로 들어가게, 홀짝 positive 씩 들어가게! 2k와 2k + 1이 positive pair이 되도록 batch를 만들게 된다. 그리고 나서 유사도행렬을 구하게 되는데, 행열 같이 들어가는식으로... 그런데 이때 N개의 데이터이면 2개씩 augmentation이 되니까 2N * 2N의 행렬이 된다. 그리고~ positive와 negative 유사도를 한 번에 구하게 된다. 

 

그리고 Training Epoch과 Batch Size가 클수록 성능이 크다고 하는데, 이게 한계점과 이어지게 된다. 왜냐하면 이 말은 연산량이 굉장히 많이 든다는 것을 의미한다. 또한 negative sample에 대한 의존성이 높다라는 것을 알 수 있다. 그리고 self-supervised learning은 보통 라벨링 없이 많은 데이터셋을 이용하는데 거기에다가 더 많은 데이터를 사용해야 하는 것은.. 아무래도 사고인 것 같다.

 

그래서 후에 나온 모델이 MoCo!

MoCo란 Momentum Contrast for Unsupervised Visual Representation Learning이라는 뜻인데, 다음은 구조도이다.  

MoCo

 

이는 하나의 배치 안에서 positive pair과 negative pair를 추출한 SimCLR과 달리 특정 크기의 dictionary를 정의하여 sample들의 key값들을 저장해두고 query와 matching되는 값을 positive key로, 나머지를 negative key로 분류하여서 추출하였다. Encoder은 ResNet을 사용하였고, 같은 이미지로부터 생성한 key와 query가 positive pair을 구성하게 된다. contrastive loss로 학습하려면 충분한 개수의 negative pair이 꼭 필요하게 되는데, moco에서는 충분히 큰 크기의 dictionary를 queue형태로 두고, 이 dictionary에서 negative sample들을 추출하게 되었다. 이 dictionary의 크기는 batch size보다 크고, 논문에서는 이 dictionary를 65536개로 지정했다고 한다. 그리고 만약 256개의 batch단위로 학습을 진행한다면, 하나의 입력 이미지에 대해 dictionary에 이미 존재하는 65536개의 key와 negative를 이루게 된다. 그리고 이제 학습 과정에서 생성된 새로운 키가 queue처럼 제일 처음에 생긴 mini-batch를 빼고 dictionary를 대체하게 되어서 dynamic dictionary라고 부른다고 한다. 

 

하지만 이런 식으로 큰 dictionary를 이용하게 되면 key encoder을 학습하는 과정에서 수많은 negative sample들에 대해서 gradient를 전파해야하기 때문에 학습이 어려워진다. 이를 해결하기 위해서 key encoder에 gradient를 흘리지 않고! momentum을 이용해 update하는 방식을 사용하는데 key encoder의 weight와 query encoder의 weight를 m:(1-m)비율로 섞어서 사용하게 된다. 이때 m을 0.9 ~ 0.999정도로 설정하게 되는데, 이때 1-m의 크기가 매우 작아지기 때문에 key encoder가 천천히 momentum을 가지고 바뀌게 된다.

 

이렇게 하는 이유.... 일단 key의 update가 빠르게 되면 안되는 이유는 dictionary를 구성하는 key들의 representation이  일관적인 것이 좋다. 따라서 매 iteration마다 weight가 빠르게 바뀌지 않도록 encoder를 점진적으로 업데이트하면서 천천히 학습시키는 방법을 택하게 되었다. 이는 key의 일관성을 높이고 query encoder의 학습을 방해하는 요소가 된다. 그리고 key encoder이 아무리 천천히 바뀐다고 해도 바뀌긴 하니 쌓인지 오래된 mini-batch와는 consistency가 유지되기 힘들 수 밖에 없다.