본문 바로가기

VirtualTryon

clip - ViT & Image projection

clip에서 사용하는 vit , Image encoder의 pooled output 을 상세하게 확인한다. 

 

  # ViT 구조 

 

  이미지 encoder  

패치의 크기는 P이다. 

ViT 14는 각 패치의 크기가 14란 뜻이다.  1개의 패치의 크기는 14x14 이고, 이건 1개의 토큰이 된다. 

 

더보기

따라서 이미지 (224 * 224 * 3)를 패치화 한다면, 

224 / 14 = 16    =>  16*16 * 3 = 768 이  된다. 

따라서 1장은 768개의 token을 갖는 문장처럼 다룬다. 

 

 

  텍스트 encoder  

텍스트 프롬프트는 77개의 토큰으로 변환되고,   이걸 768 으로 임베딩 한다.  

헷갈리지 말자 point1 )  clip 훈련시(contrastive learrning) 텍스트든 이미지든 토큰은 하나만 사용한다.! 

즉 텍스트의 77개의 토큰중 대표 토큰 (아마 맨앞 490406) 을 사용한다. 

헷갈리지 말자 point2 )

하지만 diffusion에서 t2i generation 의 경우엔 77개를 다쓴다. 

 

 상세 예시  

더보기

CLIP은 최대 75토큰의 입력값을 받아서 가장 앞에 BOS(49406) 토큰을 넣고, 뒤에는 EOS(49407) 토큰으로 채운다

즉 '1girl'을 프롬프트로 넣으면 이것을 [49406, 272, 1611, 49407, 49407, 49407, ..., 49407] 토큰으로 변환된다. 
또한 이미지 생성시 positive prompt 혹은 negative prompt가 75개 토큰을 초과할경우, 성능이 저하된다.

 코드 실행 결과 

더보기
출처 : https://hongl.tistory.com/232

 

 ViT Image encoder에 관한 그림 설명 

https://hongl.tistory.com/232

 

 
 
CLIPVisionModelWithProjection
 
위 함수에서 아래와 같이 pooled output 이 [1]로 고정되어있다.     
 
 
self.vision_model = CLIPVisionTransformer(vision_config)
vision model은 clip의 visiontransformer로  output은  b x 257 x  1024 이다. 
이때, 좀 더 상세히 보면 ( 이 예시는 vit-patch14 에 대해서다)
토큰 개수는 257 이고, 257은 이미지 사이즈, 패치 사이즈 등에 의해서 변한다. ( 16x16 개의 토큰 +1토큰 = 257 토큰) 
 
3x14x14 에 3x3x1024 nn.2dconv가 14 stride로 가해지는데, 
하지만 1024 는 고정이다. 아래 vision config를 보면 hidden_size (= output)은 1024로 고정되어있다.  
 
 
 
 
위 코드에서 pooled 하는건 contrastive learning 을 위해서 맨앞 토큰 (시작 토큰 0번을 뺀) 1번을 의미한다. 
그럼 pooled 하면 257x 1024 => 1 x 1024    (token 1개 뽑기) 가 된다. 
 
pooled output, 1x1024 이다.
 
그리고 clip trainning에서는 1024 를 768로 pojection 시켜 contrastive learning을 진행한다. 
 
           pooled_output = vision_outputs[1]  # pooled_output
           image_embeds = self.visual_projection(last_hidden_state)
 
 
난 지금 vision transformer의 전체 결과물을(1개의 토큰을 뽑아낸게 아닌) visual_projection 한 결과물이 얻어야 한다.
즉, text embedding(77x768) 대신  vision_model(CLIPVisionTransformer)의 결과물을 visual_projection 시킨 결과물을 얻고자 한다. ( transformer에서 77은 바뀌여도 되지만, 768 은 바뀌면 안된다. ) 
 
그러면 코드는 아래와 같이 수정된다.  last_hidden_state 전체를 뽑아내고, 전체를 projection visual_projection 한다. 
 
           last_hidden_state = vision_outputs.last_hidden_state  # without pooling (custom) (b x 257 x 1024) 
           image_embeds = self.visual_projection(last_hidden_state)                                     (b x 257 x 768) 
 
 
text embedding ( 77x 768 ) 대신 image embedding(257 x 768 ) 을 쓰려고 할때,    
 
batch x token은 달라도 되지만 , dimension은 같아야한다.   768 만 고정하면된다. !