节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学。
针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。
合集:
本文主要记录一下CLIP和LLaVA系列模型的核心点,便于自己后续面试和实战使用。喜欢记得收藏、关注、点赞。
CLIP 模型结构
paper: https://arxiv.org/pdf/2103.00020.pdf
CLIP 模型结构
CLIP模型是一个双塔结构,包括一个文本编码器Text Encoder和一个图像编码器Image Encoder。训练数据集的形式为(image, text),对于每个正确匹配的image和text,text是对image的一句正确描述。CLIP模型需要对(image, text)的数据对进行预测,即(image, text)匹配的为1,不匹配的为0。
-
Text Encoder: 对于每个句子,将其编码成一个隐向量,
维度(1,512);N个句子,因此有
,即[N, 512]
-
Image Encoder: 对于每张img,将其编码成一个隐向量,
维度(1,512);
N张图,因此有
-
,即[N, 512]
由于Text Encoder和Image Encoder最后都是输出[N,512]的Tensor,因此可以很方便地计算images和texts两两之间的相似度。CLIP可以选在ResNet或ViT作为Backbone。实验表明,ViT的效果要好于ResNet。
CLIP ViT vs CLIP ResNet
CLIP 损失函数
CLIP采用对称损失函数,简单来说,就是对相似度矩阵,分别从行方向和列方向计算loss,最后取两者的平均。
CLIP 损失函数
伪代码如下:
# 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
CLIP 实践认知
通过代码来验证一下理解。先安装CLIP,参考CLIP官方文档。
$ conda install --yes -c pytorch pytorch torchvision cudatoolkit
$ pip install ftfy regex tqdm
$ pip install git+https://github.com/openai/CLIP.git
测试脚本:
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"]))
LLaVA模型结构
paper: https://arxiv.org/pdf/2304.08485.pdf
LLaVA模型结构
LLaVA的模型结构非常简单,无非就是CLIP+LLM(Vicuna,LLaMA结构),利用Vison Encoder将图片转换为[N=1, grid_H x grid_W, hidden_dim]的feature map,然后接一个插值层Projection W,将图像特征和文本特征进行维度对齐。经过Projection后,得到[N=1, grid_H x grid_W=image_seqlen, emb_dim]。然后将 image token embedding和text token embedding合并到一起,作为语言模型的输入,生成描述的文本。
CLIP在LLaVA中的应用
在LLaVA中,Vision Encoder使用的是CLIP-ViT-L/14,并且,需要注意的是,LLaVA使用最后一层Transformer之前或之后的grid features作为图像表示,而不是CLIP最后的输出层。
LLaVA两阶段训练
- 阶段一:特征对齐预训练。由于从CLIP提取的特征与word embedding不在同一个语义表达空间,因此,需要通过预训练,将image token embedding对齐到text word embedding的语义表达空间。这个阶段冻结Vision Encoder和LLM模型的权重参数,只训练插值层Projection W的权重。
- 阶段二:端到端训练。这个阶段,依然冻结Vision Encoder的权重,训练过程中同时更新插值层Projection W和LLM语言模型的权重,训练考虑Multimodal Chatbot和Science QA两种典型的任务。
- 实验结论:实验结果表明LLaVA在对话、细节描述和复杂推理等任务上均优于BLIP-2。
LLaVA 1.5
paper: https://arxiv.org/pdf/2310.03744.pdf
LLaVA 1.5和LLaVA在模型架构上基本一致,对LLM模型和插值层做了修改,但是模型效果逐渐开始炸裂~
LLM模型:LLM语言模型升级为Vicuna v1.5 13B,语言模型参数量更大,效果更好
-
Connector:也就是插值层,由原来的单个线性层替换为MLP层(多层线性层叠加)
-
Vision Encoder: 输入图像分辨率由224增大为336,使用CLIP ViT-L/336px,对图像细节理解能力更强
-
更高质量的数据:真所谓 Data is All you need!
这里贴一下 LLaVA 1.5论文的雷达图,之后的LLaVA系列,基本都用这张图作为baseline,卷起来了…
对OCR任务的影响
LLaVA模型具有in-context learning和Zero-shot multilingual capability的能力,比如OCR任务,不同于以往的深度学习OCR算法(必须单独训练针对OCR任务的模型),LLaVA本身就可以直接应用与OCR,指定合适的Prompt,就可以从图片中提取文字(或者说通用多模态-图生文大模型都具有这种能力)。
LLaVA 1.6
blog: https://llava-vl.github.io/blog/2024-01-30-llava-next//2024-01-30-llava-next/
24年1月30日,LLaVA发布了1.6版本,模型效果又得到了进一步提升,增强了推理,OCR和世界知识的能力。模型参数量来到了34B,比1.5版本的13B有了巨大的提升,同时模型效果在各项指标都直接有10个点以上的提升。真是力大飞砖,太卷了… 主要改变是:
- Vision Encoder分辨率:支持更大的分辨率,包括672x672, 336x1344, 1344x336 几种分辨率的输入,并且支持通过图片裁切,编码,合并来实现。
-
LLM模型参数量大升级:由LLaVA 1.5的13B参数,增加到最多34B参数。
-
OCR能力提升:更好的推理和OCR能力:通过修改指令数据集实现
-
更好的视觉对话:在一些场景下,拥有更好的世界知识
TinyLLaVA
paper: https://arxiv.org/pdf/2402.14289.pdf
TinyLLaVA,3B模型开始来卷7B模型,论文中效果,TinyLLaVA 3.1B整体上还要优于LLaVA-1.5-7B模型。模型参数减半,效果反而更优。
VILA
paper: https://arxiv.org/pdf/2312.07533.pdf (NVIDIA作品)
VILA是NVIDIA的作品。对比的基线是LLaVA-1.5,各项指标均有提升,但是对比LLaVA 1.6似乎稍有逊色。
TensorRT-LLM部署
目前,LLaVA系列和VILA模型的部署,已经在TensorRT-LLM最新的版本支持。
传送门:
https://github.com/NVIDIA/TensorRT-LLM/tree/main/examples/multimodal
https://github.com/NVIDIA/TensorRT-LLM/tree/main/examples/multimodal
总结
本文简单梳理了LLaVA和CLIP的模型结构,并讲解了CLIP在LLaVA中的应用。持续更新中…