Appearance
词的相似性和类比任务
一、概述
这个章节是在我们之前学的词嵌入(比如 GloVe、word2vec)的基础上,来展示预训练好的词向量能捕捉到的语义信息,主要有两个实用的任务:
任务:
- 一是找和输入词语义相似的词, 比如 "chip" 会找到和它意思相近的词 "chips"
- 二是完成词的类比任务, 比如 "man" 是 "woman" 的类比,"son" 是 "daughter" 的类比。
我们会用预训练好的 GloVe 词向量来演示这两个任务。
二、词相似度:找和输入词意思相近的词
1. 原理
我们用余弦相似度来衡量两个词向量的相似性,这个值的范围是 - 1 到 1,越接近 1,说明两个词向量的方向越一致,对应的词语义就越相似。简单来说,就是两个词的 "语义方向" 越像,它们的余弦相似度就越高。
2. 代码实现
我们先实现一个 k 近邻(knn)函数,用来找到和输入词向量最相似的 k 个词向量,然后再封装成一个方便调用的函数:
python
import torch
from d2l import torch as d2l
def knn(W, x, k):
# 增加1e-9是为了避免除以0的情况,保证计算稳定
# 计算每个词向量和输入向量的余弦相似度
cos = torch.mv(W, x.reshape(-1,)) / (
torch.sqrt(torch.sum(W * W, axis=1) + 1e-9) *
torch.sqrt((x * x).sum())
)
# 找到相似度最高的k个词的索引
_, topk = torch.topk(cos, k=k)
# 返回索引和对应的相似度
return topk, [cos[int(i)] for i in topk]
def get_similar_tokens(query_token, k, embed):
# 找到和输入词最相似的k个词,排除输入词本身
topk, cos = knn(embed.idx_to_vec, embed[[query_token]], k + 1)
for i, c in zip(topk[1:], cos[1:]):
print(f'{embed.idx_to_token[int(i)]}:cosine相似度={float(c):.3f}')3. 示例演示
我们用预训练好的 GloVe 词向量来测试,比如输入 "chip",会找到和它意思相近的词:
python
# 加载预训练的GloVe词向量
glove_6b50d = d2l.TokenEmbedding('glove.6b.50d')
# 找和chip最相似的3个词
get_similar_tokens('chip', 3, glove_6b50d)运行结果是:
chips:cosine 相似度 = 0.856 intel:cosine 相似度 = 0.749 electronics:cosine 相似度 = 0.749 这些词都和芯片、电子相关,说明模型学到了 "chip" 的语义。
再比如输入 "baby",会找到: babies:cosine 相似度 = 0.839 boy:cosine 相似度 = 0.800 girl:cosine 相似度 = 0.792 这些词都和婴儿、小孩相关。
输入 "beautiful" 的话,会找到: lovely:cosine 相似度 = 0.921 gorgeous:cosine 相似度 = 0.893 wonderful:cosine 相似度 = 0.830 这些都是形容美好的词,和 "beautiful" 语义相近。
三、词类比:完成 "a:b 就像 c:d" 的填空
1. 原理
词类比任务就是我们常说的 "a 之于 b,就像 c 之于 d",比如 "男人之于女人,就像儿子之于女儿"。
具体的计算方法是:先算出 b 相对于 a 的向量变化(vec (b)-vec (a)),然后把这个变化应用到 c 上,得到 vec (d)=vec (b)-vec (a)+vec (c),最后找到和这个向量最相似的词向量,对应的词就是 d。
2. 代码实现
我们实现一个函数来完成这个任务:
python
def get_analogy(token_a, token_b, token_c, embed):
# 获取a、b、c的词向量
vecs = embed[[token_a, token_b, token_c]]
# 计算目标向量
x = vecs[1] - vecs[0] + vecs[2]
# 找到最相似的词
topk, _ = knn(embed.idx_to_vec, x, 1)
return embed.idx_to_token[int(topk[0])]3. 示例演示
(1)性别类比
比如 "man:woman :: son:daughter",我们用函数测试:
python
get_analogy('man', 'woman', 'son', glove_6b50d)结果是 "daughter",完全符合我们的预期,说明词向量捕捉到了性别相关的语义。
(2)首都 - 国家类比
比如 "beijing:china :: tokyo:japan",测试:
python
get_analogy('beijing', 'china', 'tokyo', glove_6b50d)结果是 "japan",正确对应了首都和国家的关系。
(3)句法类比
词向量还能捕捉到句法信息,比如形容词最高级的类比 "bad:worst :: big:biggest",还有过去式的类比 "do:did :: go:went",都能正确完成。
四、小结
预训练好的词向量可以用来完成词相似度和词类比任务,能很好地捕捉词的语义和句法信息。
词相似度用余弦相似度来衡量,找最相似的 k 个词;词类比通过计算向量的变化来找到对应的词。
这些预训练的词向量可以用到下游的自然语言处理任务里,帮助模型更好地理解语言的语义和句法。
(注:文档部分内容可能由 AI 生成) 源地址