文本的表示反映了语义。
在大语言模型中绝大多数时候在使用时不需要显式的操作词向量/句向量,但是作为内部机理依然在起作用。
这里介绍一下各种传统的和当前的文档向量的方法,里面一些有趣的思路和技巧。
当然在LLM的时代,也不要拘泥于向量,可以回归到文字本身的意义。

传统的手工构建特征,最基本的方法就是看关键词。

文献综述

传统统计时代(1960s–2010s 初)

  • One-hot → 词存在不存在 - 每个词一个维度 - 文档向量 = 词表长度的向量 - 有词=1,没词=0 - 缺点:超级稀疏、无语义、维度爆炸
  • BoW/VSM(词袋模型/向量空间模型)用词频表示文档,稀疏高维向量只看 “有没有、有多少”,无语义。
  • n-gram 计数向量:考虑词的顺序,把 n 个词组合起来作为特征,增加表示能力。
  • TF-IDF 对词频加权:突出重要词,抑制常用词 仍是工业界最经典、最简单的无监督表示。
  • LSA/LSI(潜在语义分析) 对共现矩阵做 SVD 降维 得到稠密向量,捕捉浅层语义关联。
  • LDA(主题模型) 把文档表示为主题分布向量 可解释性强,适合主题挖掘、聚类。
  • 词向量拼接(求和/平均)
  • 词频向量(BoW)
  • TF-IDF 向量
  • LSA/LSI 潜在语义向量
  • LDA 主题向量(文档→主题分布向量)
  • 共现矩阵向量
  • 向量空间模型 VSM(1968,Salton)
    • 核心:把文档/查询映射到词维度向量,用余弦相似度算相关
    • 最早的文档向量范式,奠定所有后续方法的基础
    • 维度 = 词典大小(几万~几十万),极度稀疏
  • 词袋模型 BoW(Bag of Words,1970s)
    • 思想:不考虑词序、语法,只统计词频
    • 文档向量 = 每个词在文档中的出现次数
    • 最简单、最老的文档向量方法:直接词频拼接
    • 缺点:丢失语序、语义弱、稀疏、停用词干扰
  • TF-IDF(1970s–1980s,Salton 完善)
    • 词频加权:TF(词频)× IDF(逆文档频率)
    • 解决:高频词(如“的”)权重过高、低频词被忽略
    • 文档向量 = 每个词的 TF-IDF 值
    • 至今仍是传统检索/基线标配
  • LSA/LSI(潜在语义分析,1990)
    • 用SVD 降维,把稀疏 TF-IDF 矩阵压到低维稠密向量(100–300维)
    • 捕捉潜在语义关联(如“电脑”≈“计算机”)
    • 第一个非词频、非稀疏的文档向量方法
    • 缺点:计算量大、线性模型、语义能力有限
  • N-gram 特征 + 机器学习
    • 用 1-gram、2-gram、3-gram 做特征
    • 丢进 SVM、LR、朴素贝叶斯
    • 文本分类主流很长一段时间
  • 主题模型:LDA(Latent Dirichlet Allocation)
    • 把文档表示成主题分布
    • 比如:科技 30%、体育 20%、娱乐 50%
    • 可看作一种语义向量
  • BM25(不是向量,但算文档表示)
    • 基于词频、逆文档频率、文档长度
    • 不是向量,但用来做相关性打分
    • 至今仍是搜索基线
    • 很多 RAG 系统先用 BM25 再用向量

静态词向量时代(2013–2017)

  • 早期文档向量:词向量平均/加权平均。最简单的文档向量:把词向量求和/平均。改进:SIF/TF-IDF 加权平均,无监督效果显著提升。
  • Word2Vec(2013,Mikolov,Google)
    • Word2Vec 真正意义上的稠密词向量语义、类比、相似度都能算。 词向量,文档=词平均
    • 里程碑:CBOW/Skip-gram,高效学静态词向量(100/300维)
    • 语义:相似词向量近,可做类比(国王-男人+女人≈女王)
    • 文档向量的过渡方法:
    • 简单拼接:所有词向量求和/平均(你说的“词向量拼接”)
    • 缺点:丢失语序、长文档信息稀释、无文档专属向量
  • GloVe(2014,斯坦福)
    • 结合全局词共现+局部窗口,词向量质量更稳
    • 文档向量同样用词向量平均/求和
  • Doc2Vec 第一个专门为文档设计的向量模型 直接学习句子/段落级表示,不再依赖词平均
    • Doc2Vec(Paragraph Vector,2014,Le & Mikolov)
    • Word2Vec 的直接扩展:给每个文档加一个专属向量
    • 两种模式:
    • DM(Distributed Memory):文档向量+上下文词 → 预测中心词
    • DBOW(Distributed Bag of Words):文档向量 → 预测文档内任意词
    • 第一个真正意义上的文档专属向量,解决词向量平均的问题
    • 维度:100/300维,稠密、可训练、语义更强
  • Sent2Vec(2016)
    • 优化 Doc2Vec:词向量加权平均+n-gram 特征
    • 更好捕捉句子/短文档语义,速度更快
  • InferSent 用监督学习做句子向量 比无监督方法更适配相似度、推理任务
  • FastText + 平均 / n-gram 向量

上下文预训练时代(2018–至今)

  • ELMo(2018)
  • BERT 上下文感知,一词多义能正确表示。
    • Transformer 预训练,双向上下文+注意力
    • 文档向量:取 或最后一层平均
  • Sentence-BERT(SBERT) 让 BERT 输出高质量、可直接计算相似度的句子向量 检索、匹配、聚类的标配模型之一。
    • 为句子/短文档向量专门改造 BERT
    • Siamese 结构:独立编码、预存向量、余弦相似度
    • 训练目标:NLI+STS+三元组,语义相似度极强
    • 现代 RAG/检索的标配文档向量方法
  • E5/BGE/GTR 等通用 Embedding 模型 海量数据 + 对比学习 + 指令微调 更强、更快、支持更长文本,成为当前工业级 Embedding 主流

传统方法

分词

中文用 jieba。

词频

不仅仅像 onehot 一样只记录关键词是否出现。
词频可以写成向量的性质,每个词是一个维度。

TF-IDF

相比而言 one-hot 只考虑是否出现。
TF-IDF

高频词能够发现文档的主题分类,同时按词频对关键词进行排序。

在词频的基础上扩展,需要去掉一些停用词,这些词不能反映主题。

TF-IDF(词频-逆文档频率)核心思想是衡量一个词在当前文档重要,但在整个语料库不常见。

它还有一整套 NLP 基础任务都靠它。

  1. 关键词提取:计算每个词的 TF-IDF 分数,分数越高 = 越能代表这篇文档,直接取 Top-N 词作为关键词。
  2. 文本表示:把文章变成向量 把一篇文档变成TF-IDF 向量: - 维度 = 所有词的数量 - 每个位置 = 对应词的 TF-IDF 值 作用: - 让计算机能计算、能比较文本 - 是很多算法的输入基础
  3. 文本相似度/文档匹配 有了 TF-IDF 向量,就能: - 用余弦相似度算两篇文章像不像 - 做: - 相似文章推荐 - 查重、抄袭检测 - 问答系统:找最相似问题
  4. 信息检索(搜索引擎核心) 搜索引擎本质: - 用户输入查询 → 转成 TF-IDF 向量 - 所有网页也用 TF-IDF 表示 - 计算查询和网页相似度 → 排序返回结果 TF-IDF 是早期搜索引擎排序核心。
  5. 文本分类 TF-IDF 向量可以直接喂给分类模型: - 朴素贝叶斯 - SVM - 逻辑回归 任务: - 新闻分类(体育/娱乐/科技) - 垃圾邮件识别 - 情感分类(简单场景)
  6. 聚类:自动给文章分组 对大量文档做 TF-IDF 后,用 K-Means 等聚类: - 自动把主题相似的文章聚成一类 - 不用人工打标签
  7. 去停用词、过滤无意义词 TF-IDF 天然会压低: - 我、你、的、了、是、在…… 这些高频但无信息量的词。 可以用来自动过滤停用词。
  8. 特征选择(降维) 在文本任务里,词太多会维度爆炸。 用 TF-IDF 分数: - 保留高分重要词 - 去掉低分无用词 减少特征数量,提升模型速度与效果。

一句话总结 TF-IDF 的作用,主要做两件事:
1. 量化一个词对一篇文档的重要程度
2. 把文本变成可计算的向量,支撑: - 关键词提取 - 搜索/检索 - 相似度、推荐、查重 - 分类、聚类、特征选择

例子 + 公式,一步步带你手算一篇文章的 TF-IDF 向量和关键词。

公式
例子
代码可以用 sklearn。

最常用改进是bm25,搜索时比向量更能匹配关键词。

手工特征

参考 SQuAD 论文中的特征。

  • 一、Lexicalized Features 词汇化特征 Exact word match 上下文词是否精确匹配问题中的词 Lowercase match 忽略大小写匹配 Lemma match 词元 / 词干匹配(词形还原后匹配) Bigram overlap 二元词组重合 Trigram overlap 三元词组重合 Question term frequency 该词在问题中出现频次 Term Frequency (TF) 单词在原文段落内词频 Inverse Document Frequency (IDF) 全局逆文档频率
  • 二、Syntactic / Dependency Path Features 句法依存特征 Dependency relation type 问题词与上下文词之间的依存关系标签 Dependency path length 两词之间依存路径长度 POS tag agreement 词性标签一致性特征 Syntactic constituent overlap 句法短语组块重合特征
  • 三、Miscellaneous 辅助手工特征 Answer span length 候选答案跨度长度 Relative positional offset 候选片段在段落中的相对位置 Sentence boundary feature 是否位于句子开头 / 结尾 Distance to question keywords 距离问题核心疑问词的文本距离

代码示例

文档向量方法对比(可直接运行)
1. BoW 词袋
2. TF-IDF
3. Doc2Vec
4. Sentence-BERT(现代主流)

 
# !pip install scikit-learn gensim sentence-transformers numpy
python
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from gensim.models import Doc2Vec
from gensim.models.doc2vec import TaggedDocument
from sentence_transformers import SentenceTransformer
 
# 示例文档(你可以换成自己的)
 
docs = [
"我喜欢人工智能。",
"人工智能未来发展很快。",
"我喜欢吃苹果。",
"苹果是一种健康水果。"
]
 
# 1. BoW 词袋向量
 
print("=" * 50)
print("1. BoW 词袋向量")
vectorizer_bow = CountVectorizer()
bow_matrix = vectorizer_bow.fit_transform(docs)
print("词表:", vectorizer_bow.get_feature_names_out())
print("BoW 向量:\n", bow_matrix.toarray())
 
# 2. TF-IDF 向量
 
print("\n" + "=" * 50)
print("2. TF-IDF 向量")
vectorizer_tfidf = TfidfVectorizer()
tfidf_matrix = vectorizer_tfidf.fit_transform(docs)
print("TF-IDF 向量:\n", np.round(tfidf_matrix.toarray(), 3))
 
# 1. Doc2Vec 文档向量
 
print("\n" + "=" * 50)
print("3. Doc2Vec 文档向量")
# 构建训练数据
tagged_docs = [ TaggedDocument(words=list(doc), tags=[str(i)]) for i, doc in enumerate(docs) ]
# 训练
model_d2v = Doc2Vec( tagged_docs, vector_size=16, 小维度方便演示 window=2, min_count=1, epochs=50 )
# 得到文档向量
doc_vectors = [model_d2v.dv[str(i)] for i in range(len(docs))]
for i, vec in enumerate(doc_vectors):
print(f"文档 {i} 向量前8维:", np.round(vec[:8], 3))
 
#  2. Sentence-BERT 向量(现代最强)
 
print("\n" + "=" * 50)
print("4. Sentence-BERT 文档向量")
model_sbert = SentenceTransformer("all-MiniLM-L6-v2")
sbert_vectors = model_sbert.encode(docs, normalize_embeddings=True)
for i, vec in enumerate(sbert_vectors):
print(f"文档 {i} 向量前8维:", np.round(vec[:8], 3))

你运行后会直观看到:

  • BoW:只看有没有词,0/1 计数
  • TF-IDF:给重要词加权
  • Doc2Vec:稠密小向量
  • SBERT:真正语义级向量
    下一步可以:
    1. 计算相似度(看看哪两个文档最像)
    2. 换成你自己的 txt/md 文档
    3. 画向量聚类图
    4. 做一个最简单的 RAG 检索

任务

现在 LLM 时代有一些新的变化

任务

  • 语义检索(RAG)
  • 句子相似度:计算距离或者余弦
  • 文本聚类
  • 文本分类(用向量+LR)
  • 问答匹配

文本相似度(余弦相似度)

from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
model = SentenceTransformer('all-MiniLM-L6-v2')
# 生成句子向量
vec1 = model.encode("我喜欢人工智能")
vec2 = model.encode("我热爱深度学习")
# 然后计算相似度:
sim = cosine_similarity([vec1], [vec2])[0][0]

评测

评测方法(从简单到专业)

  • 方法 1:直观相似度测试(最简单,零成本) 构造几组文档: - 相似对:A & A’ - 不相似对:A & B 看余弦相似度是否符合预期。 好向量: - 相似对 → 高分(0.7~1.0) - 不相似对 → 低分(0.0~0.3)
  • 方法 2:文本检索排序(最实用、最像真实业务) 1. 准备一堆文档 2. 写一个查询 3. 用每种向量方法召回Top-K 4. 看相关文档有没有排在前面 谁排得更准,谁就更强。
  • 方法 3:聚类效果(无监督评测) 把向量丢进 KMeans 聚类: - 人工智能 → 聚成一类 - 水果 → 聚成一类 看聚类准确率 / NMI / ARI。 聚类越干净,向量越好。
  • 方法 4:下游任务(最权威) 用向量做: - 文本分类 - 信息检索 - 相似匹配 谁准确率高、recall 高,谁就强。

评测代码

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
 
评测数据自己构造即可
 
docs = [
	"我喜欢人工智能", 0
	"人工智能发展很快", 1
	"我爱吃苹果", 2
	"苹果是健康水果", 3
]
# 相似对(应该高分)
similar_pairs = [(0,1), (2,3)]
# 不相似对(应该低分)
dissimilar_pairs = [(0,2), (0,3), (1,2), (1,3)]
 
# 通用评测函数(给向量就打分)
 
def evaluate(vectors, name):
	sim_scores = []
for i,j in similar_pairs:
	sim = cosine_similarity([vectors[i]], [vectors[j]])[0][0]
	sim_scores.append(sim)
	dis_scores = []
for i,j in dissimilar_pairs:
	sim = cosine_similarity([vectors[i]], [vectors[j]])[0][0]
	dis_scores.append(sim)
	sim_mean = np.mean(sim_scores)
	dis_mean = np.mean(dis_scores)
print(f"===== {name} 评测结果 =====")
print(f"相似对平均相似度: {sim_mean:.3f}")
print(f"不相似对平均相似度: {dis_mean:.3f}")
print(f"区分度(越大越好): {sim_mean - dis_mean:.3f}\n")
#然后你把 4 种向量 分别丢进去:
 
evaluate(bow_vectors, "BoW")
evaluate(tfidf_vectors, "TF-IDF")
evaluate(doc2vec_vectors, "Doc2Vec")
evaluate(sbert_vectors, "Sentence-BERT")

结果

  • 区分度从高到低:Sentence-BERT » Doc2Vec > TF-IDF > BoW
  • 真实结论(行业公认) SBERT > Doc2Vec > TF-IDF > BoW

数据集

相关工具

  • NLTK
  • Spacy
  • FastText 提供命令行

相关论文

论文

  • Efficient Estimation of Word Representations in Vector Space
  • Distributed Representations of Words and Phrases and their Compositionality
  • Bag of Tricks for Efficient Text Classification
  • GloVe: Global Vectors for Word Representation
  • Bert
  • Doc2Vec
  • Sentence-BERT

综述

教材

  • NLP
  • 中文 NLP
  • 文本上的算法