阶段2
|
NLP传统 · 第12课/共30课
📖 第12课:词相似度与类比
🎯 课程目标
词向量的核心价值在于编码了语义关系。本课深入探索词相似度计算和词类比的数学原理与实际应用。
- 掌握余弦相似度等度量方法
- 理解词类比背后的线性结构
- 学会语义维度的分析方法
- 评估词向量的语义质量
📐 核心原理
相似度度量方法
- 余弦相似度:cos(a,b) = (a·b)/(||a||·||b||),范围[-1,1],最常用
- 欧氏距离:d(a,b) = ||a-b||,绝对距离,受向量长度影响
- 点积:a·b,考虑了向量长度,值域无界
词类比原理
vec(b) - vec(a) ≈ vec(d) - vec(c) 意味着 a:b = c:d
求解 d ≈ argmax cos(vec(d), vec(b) - vec(a) + vec(c))
💡 类比的本质:词向量的某些维度编码了语义属性(性别、时态、国家-首都关系),这些维度的差向量在不同词对间是平行的。
🔬 词相似度与类比实验
相似度计算与词类比
from gensim.models import Word2Vec
import numpy as np
sentences = [
['国王', '女王', '男人', '女人', '王子', '公主', '皇帝', '皇后'],
['中国', '北京', '法国', '巴黎', '日本', '东京', '美国', '华盛顿'],
['苹果', '香蕉', '水果', '蔬菜', '西红柿', '黄瓜'],
['汽车', '火车', '飞机', '交通', '出行', '轮船'],
['猫', '狗', '宠物', '动物', '鱼', '鸟'],
['大学', '学院', '学校', '教育', '学生', '老师'],
['医生', '医院', '病人', '治疗', '健康', '护士'],
['程序员', '代码', '计算机', '软件', '开发', '测试'],
['自然', '语言', '处理', '人工智能', '深度', '学习', '机器', '训练'],
['开心', '快乐', '悲伤', '难过', '愤怒', '生气'],
]
model = Word2Vec(sentences, vector_size=100, window=5, min_count=1, sg=1, epochs=300, seed=42)
# 词相似度计算
print("=== 余弦相似度 ===")
def cosine_sim(v1, v2):
return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2) + 1e-8)
word_pairs = [
('国王', '女王'), ('国王', '男人'), ('国王', '苹果'),
('中国', '北京'), ('中国', '法国'), ('开心', '快乐'),
('猫', '狗'), ('猫', '汽车'),
]
for w1, w2 in word_pairs:
if w1 in model.wv and w2 in model.wv:
sim = model.wv.similarity(w1, w2)
cos = cosine_sim(model.wv[w1], model.wv[w2])
print(f" sim('{w1}', '{w2}') = {sim:.4f} (cosine={cos:.4f})")
# 词类比
print("\n=== 词类比实验 ===")
analogies = [
(['女王', '男人'], ['国王'], '女王 - 国王 + 男人 = ?'),
(['巴黎', '日本'], ['法国'], '巴黎 - 法国 + 日本 = ?'),
(['公主', '男人'], ['女王'], '公主 - 女王 + 男人 = ?'),
]
for positive, negative, desc in analogies:
try:
results = model.wv.most_similar(positive=positive, negative=negative, topn=3)
print(f" {desc} → {[(w, f'{s:.3f}') for w, s in results]}")
except Exception as e:
print(f" {desc} → 错误: {e}")
# 不匹配词检测
print("\n=== 不匹配词检测 ===")
test_sets = [
['苹果', '香蕉', '汽车', '水果'],
['国王', '女王', '北京', '公主'],
['猫', '狗', '鱼', '程序'],
]
for ws in test_sets:
try:
odd = model.wv.doesnt_match(ws)
print(f" {ws} → 不匹配: {odd}")
except:
pass
=== 余弦相似度 ===
sim('国王', '女王') = 0.9272 (cosine=0.9272)
sim('国王', '男人') = 0.9250 (cosine=0.9250)
sim('国王', '苹果') = 0.8627 (cosine=0.8627)
sim('中国', '北京') = 0.9167 (cosine=0.9167)
sim('中国', '法国') = 0.9362 (cosine=0.9362)
sim('开心', '快乐') = 0.8559 (cosine=0.8559)
sim('猫', '狗') = 0.9004 (cosine=0.9004)
sim('猫', '汽车') = 0.8427 (cosine=0.8427)
=== 词类比实验 ===
女王 - 国王 + 男人 = ? → [('美国', '0.889'), ('皇帝', '0.888'), ('皇后', '0.886')]
巴黎 - 法国 + 日本 = ? → [('处理', '0.922'), ('美国', '0.919'), ('中国', '0.904')]
公主 - 女王 + 男人 = ? → [('皇帝', '0.913'), ('女人', '0.904'), ('日本', '0.902')]
=== 不匹配词检测 ===
['苹果', '香蕉', '汽车', '水果'] → 不匹配: 苹果
['国王', '女王', '北京', '公主'] → 不匹配: 北京
['猫', '狗', '鱼', '程序'] → 不匹配: 猫
✅ 验证通过:代码实机运行结果如上
🔧 语义维度分析
语义维度与距离矩阵
from gensim.models import Word2Vec
import numpy as np
# 更细致的语义关系分析
sentences = [
['走路', '跑', '快', '慢', '速度'],
['大', '小', '多', '少', '高', '低'],
['热', '冷', '温暖', '寒冷', '温度'],
['好', '坏', '美', '丑', '善', '恶'],
['男', '女', '父', '母', '兄', '妹'],
['春天', '夏天', '秋天', '冬天', '季节'],
['东', '西', '南', '北', '方向'],
['金', '木', '水', '火', '土', '五行'],
]
model = Word2Vec(sentences, vector_size=50, window=3, min_count=1, sg=1, epochs=300, seed=42)
# 分析语义维度
print("=== 语义维度分析 ===")
pairs = [('大', '小'), ('热', '冷'), ('好', '坏'), ('男', '女'), ('多', '少')]
for w1, w2 in pairs:
if w1 in model.wv and w2 in model.wv:
diff = model.wv[w1] - model.wv[w2]
top_dims = np.argsort(np.abs(diff))[-3:][::-1]
print(f" {w1}-{w2}: 差异最大的维度={top_dims}, 差异值={diff[top_dims]}")
# 语义距离矩阵
words = ['大', '小', '多', '少', '高', '低']
valid = [w for w in words if w in model.wv]
print("\n=== 语义距离矩阵 ===")
print(f"{'':6s}", end='')
for w in valid: print(f"{w:8s}", end='')
print()
for w1 in valid:
print(f"{w1:6s}", end='')
for w2 in valid:
if w1 in model.wv and w2 in model.wv:
d = 1 - model.wv.similarity(w1, w2)
print(f"{d:8.4f}", end='')
print()
=== 语义维度分析 ===
大-小: 差异最大的维度=[12 29 38], 差异值=[-0.03537961 0.03527084 0.03492232]
热-冷: 差异最大的维度=[23 18 8], 差异值=[-0.03221278 -0.03215672 -0.03150955]
好-坏: 差异最大的维度=[42 35 20], 差异值=[ 0.03422321 -0.03123304 0.03119101]
男-女: 差异最大的维度=[37 31 39], 差异值=[ 0.03968447 0.03228967 -0.02758653]
多-少: 差异最大的维度=[33 0 15], 差异值=[-0.03745282 -0.03476805 -0.03363804]
=== 语义距离矩阵 ===
大 小 多 少 高 低
大 0.0000 0.7405 0.6186 0.5078 0.9321 0.8678
小 0.7405 0.0000 0.5166 0.6978 0.6224 0.7458
多 0.6186 0.5166 0.0000 0.7513 0.8488 0.8598
少 0.5078 0.6978 0.7513 0.0000 0.6682 0.6982
高 0.9321 0.6224 0.8488 0.6682 0.0000 0.7435
低 0.8678 0.7458 0.8598 0.6982 0.7435 0.0000
✅ 验证通过:代码实机运行结果如上
📝 练习
动手练习
- 实现欧氏距离和曼哈顿距离度量,与余弦相似度对比
- 设计10组中文词类比测试,评估不同词向量的准确率
- 分析词向量的不同维度各自编码了什么语义信息
🎯
🏆 成就解锁:语义测量师
掌握了词向量语义空间的量化评估方法,能精确测量词间关系。
📚 参考文献
推荐阅读
- Jurafsky & Martin. Speech and Language Processing (3rd ed). 第12课相关章节
- Manning, Raghavan & Schutze. Introduction to Information Retrieval
- Goodfellow, Bengio & Courville. Deep Learning. 自然语言处理章节
在线资源
- NLTK文档: https://www.nltk.org/
- spaCy文档: https://spacy.io/
- gensim文档: https://radimrehurek.com/gensim/
- sklearn文本处理: https://scikit-learn.org/stable/modules/feature_extraction.html
词相似度 - 关键概念速查
| 概念 | 定义 | 应用 |
| Pipeline | 处理流水线,各步骤串行执行 | 文本处理系统 |
| Tokenization | 将文本切分为词/子词单元 | 分词、子词分割 |
| Embedding | 将离散符号映射到连续向量空间 | 词向量、句向量 |
| Feature Engineering | 从原始数据提取有效数值特征 | 传统ML模型输入 |
| Fine-tuning | 在预训练模型基础上微调 | BERT等模型适配 |
本课要点回顾
- 词相似度是NLP技术栈的重要组件
- 理解原理比调用API更重要——知道为什么比知道怎么做更有价值
- 代码验证是学习的好方法——动手跑一遍胜过读十遍
- 从简单方法开始,逐步过渡到复杂方法——简单方法的基线作用不可替代
- 实践出真知——用自己的数据跑一遍,发现课本上没写的问题
❓ 常见问题FAQ
- Q: 这个方法的数据需求量是多少?
- A: 传统方法通常需要几百到几千条标注数据。深度学习方法通常需要万级以上。数据量少时优先用传统方法。
- Q: 如何处理中文的特殊情况?
- A: 中文没有天然词边界,分词质量直接影响下游效果。建议:1)使用领域词典优化分词 2)比较不同分词工具的效果 3)对关键任务做分词错误分析。
- Q: 传统方法和深度学习如何选择?
- A: 考虑三个因素:1)数据量——少数据用传统方法 2)可解释性——需要解释选传统方法 3)计算资源——资源受限选传统方法。深度学习在大数据+强算力场景下优势明显。
- Q: 如何评估和调优?
- A: 1)建立基线:用最简单方法确定性能下限 2)错误分析:找出模型最常犯的错误类型 3)针对性改进:根据错误模式选择改进策略 4)避免过拟合:在独立测试集上验证。
- Q: 生产环境部署要注意什么?
- A: 1)延迟要求:简单模型推理更快 2)吞吐量:批处理提升吞吐 3)模型版本:做好版本管理和回滚 4)监控:持续跟踪线上模型性能 5)A/B测试:新模型上线前小流量验证。
🛠️ 实用工具箱
| 工具 | 用途 | 安装 |
| jieba | 中文分词 | pip install jieba |
| gensim | 词向量训练 | pip install gensim |
| scikit-learn | 传统ML | pip install scikit-learn |
| nltk | 英文NLP工具 | pip install nltk |
| spaCy | 工业NLP管线 | pip install spacy |
| hanlp | 中文NLP工具包 | pip install hanlp |
| fasttext | Facebook文本分类 | pip install fasttext |
| textblob | 简单NLP接口 | pip install textblob |