词嵌入进阶

“Word2Vec的实现”一节中,我们在小规模数据集上训练了一个 Word2Vec 词嵌入模型,并通过词向量的余弦相似度搜索近义词。虽然 Word2Vec 已经能够成功地将离散的单词转换为连续的词向量,并能一定程度上地保存词与词之间的近似关系,但 Word2Vec 模型仍不是完美的,它还可以被进一步地改进:

  1. 子词嵌入(subword embedding):FastText 以固定大小的 n-gram 形式将单词更细致地表示为了子词的集合,而 BPE (byte pair encoding) 算法则能根据语料库的统计信息,自动且动态地生成高频子词的集合;
  2. GloVe 全局向量的词嵌入: 通过等价转换 Word2Vec 模型的条件概率公式,我们可以得到一个全局的损失函数表达,并在此基础上进一步优化模型。

实际中,我们常常在大规模的语料上训练这些词嵌入模型,并将预训练得到的词向量应用到下游的自然语言处理任务中。本节就将以 GloVe 模型为例,演示如何用预训练好的词向量来求近义词和类比词。

GloVe 全局向量的词嵌入

GloVe 模型

先简单回顾以下 Word2Vec 的损失函数(以 Skip-Gram 模型为例,不考虑负采样近似):

−∑t=1T∑−m≤j≤m,j≠0log⁡P(w(t+j)∣w(t))
-\sum_{t=1}^T\sum_{-m\le j\le m,j\ne 0} \log P(w^{(t+j)}\mid w^{(t)})
−t=1∑T​−m≤j≤m,j​=0∑​logP(w(t+j)∣w(t))

其中

P(wj∣wi)=exp⁡(uj⊤vi)∑k∈Vexp⁡(uk⊤vi)
P(w_j\mid w_i) = \frac{\exp(\boldsymbol{u}_j^\top\boldsymbol{v}_i)}{\sum_{k\in\mathcal{V}}\exp(\boldsymbol{u}_k^\top\boldsymbol{v}_i)}
P(wj​∣wi​)=∑k∈V​exp(uk⊤​vi​)exp(uj⊤​vi​)​

是 wiw_iwi​ 为中心词,wjw_jwj​ 为背景词时 Skip-Gram 模型所假设的条件概率计算公式,我们将其简写为 qijq_{ij}qij​。

注意到此时我们的损失函数中包含两个求和符号,它们分别枚举了语料库中的每个中心词和其对应的每个背景词。实际上我们还可以采用另一种计数方式,那就是直接枚举每个词分别作为中心词和背景词的情况:

−∑i∈V∑j∈Vxijlog⁡qij
-\sum_{i\in\mathcal{V}}\sum_{j\in\mathcal{V}} x_{ij}\log q_{ij}
−i∈V∑​j∈V∑​xij​logqij​

其中 xijx_{ij}xij​ 表示整个数据集中 wjw_jwj​ 作为 wiw_iwi​ 的背景词的次数总和。

我们还可以将该式进一步地改写为交叉熵 (cross-entropy) 的形式如下:

−∑i∈Vxi∑j∈Vpijlog⁡qij
-\sum_{i\in\mathcal{V}}x_i\sum_{j\in\mathcal{V}}p_{ij} \log q_{ij}
−i∈V∑​xi​j∈V∑​pij​logqij​

其中 xix_ixi​ 是 wiw_iwi​ 的背景词窗大小总和,pij=xij/xip_{ij}=x_{ij}/x_ipij​=xij​/xi​ 是 wjw_jwj​ 在 wiw_iwi​ 的背景词窗中所占的比例。

从这里可以看出,我们的词嵌入方法实际上就是想让模型学出 wjw_jwj​ 有多大概率是 wiw_iwi​ 的背景词,而真实的标签则是语料库上的统计数据。同时,语料库中的每个词根据 xix_ixi​ 的不同,在损失函数中所占的比重也不同。

注意到目前为止,我们只是改写了 Skip-Gram 模型损失函数的表面形式,还没有对模型做任何实质上的改动。而在 Word2Vec 之后提出的 GloVe 模型,则是在之前的基础上做出了以下几点改动:

  1. 使用非概率分布的变量 pij′=xijp'_{ij}=x_{ij}pij′​=xij​ 和 q′ij=exp⁡(uj⊤vi)q′_{ij}=\exp(\boldsymbol{u}^\top_j\boldsymbol{v}_i)q′ij​=exp(uj⊤​vi​),并对它们取对数;
  2. 为每个词 wiw_iwi​ 增加两个标量模型参数:中心词偏差项 bib_ibi​ 和背景词偏差项 cic_ici​,松弛了概率定义中的规范性;
  3. 将每个损失项的权重 xix_ixi​ 替换成函数 h(xij)h(x_{ij})h(xij​),权重函数 h(x)h(x)h(x) 是值域在 [0,1][0,1][0,1] 上的单调递增函数,松弛了中心词重要性与 xix_ixi​ 线性相关的隐含假设;
  4. 用平方损失函数替代了交叉熵损失函数。

综上,我们获得了 GloVe 模型的损失函数表达式:

∑i∈V∑j∈Vh(xij)(uj⊤vi+bi+cj−log⁡xij)2
\sum_{i\in\mathcal{V}}\sum_{j\in\mathcal{V}} h(x_{ij}) (\boldsymbol{u}^\top_j\boldsymbol{v}_i+b_i+c_j-\log x_{ij})^2
i∈V∑​j∈V∑​h(xij​)(uj⊤​vi​+bi​+cj​−logxij​)2

由于这些非零 xijx_{ij}xij​ 是预先基于整个数据集计算得到的,包含了数据集的全局统计信息,因此 GloVe 模型的命名取“全局向量”(Global Vectors)之意。

载入预训练的 GloVe 向量

GloVe 官方 提供了多种规格的预训练词向量,语料库分别采用了维基百科、CommonCrawl和推特等,语料库中词语总数也涵盖了从60亿到8,400亿的不同规模,同时还提供了多种词向量维度供下游模型使用。

torchtext.vocab 中已经支持了 GloVe, FastText, CharNGram 等常用的预训练词向量,我们可以通过声明 torchtext.vocab.GloVe 类的实例来加载预训练好的 GloVe 词向量。

  1. import torch
  2. import torchtext.vocab as vocab
  3. print([key for key in vocab.pretrained_aliases.keys() if "glove" in key])
  4. cache_dir = "/home/kesci/input/GloVe6B5429"
  5. glove = vocab.GloVe(name='6B', dim=50, cache=cache_dir)
  6. print("一共包含%d个词。" % len(glove.stoi))
  7. print(glove.stoi['beautiful'], glove.itos[3366])
  1. ['glove.42B.300d', 'glove.840B.300d', 'glove.twitter.27B.25d', 'glove.twitter.27B.50d', 'glove.twitter.27B.100d', 'glove.twitter.27B.200d', 'glove.6B.50d', 'glove.6B.100d', 'glove.6B.200d', 'glove.6B.300d']
  2. 一共包含400000个词。
  3. 3366 beautiful

求近义词和类比词

求近义词

由于词向量空间中的余弦相似性可以衡量词语含义的相似性(为什么?),我们可以通过寻找空间中的 k 近邻,来查询单词的近义词。

  1. def knn(W, x, k):
  2. '''
  3. @params:
  4. W: 所有向量的集合
  5. x: 给定向量
  6. k: 查询的数量
  7. @outputs:
  8. topk: 余弦相似性最大k个的下标
  9. [...]: 余弦相似度
  10. '''
  11. cos = torch.matmul(W, x.view((-1,))) / (
  12. (torch.sum(W * W, dim=1) + 1e-9).sqrt() * torch.sum(x * x).sqrt())
  13. _, topk = torch.topk(cos, k=k)
  14. topk = topk.cpu().numpy()
  15. return topk, [cos[i].item() for i in topk]
  16. def get_similar_tokens(query_token, k, embed):
  17. '''
  18. @params:
  19. query_token: 给定的单词
  20. k: 所需近义词的个数
  21. embed: 预训练词向量
  22. '''
  23. topk, cos = knn(embed.vectors,
  24. embed.vectors[embed.stoi[query_token]], k+1)
  25. for i, c in zip(topk[1:], cos[1:]): # 除去输入词
  26. print('cosine sim=%.3f: %s' % (c, (embed.itos[i])))
  27. get_similar_tokens('chip', 3, glove)
  1. cosine sim=0.856: chips
  2. cosine sim=0.749: intel
  3. cosine sim=0.749: electronics
  4. 100%|█████████▉| 398393/400000 [00:30<00:00, 38997.22it/s]
  1. get_similar_tokens('baby', 3, glove)
  1. cosine sim=0.839: babies
  2. cosine sim=0.800: boy
  3. cosine sim=0.792: girl
  1. get_similar_tokens('beautiful', 3, glove)
  1. cosine sim=0.921: lovely
  2. cosine sim=0.893: gorgeous
  3. cosine sim=0.830: wonderful

求类比词

除了求近义词以外,我们还可以使用预训练词向量求词与词之间的类比关系,例如“man”之于“woman”相当于“son”之于“daughter”。求类比词问题可以定义为:对于类比关系中的4个词“aaa 之于 bbb 相当于 ccc 之于 ddd”,给定前3个词 a,b,ca,b,ca,b,c 求 ddd。求类比词的思路是,搜索与 vec(c)+vec(b)−vec(a)\text{vec}(c)+\text{vec}(b)−\text{vec}(a)vec(c)+vec(b)−vec(a) 的结果向量最相似的词向量,其中 vec(w)\text{vec}(w)vec(w) 为 www 的词向量。

  1. def get_analogy(token_a, token_b, token_c, embed):
  2. '''
  3. @params:
  4. token_a: 词a
  5. token_b: 词b
  6. token_c: 词c
  7. embed: 预训练词向量
  8. @outputs:
  9. res: 类比词d
  10. '''
  11. vecs = [embed.vectors[embed.stoi[t]]
  12. for t in [token_a, token_b, token_c]]
  13. x = vecs[1] - vecs[0] + vecs[2]
  14. topk, cos = knn(embed.vectors, x, 1)
  15. res = embed.itos[topk[0]]
  16. return res
  17. get_analogy('man', 'woman', 'son', glove)
  1. 'daughter'
  1. get_analogy('beijing', 'china', 'tokyo', glove)
  1. 'japan'
  1. get_analogy('bad', 'worst', 'big', glove)
  1. 'biggest'
  1. get_analogy('do', 'did', 'go', glove)
  1. 'went'

L25词嵌入进阶GloVe模型的更多相关文章

  1. 词嵌入之GloVe

    什么是GloVe GloVe(Global Vectors for Word Representation)是一个基于全局词频统计(count-based & overall statisti ...

  2. DeepLearning.ai学习笔记(五)序列模型 -- week2 自然语言处理与词嵌入

    一.词汇表征 首先回顾一下之前介绍的单词表示方法,即one hot表示法. 如下图示,"Man"这个单词可以用 \(O_{5391}\) 表示,其中O表示One_hot.其他单词同 ...

  3. DLNg序列模型第二周NLP与词嵌入

    1.使用词嵌入 给了一个命名实体识别的例子,如果两句分别是“orange farmer”和“apple farmer”,由于两种都是比较常见的,那么可以判断主语为人名. 但是如果是榴莲种植员可能就无法 ...

  4. NLP学习(1)---Glove模型---词向量模型

    一.简介: 1.概念:glove是一种无监督的Word representation方法. Count-based模型,如GloVe,本质上是对共现矩阵进行降维.首先,构建一个词汇的共现矩阵,每一行是 ...

  5. Coursera Deep Learning笔记 序列模型(二)NLP & Word Embeddings(自然语言处理与词嵌入)

    参考 1. Word Representation 之前介绍用词汇表表示单词,使用one-hot 向量表示词,缺点:它使每个词孤立起来,使得算法对相关词的泛化能力不强. 从上图可以看出相似的单词分布距 ...

  6. cips2016+学习笔记︱简述常见的语言表示模型(词嵌入、句表示、篇章表示)

    在cips2016出来之前,笔者也总结过种类繁多,类似词向量的内容,自然语言处理︱简述四大类文本分析中的"词向量"(文本词特征提取)事实证明,笔者当时所写的基本跟CIPS2016一 ...

  7. [DeeplearningAI笔记]序列模型2.3-2.5余弦相似度/嵌入矩阵/学习词嵌入

    5.2自然语言处理 觉得有用的话,欢迎一起讨论相互学习~Follow Me 2.3词嵌入的特性 properties of word embedding Mikolov T, Yih W T, Zwe ...

  8. [DeeplearningAI笔记]序列模型2.1-2.2词嵌入word embedding

    5.2自然语言处理 觉得有用的话,欢迎一起讨论相互学习~Follow Me 2.1词汇表征 Word representation 原先都是使用词汇表来表示词汇,并且使用1-hot编码的方式来表示词汇 ...

  9. 吴恩达《深度学习》-课后测验-第五门课 序列模型(Sequence Models)-Week 2: Natural Language Processing and Word Embeddings (第二周测验:自然语言处理与词嵌入)

    Week 2 Quiz: Natural Language Processing and Word Embeddings (第二周测验:自然语言处理与词嵌入) 1.Suppose you learn ...

随机推荐

  1. tarjan算法强连通分量的正确性解释+错误更新方法的解释!!!+hdu1269

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1269 以下内容为原创,转载请声明. 强连通分量SCC(Strongly Connected Compo ...

  2. P2341 [USACO03FALL][HAOI2006]受欢迎的牛 G 题解

    原题链接 POJ的链接 简要题意: 给定一张图,求多少个点,每个点都能到达它. 本题作为强连通分量的入门题. 何为强连通分量?有什么用? 下面一一解释. 首先,我们要确认,这道题目如果不用强连通分量而 ...

  3. 条件随机场 CRF

    2019-09-29 15:38:26 问题描述:请解释一下NER任务中CRF层的作用. 问题求解: 在做NER任务的时候,神经网络学习到了文本间的信息,而CRF学习到了Tag间的信息. 加入CRF与 ...

  4. TensorFlow RNN 教程和代码

    分析: 看 TensorFlow 也有一段时间了,准备按照 GitHub 上的教程,敲出来,顺便整理一下思路. RNN部分 定义参数,包括数据相关,训练相关. 定义模型,损失函数,优化函数. 训练,准 ...

  5. 树莓派3B+之Raspbian系统的安装

    概述 因为之前一段时间在研究物联网的原因,所以对树莓派这个东西早就有所耳闻.在我的印象里,树莓派几乎无所不能,它可以用来学编程. 搞物联网. 做服务器,甚至还能用它来进行渗透测试.终于,没禁的住诱惑, ...

  6. 模块 collections 高级数据类型

    collections模块 原文来自cnblog 的 Eva-J Eva-J 介绍了collections模块的常用方法,和演示实例 在 Python cookbook 的第一章中还有一些 更加好玩的 ...

  7. vue组件中的style scoped中遇到的问题

    在uve组件中我们我们经常需要给style添加scoped来使得当前样式只作用于当前组件的节点.添加scoped之后,实际上vue在背后做的工作是将当前组件的节点添加一个像data-v-1233这样唯 ...

  8. TCP漫谈之keepalive和time_wait

    TCP是一个有状态通讯协议,所谓的有状态是指通信过程中通信的双方各自维护连接的状态. 一.TCP keepalive 先简单回顾一下TCP连接建立和断开的整个过程.(这里主要考虑主流程,关于丢包.拥塞 ...

  9. centos7 编译安装mysql5.7

    mysql源码可以到官网下载 安装依赖包 yum -y install gcc gcc-c++ ncurses ncurses-devel bison libgcrypt perl make cmak ...

  10. 【cs224w】Lecture 4 - 社区结构

    Community 转自本人:https://blog.csdn.net/New2World/article/details/105328390 之前讲到了网络中节点扮演不同角色,而角色这个概念和社区 ...