2、向量化技术基础:Embedding模型简介、文本向量化、图像向量化、向量维度与精度权衡

好,我们正式开始聊向量化的底层逻辑。

很多人一上来就问我:「选哪个向量数据库好?」

我的回答通常是——你先搞清楚你的数据怎么变成向量。数据库再快,喂进去的向量是垃圾,查出来也是垃圾。这个道理,我在好几个项目里都吃过亏。

2.1 Embedding模型:到底在做什么?

说白了,Embedding 就是把「猫」、「狗」、「苹果」、「手机」这些人类能理解的概念,映射到一组浮点数上。比如「猫」可能变成 [0.23, -0.45, 0.67, ...],一共几百上千个数字。

这些数字不是乱给的。模型训练出来后,语义相近的词,它们的向量在空间里也靠得近。「猫」和「狗」的距离,肯定比「猫」和「汽车」近。这就是向量化的核心价值——把非结构化数据变成可计算的距离。

核心公式: 语义相似度 ≈ 向量空间距离(余弦距离 / 欧氏距离)

我个人习惯把 Embedding 模型理解成一个「翻译器」。它把人类语言翻译成机器能算的数学语言。你想想看,没有这个翻译器,数据库怎么知道「苹果手机」和「iPhone 15」是同一个东西?

2.2 文本向量化: vs 开源模型

文本向量化是最常见的场景。目前主流方案分两派:闭源 API 和开源模型。

2.2.1 Embedding API

的 text-embedding-3-small 和 text-embedding-3-large 是目前工业界用得最多的。我去年做一个知识库项目,直接调 API,效果确实稳。

import 

response = .embeddings.create(
    model="text-embedding-3-small",
    input="向量数据库选型指南"
)
embedding = response.data[0].embedding
print(len(embedding))  # 输出: 1536

输出 1536 维。什么意思?就是每个文本被表示成 1536 个浮点数。维度越高,信息越丰富,但存储和计算成本也越高。这个后面会细说。

我的经验: text-embedding-3-small 在大部分场景下够用了。large 版本 3072 维,精度提升有限,但成本翻倍。别盲目上大模型。

2.2.2 开源模型:BGE / Instructor / Sentence-BERT

如果你对数据隐私有要求,或者不想付 API 费,开源模型是唯一选择。

我比较推荐 BGE(BAAI General Embedding)系列。它在 MTEB 榜单上表现不错,而且中文支持好。用起来也不复杂:

from sentence_transformers import SentenceTransformer

model = SentenceTransformer('BAAI/bge-large-zh-v1.5')
embeddings = model.encode("向量数据库选型指南")
print(embeddings.shape)  # 输出: (1024,)

1024 维。比 小,但中文场景下效果不差。我在一个金融文档检索项目里做过对比,BGE 的召回率只比 低 2-3 个百分点,但成本几乎为零。

模型 维度 中文支持 成本 适用场景
text-embedding-3-small 1536 好 按 收费 通用、快速验证
text-embedding-3-large 3072 好 高 高精度需求
BGE-large-zh-v1.5 1024 优秀 免费 中文场景、私有部署
Instructor-XL 768 一般 免费 多任务指令嵌入
Sentence-BERT (all-MiniLM) 384 差 免费 轻量、英文场景
避坑: 我曾经在一个项目里直接用 Sentence-BERT 处理中文文档,结果召回率惨不忍睹。后来换成 BGE,效果直接翻倍。开源模型一定要选对语言版本。

2.3 图像向量化:不只是「看图说话」

图像向量化和文本不太一样。文本有天然的分词结构,图像是一堆像素。怎么把一张图变成向量?

主流做法是用预训练的 CNN 或 Vision Transformer(ViT)模型,把图像通过模型的全连接层之前的那一层特征提取出来。这一层输出的向量,就是图像的 Embedding。

from transformers import CLIPProcessor, CLIPModel
from PIL import Image

model = CLIPModel.from_pretrained("/clip-vit-base-patch32")
processor = CLIPProcessor.from_pretrained("/clip-vit-base-patch32")

image = Image.open("product_photo.jpg")
inputs = processor(images=image, return_tensors="pt")
image_features = model.get_image_features(**inputs)

print(image_features.shape)  # 输出: torch.Size([1, 512])

CLIP 模型有个好处——它同时支持文本和图像,能把两者映射到同一个向量空间。这意味着你可以用文字搜图片,或者用图片搜图片。我在一个电商项目里就用 CLIP 做「以图搜图」,效果相当好。

关键点: 图像向量化时,输入尺寸、预处理方式(归一化、裁剪)会直接影响向量质量。别偷懒,预处理步骤一定要对齐模型训练时的配置。

2.4 向量维度与精度权衡:没有免费的午餐

这是本章最核心的部分。我见过太多人一上来就选 3072 维,觉得维度越高越好。其实不是。

维度越高,带来的问题越明显:

  • 存储成本: 1536 维 float32 向量,每个占 6KB。1000 万条就是 60GB。3072 维直接翻倍。
  • 计算成本: 高维向量的距离计算更慢。暴力搜索时,维度每翻一倍,耗时也翻倍。
  • 维度诅咒: 维度太高时,所有向量之间的距离都趋于相等,区分度反而下降。这是数学上的问题,不是模型能解决的。

那怎么选?我一般按这个原则:

  1. 先看数据量: 百万级以下,1536 维随便用。千万级以上,考虑降维到 768 或 512。
  2. 再看精度要求: 搜索场景(Top-K 召回),768 维通常够用。分类或聚类场景,可能需要更高维度。
  3. 最后看硬件: GPU 显存有限的话,优先降维。我有个项目用 384 维的 MiniLM,在 CPU 上跑得飞快,精度损失不到 5%。
降维技巧: 可以用 PCA 或 UMAP 把高维向量降到 256-512 维。我试过把 1536 维降到 512 维,召回率只掉了 1-2%,但查询速度提升了 3 倍。划算。

嗯,这里还要提一下精度格式。大部分模型输出 float32,但你可以转成 float16 甚至 int8。float16 精度损失几乎不可感知,但存储减半。int8 损失稍大,但适合大规模场景。

import numpy as np

# float32 -> float16
embedding_f32 = np.array([0.123456, -0.789012, ...], dtype=np.float32)
embedding_f16 = embedding_f32.astype(np.float16)

# 量化到 int8
scale = np.max(np.abs(embedding_f32))
embedding_i8 = (embedding_f32 / scale * 127).astype(np.int8)
注意: 量化后的向量不能直接和原始向量混用。要么全库统一量化,要么在查询时也量化查询向量。我曾经踩过这个坑,查出来的结果全是乱的。

2.5 本章知识体系总览

下面这张图把本章的核心逻辑串起来了。从原始数据到向量,再到维度权衡,每一步都有取舍。

向量化技术基础:知识体系 原始数据 文本:句子 / 段落 图像:像素矩阵 Embedding 模型 / BGE / CLIP 向量表示 维度:384~3072 维度 vs 精度 vs 成本 高维度 → 高精度 + 高成本 降维 → 速度提升 + 精度微损 量化 → 存储减半 + 精度可控 核心原则:根据数据量、精度要求、硬件资源,在维度与精度之间找到平衡点 没有最优,只有最适合你场景的配置

总结一下:向量化不是越「大」越好。选模型、选维度、选精度,都是在做 trade-off。我个人的习惯是:先用小维度快速验证,再根据效果逐步调整。别一上来就追求完美,先跑通再说。