[LLaVA系列]CLIP/LLaVA/LLaVA1.5/VILA筆記
共 6514字,需瀏覽 14分鐘
·
2024-05-31 22:54
0x00 前言
本文主要記錄一下CLIP和LLaVA系列模型的核心點(diǎn),便于自己后續(xù)復(fù)習(xí)查找。
0x01 CLIP 模型結(jié)構(gòu)
paper: https://arxiv.org/pdf/2103.00020.pdf
CLIP模型是一個(gè)雙塔結(jié)構(gòu),包括一個(gè)文本編碼器Text Encoder和一個(gè)圖像編碼器Image Encoder。訓(xùn)練數(shù)據(jù)集的形式為(image, text),對(duì)于每個(gè)正確匹配的image和text,text是對(duì)image的一句正確描述。CLIP模型需要對(duì)(image, text)的數(shù)據(jù)對(duì)進(jìn)行預(yù)測(cè),即(image, text)匹配的為1,不匹配的為0。
Text Encoder: 對(duì)于每個(gè)句子,將其編碼成一個(gè)隱向量,
維度(1,512);N個(gè)句子,因此有
,即[N, 512]
Image Encoder: 對(duì)于每張img,將其編碼成一個(gè)隱向量,
維度(1,512);
N張圖,因此有
-
,即[N, 512]
由于Text Encoder和Image Encoder最后都是輸出[N,512]的Tensor,因此可以很方便地計(jì)算images和texts兩兩之間的相似度。CLIP可以選在ResNet或ViT作為Backbone。實(shí)驗(yàn)表明,ViT的效果要好于ResNet。
0x02 CLIP 損失函數(shù)
CLIP采用對(duì)稱損失函數(shù),簡(jiǎn)單來說,就是對(duì)相似度矩陣,分別從行方向和列方向計(jì)算loss,最后取兩者的平均。
偽代碼如下:
# image_encoder - ResNet or Vision Transformer# text_encoder - CBOW or Text Transformer# I[n, h, w, c] - minibatch of aligned images# T[n, l] - minibatch of aligned texts# W_i[d_i, d_e] - learned proj of image to embed# W_t[d_t, d_e] - learned proj of text to embed# t - learned temperature parameter# extract feature representations of each modalityI_f = image_encoder(I) #[n, d_i]T_f = text_encoder(T) #[n, d_t]# joint multimodal embedding [n, d_e]I_e = l2_normalize(np.dot(I_f, W_i), axis=1)T_e = l2_normalize(np.dot(T_f, W_t), axis=1)# scaled pairwise cosine similarities [n, n]logits = np.dot(I_e, T_e.T) * np.exp(t)# symmetric loss functionlabels = np.arange(n)loss_i = cross_entropy_loss(logits, labels, axis=0)loss_t = cross_entropy_loss(logits, labels, axis=1)loss = (loss_i + loss_t)/2
0x03 CLIP實(shí)踐認(rèn)知
通過代碼來驗(yàn)證一下理解。先安裝CLIP,參考CLIP官方文檔。
$ conda install --yes -c pytorch pytorch torchvision cudatoolkit
$ pip install ftfy regex tqdm
$ pip install git+https://github.com/openai/CLIP.git
測(cè)試腳本:
import torchimport clipfrom PIL import Imagedevice = "cuda" if torch.cuda.is_available() else "cpu"model, preprocess = clip.load("ViT-B/32", device=device)image = preprocess(Image.open("CLIP.png")).unsqueeze(0).to(device)text = clip.tokenize(["a diagram", "a dog", "a cat"]).to(device)with torch.no_grad():
image_features = model.encode_image(image)
print("image_features shape:", image_features.shape) # [1, 512]
text_features = model.encode_text(text)
print("text_features shape:", text_features.shape) # [3, 512]
logits_per_image, logits_per_text = model(image, text)
print("logits_per_image shape:", logits_per_image.shape) # [1, 3]
print("logits_per_text shape:", logits_per_text.shape) # [3, 1]
probs = logits_per_image.softmax(dim=-1).cpu().numpy()print("Label probs:", probs) # prints: [[0.9927937 0.00421068 0.00299572]]print(" Label: {}".format(["a diagram", "a dog", "a cat"]))
0x04 LLaVA模型結(jié)構(gòu)
paper: https://arxiv.org/pdf/2304.08485.pdf
LLaVA的模型結(jié)構(gòu)非常簡(jiǎn)單,無非就是CLIP+LLM(Vicuna,LLaMA結(jié)構(gòu)),利用Vison Encoder將圖片轉(zhuǎn)換為[N=1, grid_H x grid_W, hidden_dim]的feature map,然后接一個(gè)插值層Projection W,將圖像特征和文本特征進(jìn)行維度對(duì)齊。經(jīng)過Projection后,得到[N=1, grid_H x grid_W=image_seqlen, emb_dim]。然后將 image token embedding和text token embedding合并到一起,作為語(yǔ)言模型的輸入,生成描述的文本。
0x05 CLIP在LLaVA中的應(yīng)用
在LLaVA中,Vision Encoder使用的是CLIP-ViT-L/14,并且,需要注意的是,LLaVA使用最后一層Transformer之前或之后的grid features作為圖像表示,而不是CLIP最后的輸出層。
0x06 LLaVA兩階段訓(xùn)練
階段一:特征對(duì)齊預(yù)訓(xùn)練。由于從CLIP提取的特征與word embedding不在同一個(gè)語(yǔ)義表達(dá)空間,因此,需要通過預(yù)訓(xùn)練,將image token embedding對(duì)齊到text word embedding的語(yǔ)義表達(dá)空間。這個(gè)階段凍結(jié)Vision Encoder和LLM模型的權(quán)重參數(shù),只訓(xùn)練插值層Projection W的權(quán)重。
階段二:端到端訓(xùn)練。這個(gè)階段,依然凍結(jié)Vision Encoder的權(quán)重,訓(xùn)練過程中同時(shí)更新插值層Projection W和LLM語(yǔ)言模型的權(quán)重,訓(xùn)練考慮Multimodal Chatbot和Science QA兩種典型的任務(wù)。
實(shí)驗(yàn)結(jié)論:實(shí)驗(yàn)結(jié)果表明LLaVA在對(duì)話、細(xì)節(jié)描述和復(fù)雜推理等任務(wù)上均優(yōu)于BLIP-2。
0x07 LLaVA 1.5
paper: https://arxiv.org/pdf/2310.03744.pdf
LLaVA 1.5和LLaVA在模型架構(gòu)上基本一致,對(duì)LLM模型和插值層做了修改,但是模型效果逐漸開始炸裂~
LLM模型:LLM語(yǔ)言模型升級(jí)為Vicuna v1.5 13B,語(yǔ)言模型參數(shù)量更大,效果更好
Connector:也就是插值層,由原來的單個(gè)線性層替換為MLP層(多層線性層疊加)
Vision Encoder: 輸入圖像分辨率由224增大為336,使用CLIP ViT-L/336px,對(duì)圖像細(xì)節(jié)理解能力更強(qiáng)
更高質(zhì)量的數(shù)據(jù):真所謂 Data is All you need!
這里貼一下 LLaVA 1.5論文的雷達(dá)圖,之后的LLaVA系列,基本都用這張圖作為baseline,卷起來了...
0x08 對(duì)OCR任務(wù)的影響
LLaVA模型具有in-context learning和Zero-shot multilingual capability的能力,比如OCR任務(wù),不同于以往的深度學(xué)習(xí)OCR算法(必須單獨(dú)訓(xùn)練針對(duì)OCR任務(wù)的模型),LLaVA本身就可以直接應(yīng)用與OCR,指定合適的Prompt,就可以從圖片中提取文字(或者說通用多模態(tài)-圖生文大模型都具有這種能力)。
0x09 LLaVA 1.6
blog: https://llava-vl.github.io/blog/2024-01-30-llava-next//2024-01-30-llava-next/
24年1月30日,LLaVA發(fā)布了1.6版本,模型效果又得到了進(jìn)一步提升,增強(qiáng)了推理,OCR和世界知識(shí)的能力。模型參數(shù)量來到了34B,比1.5版本的13B有了巨大的提升,同時(shí)模型效果在各項(xiàng)指標(biāo)都直接有10個(gè)點(diǎn)以上的提升。真是力大飛磚,太卷了... 主要改變是:
Vision Encoder分辨率:支持更大的分辨率,包括672x672, 336x1344, 1344x336 幾種分辨率的輸入,并且支持通過圖片裁切,編碼,合并來實(shí)現(xiàn)。
LLM模型參數(shù)量大升級(jí):由LLaVA 1.5的13B參數(shù),增加到最多34B參數(shù)。
OCR能力提升:更好的推理和OCR能力:通過修改指令數(shù)據(jù)集實(shí)現(xiàn)
更好的視覺對(duì)話:在一些場(chǎng)景下,擁有更好的世界知識(shí)
0x0a TinyLLaVA
paper: https://arxiv.org/pdf/2402.14289.pdf
TinyLLaVA,3B模型開始來卷7B模型,論文中效果,TinyLLaVA 3.1B整體上還要優(yōu)于LLaVA-1.5-7B模型。模型參數(shù)減半,效果反而更優(yōu)。
0x0b VILA
paper: https://arxiv.org/pdf/2312.07533.pdf (NVIDIA作品)
VILA是NVIDIA的作品。對(duì)比的基線是LLaVA-1.5,各項(xiàng)指標(biāo)均有提升,但是對(duì)比LLaVA 1.6似乎稍有遜色。
0x0c TensorRT-LLM部署
目前,LLaVA系列和VILA模型的部署,已經(jīng)在TensorRT-LLM最新的版本支持。傳送門:
0x0d 總結(jié)
本文簡(jiǎn)單梳理了LLaVA和CLIP的模型結(jié)構(gòu),并講解了CLIP在LLaVA中的應(yīng)用。持續(xù)更新中......
- The End -
長(zhǎng)按二維碼關(guān)注我們
本公眾號(hào)專注:
1. 技術(shù)分享;
2. 學(xué)術(shù)交流;
3. 資料共享。
歡迎關(guān)注我們,一起成長(zhǎng)!
