嵌入(Embedding)是什么?
- 定义: 把每个词或句子转化成一串数字(向量,如 [0.2, -0.5, 0.8, ...]),并让语义相近的内容转化出的数字串也相近;
- 向量空间: 这些向量所在的数学空间,可想象成一张高维地图,语义越接近的内容彼此越靠近;
- 经典例子:
“国王” - “男性” + “女性” ≈ “女王”,说明向量运算能捕捉语义关系;
- “稠密”的含义: 相对于稀疏嵌入而言——稠密向量的每个维度都有数值,稀疏向量大部分维度为零;
- 作用: 用深度学习把文本映射到向量空间,语义相近则向量距离也近;
为什么用余弦相似度而不是距离?
- 公式:
cos(θ) = (A·B) / (|A| × |B|),A·B 是点积(对应维度相乘再求和),|A| 是模(各维度平方和的平方根);
- 直觉: 关心两个向量的方向是否一致(语义是否相近),而不是它们的长度(文本的长度或频率);
- 理由: 两篇内容相同但长度不同的文档,向量长度不同但方向一致,余弦相似度能正确判断语义相同;
- 手算示例: “如何养猫” A=(0.9, 0.5, 0.1) 与“猫咪饲养指南” B=(0.8, 0.6, 0.1) 的 cos(θ) ≈ 0.99;与“股票投资策略” C=(0.1, 0.1, 0.9) 的 cos(θ) ≈ 0.25;
- 量级: 实际嵌入模型使用 768 维甚至更高维度,但判断“是否相似”的原理完全相同;
稠密嵌入如何从 Word2Vec 演进到上下文感知?
- Word2Vec: 通过分析海量文本中的词汇共现关系,为每个词生成一个固定向量,能捕捉
king - man + woman ≈ queen 这类线性语义关系;
- 静态向量的局限: 无法处理一词多义——“bank”在“river bank”(河岸)与“investment bank”(投资银行)中得到完全相同的向量;
- 上下文感知模型(BERT、BGE-M3): 生成一个词的向量时充分考虑其所在句子甚至段落,同一词在不同语境下得到不同向量;
- 机制: 自注意力(Self-Attention)让模型计算每个词向量时同时参考句子中所有其他词的信息;
- 例子: “苹果”在“苹果公司发布新产品”与“买了两斤苹果”中得到不同的向量表示,实现从“词汇级”到“语境级”语义的飞跃;
- 长文本: BERT 这类较早的上下文模型输入长度上限仅 512 个 token,不适合长文本;BGE-M3 等新一代模型进一步支持多语言与长文本;
- 注意: BGE-M3 实际同时输出稠密、稀疏、多向量三种表示,此处仅以其稠密输出为例;
什么是 ANN,为什么需要它?
- 场景: 知识库有上百万条文档时,逐一计算相似度太慢;
- ANN(Approximate Nearest Neighbor,近似最近邻): 通过巧妙的索引结构,在海量向量中实现近似但极快的最近邻查找;
- 收益: 用少量精度损失换取数量级的查询速度;
- 实现选择:
dense-embedding 项目提供 ANNOY 与 HNSW 两种可切换后端,直接观察两类主流 ANN 算法的区别;
ANNOY 与 HNSW 如何取舍?
| 特性 | ANNOY(基于树) | HNSW(基于图) |
|---|
| 构建速度 | 快 | 较慢 |
| 内存占用 | 低 | 较高 |
| 增量更新 | 不支持(需完全重建) | 支持(长期增量插入后建议定期重建以保持查询精度) |
| 查询精度 | 较高 | 极高 |
| 适用场景 | 数据不常变的静态数据集 | 需要实时索引新信息的动态场景 |
- 结论: 选择合适的索引策略与选择嵌入模型同等重要,它直接决定系统的性能、成本和可维护性;