01 Embedding与向量数据库
摘要
本笔记深入探讨了Embedding和向量数据库的核心概念与应用。Embedding是将文本、图片等非结构化数据转化为高维向量,捕捉其语义信息。向量数据库则高效存储和检索这些向量,为LLM提供长期记忆和语义搜索能力,并详细介绍了Word2Vec、TF-IDF等Embedding技术以及FAISS等向量数据库的实际应用。
什么是Embedding
Embedding是一种降维技术,旨在将不同特征(如文本、图像等)转换为固定维度的向量,从而将离散数据映射到低维、稠密的数学空间中,并捕捉其语义信息。
核心概念
- 降维方式:将高维、稀疏的离散变量(如one-hot编码)转换为固定大小的稠密向量。
- 语义相似度:在向量空间中,语义相似的物体之间的向量距离(如余弦相似度)会更近。
- 可运算性:向量可以进行数学运算,实现语义推理。
余弦相似度计算
余弦相似度用于度量两个向量方向上的相似性,值域为 [-1, 1]。
1表示方向完全相同(高度相似)0表示方向正交(无相关性)-1表示方向完全相反(高度不相似)
N-Gram
N-Gram是一种简单的文本特征提取方法,基于假设:第n个词的出现只与前n-1个词相关。
- Unigram (N=1): 单个词
- Bigram (N=2): 两个连续词的组合
- Trigram (N=3): 三个连续词的组合
代码示例:N-Gram词频统计
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
import matplotlib.pyplot as plt
df = pd.read_csv('Seattle_Hotels.csv', encoding="latin-1")
def get_top_n_words(corpus, n=1, k=None):
vec = CountVectorizer(ngram_range=(n, n), stop_words='english').fit(corpus)
bag_of_words = vec.transform(corpus)
sum_words = bag_of_words.sum(axis=0)
words_freq = [(word, sum_words[0, idx]) for word, idx in vec.vocabulary_.items()]
words_freq = sorted(words_freq, key=lambda x: x[1], reverse=True)
return words_freq[:k]
common_words_bigram = get_top_n_words(df['desc'], 2, 20)
df_bigram = pd.DataFrame(common_words_bigram, columns=['desc', 'count'])
df_bigram.groupby('desc').sum()['count'].sort_values(ascending=True).plot(
kind='barh', title='Top20 Bigram'
)
plt.show()
TF-IDF
TF-IDF (Term Frequency-Inverse Document Frequency) 评估一个词对于文档集中某文档的重要程度。
- TF (词频):单词在文档中出现的次数 / 文档总词数
- IDF (逆向文档频率):log(文档总数 / 单词出现的文档数 + 1)
代码示例:TF-IDF特征提取与余弦相似度
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import linear_kernel
tf = TfidfVectorizer(analyzer='word', ngram_range=(1, 3), min_df=0, stop_words='english')
tfidf_matrix = tf.fit_transform(df['desc_clean'])
cosine_similarities = linear_kernel(tfidf_matrix, tfidf_matrix)
def recommendations(name, cosine_similarities=cosine_similarities):
idx = indices[name]
score_series = pd.Series(cosine_similarities[idx]).sort_values(ascending=False)
top_10_indexes = list(score_series.iloc[1:11].index)
return [list(df.name)[i] for i in top_10_indexes]
Word Embedding
Word Embedding将单词映射到低维、稠密的连续向量空间,语义相似的词在向量空间中距离更近。
核心特性
- 降维:将高维one-hot向量转换为固定维度的Embedding向量
- 语义信息捕捉:向量捕获单词的语义和语法信息
- 可运算性:例如
king - man + woman ≈ queen
Word2Vec
Word2Vec有两种主要模式:
- Skip-Gram:给定输入词,预测其上下文词
- CBOW (Continuous Bag-of-Words):给定上下文词,预测输入词
使用Gensim训练Word2Vec
from gensim.models import word2vec
import multiprocessing
sentences = word2vec.PathLineSentences('./segment')
model = word2vec.Word2Vec(
sentences,
vector_size=100,
window=5,
min_count=5,
workers=multiprocessing.cpu_count()
)
print(model.wv.similarity('孙悟空', '猪八戒'))
model.save('./models/word2Vec.model')
Embedding模型的选择
MTEB榜单
MTEB (Massive Text Embedding Benchmark) 是全面的文本Embedding模型评测基准,涵盖8大类任务和58个数据集,包括分类、聚类、检索、重排序、STS等任务类型。
向量维度对模型性能的影响
- 高维度 (1024, 4096):语义更丰富,但计算和存储成本更高
- 低维度 (256, 512):计算快,内存小,适合资源受限场景
Matryoshka Representation Learning (MRL)
Jina-embeddings模型采用MRL技术,生成「俄罗斯套娃」特性的向量:
- 内部生成最完整的高维向量(如2048维)
- 前缀子向量(如128/256/512维)本身即可独立使用
- 通过
embedding_size参数按需指定维度
模型选择建议
| 场景 | 推荐 |
|---|---|
| 单一中文场景 | BGE-large-zh 等单语言模型 |
| 多语言跨语言检索 | m3e-base, multilingual-e5-large |
| 追求极致性能 | 参考MTEB榜单,构建黄金测试集评测 |
向量数据库
向量数据库存储和查询由非结构化数据转化而来的高维向量嵌入,向量间距离代表原始数据的语义相似度。
核心价值
- 为大模型提供长期记忆,弥补Context Window限制
- 实现私有知识库的语义搜索
- 赋能推荐系统、以图搜图等应用
常见向量数据库对比
| 数据库 | 特点 | 适用场景 |
|---|---|---|
| FAISS | Meta AI开发,纯算法库,GPU加速 | 研究场景,需深度集成 |
| Milvus | 开源云原生,高扩展性 | 企业级海量数据 |
| Pinecone | 全托管Serverless | 快速上线,低运维 |
| Weaviate | 内置向量化模块 | 简化ETL流程 |
| Qdrant | Rust开发,复杂过滤 | 极致性能需求 |
| Elasticsearch | 混合搜索 | 文本+向量混合场景 |
FAISS使用示例:Embedding与元数据导入
import numpy as np
import faiss
from openai import OpenAI
client = OpenAI(
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
documents = [
{"id": "doc1", "text": "迪士尼门票退票政策...", "metadata": {"category": "退票政策"}},
{"id": "doc2", "text": "年卡用户享受折扣...", "metadata": {"category": "会员权益"}},
]
# 生成向量
metadata_store = []
vectors_list = []
for i, doc in enumerate(documents):
result = client.embeddings.create(
model="text-embedding-v4",
input=doc["text"],
dimensions=1024,
encoding_format="float"
)
vectors_list.append(result.data[0].embedding)
metadata_store.append(doc)
vectors_np = np.array(vectors_list).astype('float32')
vector_ids_np = np.arange(len(vectors_list))
# 构建FAISS索引(使用IndexIDMap关联元数据)
index = faiss.IndexIDMap(faiss.IndexFlatL2(1024))
index.add_with_ids(vectors_np, vector_ids_np)
# 搜索
query = client.embeddings.create(model="text-embedding-v4", input="退款流程", dimensions=1024, encoding_format="float")
query_vec = np.array([query.data[0].embedding]).astype('float32')
distances, ids = index.search(query_vec, k=3)
for i, doc_id in enumerate(ids[0]):
print(f"排名{i+1}: {metadata_store[doc_id]['text']} (距离: {distances[0][i]:.4f})")
FAISS不存储元数据,需在外部维护「查找表」(Redis/PostgreSQL/MongoDB),用向量ID关联原始数据。
关键要点
- Embedding 是将非结构化数据(文本、图片)转化为高维向量的技术,语义相似的内容在向量空间中距离更近
- TF-IDF + N-Gram 是传统特征提取方法,会产生稀疏矩阵;Word2Vec 等神经网络方法生成稠密向量,语义表达更强
- 选择Embedding模型 需参考MTEB榜单并在自己的黄金测试集上评测,不能仅凭榜单排名决定
- 向量数据库 为LLM提供长期记忆和私有知识库检索能力,FAISS适合研究,Milvus/Qdrant适合生产
- FAISS本身不存储元数据,需借助
IndexIDMap将向量ID与外部元数据存储(Redis/DB)关联