一、为什么要向量化
计算机只认得数字。文本向量化(Text Vectorization)就是把字、词、句子映射成实数向量,使文本能够参与加减、距离、概率等数学运算。它是从「符号处理」迈向「统计计算」的关键一跃。
本章的技术谱系,也是表示能力不断升级的过程:
One-Hot(离散、稀疏、无语义)
└─ 词袋模型 BoW(计数、稀疏、仍无语义)
└─ TF-IDF(加权、稀疏、部分语义)
└─ 分布式词向量 Word2Vec(稠密、含语义)
└─ 上下文表示 ELMo / BERT(动态、多义词)
二、One-Hot 编码
最朴素的想法:为词表中的每个词分配一个编号,用「只有该位置为 1、其余为 0」的长向量表示它。
词表 V = [分词, 向量化, 情感, 问答]
分词 = [1, 0, 0, 0]
向量化 = [0, 1, 0, 0]
情感 = [0, 0, 1, 0]
问答 = [0, 0, 0, 1]
优点是简单直观;缺点同样致命:
- 维度灾难:词表十万,每个向量就是十万维且几乎全 0;
- 语义鸿沟:任意两个词的向量都正交,余弦相似度恒为 0——「汽车」与「轿车」在模型看来毫无关系;
- 词序丢失:句子被压缩成等长向量,「狗咬人」与「人咬狗」向量相同。
三、词袋与 TF-IDF 向量
词袋模型(Bag of Words, BoW)把整句/整篇文档表示为「词表上的计数向量」:
词表 [分词, 向量化, 情感, 问答]
句 A「问答机器人离不开分词」→ [1, 0, 0, 1]
句 B「情感分析需要向量化」 → [0, 1, 1, 0]
BoW 已经可以衡量文档间的重叠程度,再加权升级就是第四章学过的 TF-IDF 向量:用 TF-IDF 值替换原始计数,常见词权重更低。
两个常用的小改进:
- N-gram:把相邻两个词也当作特征(「不/喜欢」→「不喜欢」),部分挽回词序与否定信息;
- 子词 / 字符 n-gram:缓解未登录词问题,英文还能捕捉词形(
-ing、-ed)。
词袋家族在传统文本分类(垃圾邮件、情感分类)中至今仍是又快又稳的基线。
四、分布式表示与 Word2Vec
语言学家有一句名言:「You shall know a word by the company it keeps」——一个词的意思,由它周围常出现的词决定。这就是分布式假设(Distributional Hypothesis)。
2013 年谷歌开源的 Word2Vec 用浅层神经网络从大规模语料中学习每个词的稠密低维向量(通常 100–300 维),语义相近的词在空间中彼此邻近,并出现著名的向量运算:
vec("国王") − vec("男人") + vec("女人") ≈ vec("女王")
vec("北京") − vec("中国") + vec("法国") ≈ vec("巴黎")
它有两种对称的训练结构:
| 模型 | 输入 → 预测 | 特点 |
|---|---|---|
| CBOW | 上下文词 → 中心词 | 训练快,适合高频词 |
| Skip-gram | 中心词 → 上下文词 | 对低频词更友好,常用 |
此后还有 GloVe(结合全局共现矩阵)、FastText(把词拆成字符 n-gram,解决未登录词)。而 BERT 类模型进一步实现动态上下文表示:「苹果」在「吃苹果」与「买苹果手机」中向量不同,从根本上处理多义词。
python · gensim 训练词向量from gensim.models import Word2Vec
sentences = [
["自然语言处理", "需要", "分词", "向量化"],
["情感分析", "基于", "向量化", "分类器"],
# …… 实际需要海量分好词的句子
]
model = Word2Vec(sentences, vector_size=100, window=5,
min_count=1, sg=1) # sg=1 即 Skip-gram
vec = model.wv["分词"] # 100 维向量
print(model.wv.most_similar("分词", topn=5)) # 最相近的 5 个词
五、余弦相似度
有了向量,如何衡量两段文本像不像?最常用的是余弦相似度——计算两个向量夹角的余弦,只看方向、不受长度影响:
cos(A, B) = (A · B) / ( ‖A‖ × ‖B‖ )
取值范围 [−1, 1]:越接近 1 越相似,0 表示正交无关
从推荐系统的「相似文章」、检索式问答的「匹配问题」,到 RAG 的语义召回,背后都有余弦相似度(或其等价的归一化向量点积)的身影。第七章的演示将直接用它计算两句话的语义近似程度。
六、Python 实战与交互演示
python · sklearn 构建词袋 / TF-IDF 向量from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
sents = ["问答机器人 需要 分词",
"情感分析 需要 文本向量化"]
bow = CountVectorizer()
X = bow.fit_transform(sents)
print(bow.get_feature_names_out())
print(X.toarray())
tfidf = TfidfVectorizer()
Y = tfidf.fit_transform(sents)
print(Y.toarray().round(3))
动手一试:句子变向量
输入两个句子,演示会自动完成分词 → 构建词表 → 生成 One-Hot 与词袋向量的全过程(已自动过滤虚词):
可以看到,两个句子共享的「需要、向量化」在两个 BoW 向量中对应位置同时非零——这正是下一章句法之前、本章向量表示所能捕捉的最朴素的「语义重叠」。