4. 向量化模型选择:文本、图像与多模态
模型选得好,评估结果才靠谱。这个道理,我是在第一次做向量检索评测时摔了跟头才真正理解的。
当时我随便选了个通用 embedding 模型,结果在垂直领域的数据上,召回率惨不忍睹。后来才明白——向量化模型,是整个评估集的基石。选错了,后面所有工作都是白费。
这一章,我们就来聊聊怎么选模型。我会把文本、图像、多模态这三条线拆开讲,再结合我踩过的坑,给你一份实用的选型指南。
核心观点:没有最好的模型,只有最适合你场景的模型。选型前,先搞清楚你的数据长什么样、任务要什么。
4.1 文本向量化模型:从词到句的进化
文本向量化,说白了就是把文字变成一串数字。但怎么变,差别大了去了。
我刚开始做 NLP 时,用的还是 Word2Vec 和 GloVe。每个词一个固定向量,简单粗暴。但有个致命问题——一词多义。比如「苹果」这个词,在「吃苹果」和「用苹果手机」里,意思完全不同。Word2Vec 可不管这些,它给同一个词永远输出同一个向量。
后来 BERT 出来了,才真正解决了这个问题。
4.1.1 BERT:上下文感知的语义理解
BERT 的核心思想很简单:每个词的向量,由它周围的词决定。你想想看,这多合理。
举个例子,「他正在银行存钱」和「他坐在银行河边钓鱼」,两个「银行」的向量完全不同。前者偏向金融语义,后者偏向地理语义。
我在项目中用过 BERT 做文本相似度计算。效果确实好,但有个坑——BERT 输出的不是句子级向量。它输出的是每个 的向量,如果你直接取 [CLS] 或者做平均池化,效果往往不理想。
我的经验:如果你用 BERT 做句子相似度,别直接用原始输出。试试 mean pooling 或者 max pooling,效果会好不少。我一般用 mean pooling,稳定。
4.1.2 Sentence-BERT:专为句向量而生
BERT 的痛点,Sentence-BERT 解决了。它用孪生网络结构,专门优化句子级别的语义表示。
什么意思呢?就是两个句子分别过同一个 BERT,然后计算它们的相似度。训练时用对比学习,让相似句子靠近,不相似的远离。
我个人习惯用 all-MiniLM-L6-v2 这个版本。速度快,效果好,768 维向量,够用。在语义搜索、聚类、去重这些场景下,表现很稳。
# 用 Sentence-BERT 生成句向量
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
sentences = [
"我今天心情很好",
"今天天气真不错",
"这个产品太难用了"
]
embeddings = model.encode(sentences)
print(embeddings.shape) # (3, 768)
注意:Sentence-BERT 对长文本不太友好。默认最大长度 256 ,超过的部分会被截断。如果你的文档很长,建议先分段再向量化。
4.1.3 Embeddings:省心但贵
如果你不想自己训练模型,也不想部署, 的 Embeddings API 是个省心选择。
我曾在客户项目里用过 text-embedding-ada-002。1536 维向量,语义理解能力很强。中文效果也不错,毕竟训练数据量大。
但有两个问题:
- 成本:按 收费。数据量大了,费用蹭蹭往上涨。我有个项目每天要处理 100 万条文本,一个月下来账单吓人。
- 隐私:数据要传到 服务器。敏感数据不能这么干。
所以我的建议是:小规模实验用 ,生产环境用开源模型。
| 模型 | 维度 | 最大长度 | 中文效果 | 部署成本 | 适用场景 |
|---|---|---|---|---|---|
| BERT-base | 768 | 512 | 好 | 中 | 语义理解、分类 |
| Sentence-BERT | 384/768 | 256 | 好 | 低 | 语义搜索、聚类 |
| ada-002 | 1536 | 8191 | 优秀 | 高 | 通用场景、快速验证 |
4.2 图像向量化模型:从像素到特征
图像向量化,就是把一张图变成一串数字。这个数字要能代表图像的内容、风格、结构等信息。
我最早做图像检索时,用的是手工特征——SIFT、HOG 这些。效果嘛,只能说凑合。后来 CNN 一统天下,ResNet 成了标配。
4.2.1 ResNet:残差学习的经典
ResNet 解决了深层网络退化的问题。简单说,就是网络越深,效果反而变差。ResNet 用残差连接,让梯度能直接传到前面层,训练更稳定。
在图像向量化场景下,我们通常取 ResNet 的 倒数第二层全连接层之前的特征。这个特征向量包含了图像的语义信息,可以用来做相似度计算。
# 用 ResNet 提取图像特征
import torch
import torchvision.models as models
from torchvision import transforms
from PIL import Image
model = models.resnet50(pretrained=True)
# 去掉最后的全连接层
model = torch.nn.Sequential(*list(model.children())[:-1])
model.eval()
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
img = Image.open('example.jpg')
img_tensor = transform(img).unsqueeze(0)
with torch.no_grad():
features = model(img_tensor)
features = features.squeeze().numpy()
print(features.shape) # (2048,)
避坑指南:ResNet 提取的特征对图像分类任务很友好,但对细粒度相似度(比如两件衣服的款式差异)表现一般。我曾经用它做服装检索,结果颜色相近但款式不同的衣服,相似度反而很高。后来换了 CLIP,效果才好起来。
4.2.2 CLIP:图文对齐的新范式
CLIP 是 2021 年发布的模型。它用 4 亿对图文数据训练,学会了把图像和文本映射到同一个向量空间。
这意味着什么?你可以用文字描述来搜索图片。比如输入「一只在草地上奔跑的狗」,CLIP 能找到对应的图片。
在图像向量化场景下,CLIP 的优势很明显:
- 语义理解强:不只是识别物体,还能理解场景、动作、情感
- 零样本能力:没见过的类别也能处理
- 多模态对齐:图像和文本在同一空间,方便做跨模态检索
我个人习惯用 ViT-B/32 这个版本。速度适中,效果不错。如果你要更高精度,可以上 ViT-L/14,但显存占用也更大。
4.3 多模态模型:打通文本与图像的桥梁
多模态模型,说白了就是能同时理解文本和图像的模型。CLIP 是其中最典型的代表。
但多模态模型不只是 CLIP。还有像 ALIGN(Google)、BLIP(Salesforce)、FLAVA(Meta)这些。它们各有侧重。
我在做电商搜索项目时,用过 CLIP 做图文匹配。用户输入「红色连衣裙」,系统返回图片。效果比纯文本搜索好很多,因为 CLIP 能理解「红色」和「连衣裙」这两个概念在图像中的对应关系。
| 模型 | 训练数据 | 向量维度 | 特点 | 适用场景 |
|---|---|---|---|---|
| CLIP | 4亿图文对 | 512/768 | 零样本能力强 | 图文检索、分类 |
| ALIGN | 18亿图文对 | 640 | 数据量大,泛化好 | 大规模检索 |
| BLIP | 1.29亿图文对 | 768 | 生成+理解兼顾 | 图文生成、问答 |
注意:多模态模型对显存要求高。CLIP ViT-L/14 需要至少 8GB 显存。如果你用 CPU 推理,速度会很慢。建议用 GPU,或者用量化版本。
4.4 选型决策:我该用哪个?
说了这么多,到底怎么选?我给你一个简单的决策流程:
- 先看数据模态:纯文本?纯图像?还是图文混合?
- 再看任务类型:语义搜索?图像检索?图文匹配?
- 然后看性能要求:精度优先还是速度优先?
- 最后看成本预算:能接受 API 付费吗?有 GPU 资源吗?
举个例子:
- 如果你做文本语义搜索,Sentence-BERT 是首选。效果好,部署简单。
- 如果你做图像检索,CLIP 比 ResNet 强。语义理解更丰富。
- 如果你做图文匹配,CLIP 或 BLIP 都行。看你的数据量。
- 如果你只是快速验证想法, Embeddings 最省事。
我的建议:不要一上来就选最复杂的模型。先用简单的跑通流程,再逐步优化。我曾经在一个项目里,一开始就上了 CLIP,结果数据预处理就花了两周。后来换成 Sentence-BERT,三天就出了结果。
嗯,模型选型就聊到这里。记住一句话:模型是工具,不是目的。选对工具,事半功倍。