【NLP.TM】GloVe模型及其Python实现

2020 年 11 月 24 日 AINLP


NLP.TM


本栏目是结合我最近上的课,和我最近的研究方向,自然语言处理和文本挖掘而设计的,会讲一些和自然语言处理以及文本挖掘相关的内容,欢迎大家关注和交流!



往期回顾:

在进行自然语言处理中,需要对文章的中的语义进行分析,于是迫切需要一些模型去描述词汇的含义,很多人可能都知道word2vector算法,诚然,word2vector是一个非常优秀的算法,并且被广泛运用,为人们熟知,然而,从结果的优劣性来看,其实word2vector并非唯一的优秀方案,斯坦福大学提出的GloVe就是其中之一。今天我来为大家介绍一下GloVe模型,但是重点,还是放在实现上。

原论文:http://www.eecs.wsu.edu/~sji/classes/DL16/CNN-text/glove.pdf

简单地说一下原理

这里的原理我主要参考了两篇博客,感谢两位优秀的博主。

  • 理解GloVe模型(+总结):https://blog.csdn.net/u014665013/article/details/79642083

  • GloVe模型:https://www.cnblogs.com/Weirping/p/7999979.html

前者会比较通俗,后者则比较深刻。

共现关系

和word2vector不同,GloVe更倾向于进行分析前后语境之间的共现关系,通过共现关系抽象出词向量。

所谓的共现,共同出现,其实就是看一个词有没有在另一个词的附近出现,所谓的附近,其实就是一个移动窗口的概念,定义窗口的半径(从中心词到边缘的距离)后,看看方圆多少范围内出现词的个数,就是共现,现在看看例子。

假设语料库就只有下面一行:

i love you but you love him i am sad

设半径为2,于是移动窗口的滑动就有下面的形式:

以窗口5为例,此处就可以认为,love分别和but, you, him, i共同出现了一次,通过这种方式去计数,就能知道任意两个词之间的共现关系(一般是可逆的),构成共现矩阵X,一般地,X是一个对称矩阵。

词向量的产生

首先,模型的损失函数长这样的:

vi和vj是词汇i和j的词向量,bi和bj是常数项,f是特定的权重函数,N是词汇表大小。

这个损失函数怎么来的,我觉得上面的第一个链接讲的非常清楚,看的时候注意一个核心,就是考虑两个词汇的共现关系与词向量之间的关系(映射)尽可能接近,于是就构造了上面的损失函数。

GloVe的Python实现

在pypi里面看到了很多GloVe的包,但是很多都有坑,我直接说一个我自己已经走通的包mittens。

下载方式还是比较简单的, pip install mittens基本没什么问题,想要去看看源码的话,在这里:

https://github.com/roamanalytics/mittens

一般而言GloVe按照计算共现矩阵和GloVe训练两大模块,而mittens里面其实只提供了后者,前者还是需要自己写,这是我写的部分内容,给大家详细讲讲(复杂度啥的基本没做什么优化,欢迎提出一些意见)。

共现矩阵的计算

将之前事先说明一下,现在读进来的数据,即代码中的“data”变量,每行不是对应的单词或者短语,而是已经对应在词典中的该短语的index(自己构建词典,一般设置为0-(N-1),N为词典中词语的个数),尤其在后面的cooccurrence的统计,即如果句子数组中的第i个词语是词典中的第j个词,则句子向量中第i个位置就是数字j,这种方式对cooccurrence的统计非常方便。

  
  
    
  1. # 构建空的词表

  2. coWindow = 3  # 共现窗口大小(半径)

  3. tableSize = 1000    # 共现矩阵维度

  4. cooccurrence = np.zeros((tableSize, tableSize),"int64")

首先是数据初始化,这里不详细说数据载入了,但是共现矩阵当然是需要初始化的(np是numpy别忘了)。

  
  
    
  1. # 开始统计

  2. flag = 0

  3. for item in data:

  4.    itemInt = [int(x) for x in item]

  5.    for core in range(1, len(item)):

  6.        if core <= coWindow + 1:

  7.            # 左窗口不足

  8.            window = itemInt[1:core + coWindow + 1]

  9.            coreIndex = core - 1

  10.            cooccurrence = countCOOC(cooccurrence, window, coreIndex)

  11.        elif core >= len(item) - 1 - coWindow:

  12.            # 右窗口不足

  13.            window = itemInt[core - coWindow:(len(item))]

  14.            coreIndex = coWindow

  15.            cooccurrence = countCOOC(cooccurrence, window, coreIndex)

  16.        else:

  17.            # 左右均没有问题

  18.            window = itemInt[core - coWindow:core + coWindow + 1]

  19.            coreIndex = coWindow

  20.            cooccurrence = countCOOC(cooccurrence, window, coreIndex)

  21.    flag = flag + 1

  22.    if flag % 1000 == 0:

  23.        endTime = datetime.datetime.now()

  24.        print("已经计算了%s条数据,用时%s" % (flag, endTime - startTime))

这一块里面主要是为了设置移动窗口来进行挪动识别,具体统计移动窗口内部的共现,是在countCOOC函数里面做的。

  
  
    
  1. def countCOOC(cooccurrence, window, coreIndex):

  2.    # cooccurrence:当前共现矩阵

  3.    # window:当前移动窗口数组

  4.    # coreIndex:当前移动窗口数组中的窗口中心位置

  5.    for index in range(len(window)):

  6.        if index == coreIndex:

  7.            continue

  8.        else:

  9.            cooccurrence[window[coreIndex]][window[index]] = cooccurrence[window[coreIndex]][window[index]] + 1

  10.    return cooccurrence

countCOOC用来当前移动窗口的共现,一个一个计数即可。

GloVe的训练

  
  
    
  1. # 包的引入

  2. from mittens import GloVe

  3. # 初始化模型

  4. vecLength=100           # 矩阵长度

  5. max_iter=100000         # 最大迭代次数

  6. display_progress=1000   # 每次展示

  7. glove_model = GloVe(n=vecLength, max_iter=max_iter, display_progress=display_progress)

  8. # 模型训练与结果输出

  9. embeddings = glove_model.fit(coocMatric)

引入包之后,配置相应的参数,然后可以开始训练,训练完的返回值embeddings就是得到的词向量词典,通过词向量词典,就能够将每篇文本的每一个单词转化为词向量,从而进行进一步分析。

小结

GloVe终于写完了,不知道大家觉得怎么样,关于原理写的人相对比较多,也理解的比我好我就不再解释了,而代码这块,网上写的不多,所以我写得详细一些,这也是我把结果写出来的核心代码,有什么问题我来回答,后台提问即可。


由于微信平台算法改版,公号内容将不再以时间排序展示,如果大家想第一时间看到我们的推送,强烈建议星标我们和给我们多点点【在看】。星标具体步骤为:

(1)点击页面最上方"AINLP",进入公众号主页。

(2)点击右上角的小点点,在弹出页面点击“设为星标”,就可以啦。

感谢支持,比心

欢迎加入AINLP技术交流群
进群请添加AINLP小助手微信 AINLPer(id: ainlper),备注技术交流

推荐阅读

这个NLP工具,玩得根本停不下来

征稿启示| 200元稿费+5000DBC(价值20个小时GPU算力)

完结撒花!李宏毅老师深度学习与人类语言处理课程视频及课件(附下载)

从数据到模型,你可能需要1篇详实的pytorch踩坑指南

如何让Bert在finetune小数据集时更“稳”一点

模型压缩实践系列之——bert-of-theseus,一个非常亲民的bert压缩方法

文本自动摘要任务的“不完全”心得总结番外篇——submodular函数优化

Node2Vec 论文+代码笔记

模型压缩实践收尾篇——模型蒸馏以及其他一些技巧实践小结

中文命名实体识别工具(NER)哪家强?

学自然语言处理,其实更应该学好英语

斯坦福大学NLP组Python深度学习自然语言处理工具Stanza试用

关于AINLP

AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括文本摘要、智能问答、聊天机器人、机器翻译、自动生成、知识图谱、预训练模型、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLPer(id:ainlper),备注工作/研究方向+加群目的。


阅读至此了,分享、点赞、在看三选一吧🙏

登录查看更多
2

相关内容

【2020新书】深度学习自然语言处理简明导论,69页pdf
专知会员服务
114+阅读 · 2020年11月7日
【新书】Pro 机器学习算法Python实现,379页pdf
专知会员服务
199+阅读 · 2020年2月11日
Transformer文本分类代码
专知会员服务
116+阅读 · 2020年2月3日
博客 | MIT—线性代数(上)
AI研习社
9+阅读 · 2018年12月18日
教你在Python中实现潜在语义分析(附代码)
数据派THU
8+阅读 · 2018年12月6日
不懂 word2vec,还敢说自己是做 NLP 的?
AI研习社
8+阅读 · 2018年5月4日
基础|Word2vec的原理介绍
全球人工智能
10+阅读 · 2018年1月4日
教程 | 在Python和TensorFlow上构建Word2Vec词嵌入模型
机器之心
6+阅读 · 2017年11月20日
深度学习 | 利用词嵌入对文本进行情感分析
沈浩老师
11+阅读 · 2017年10月19日
Python 自然语言处理(NLP)工具库汇总
数据挖掘入门与实战
7+阅读 · 2017年9月25日
NLP自然语言处理(二)——基础文本分析
乐享数据DataScientists
12+阅读 · 2017年2月7日
NLP自然语言处理(一)——jieba分词(R vs. python)
乐享数据DataScientists
6+阅读 · 2017年1月15日
Arxiv
0+阅读 · 2021年1月31日
Universal Transformers
Arxiv
5+阅读 · 2019年3月5日
Arxiv
3+阅读 · 2018年8月27日
VIP会员
相关VIP内容
【2020新书】深度学习自然语言处理简明导论,69页pdf
专知会员服务
114+阅读 · 2020年11月7日
【新书】Pro 机器学习算法Python实现,379页pdf
专知会员服务
199+阅读 · 2020年2月11日
Transformer文本分类代码
专知会员服务
116+阅读 · 2020年2月3日
相关资讯
博客 | MIT—线性代数(上)
AI研习社
9+阅读 · 2018年12月18日
教你在Python中实现潜在语义分析(附代码)
数据派THU
8+阅读 · 2018年12月6日
不懂 word2vec,还敢说自己是做 NLP 的?
AI研习社
8+阅读 · 2018年5月4日
基础|Word2vec的原理介绍
全球人工智能
10+阅读 · 2018年1月4日
教程 | 在Python和TensorFlow上构建Word2Vec词嵌入模型
机器之心
6+阅读 · 2017年11月20日
深度学习 | 利用词嵌入对文本进行情感分析
沈浩老师
11+阅读 · 2017年10月19日
Python 自然语言处理(NLP)工具库汇总
数据挖掘入门与实战
7+阅读 · 2017年9月25日
NLP自然语言处理(二)——基础文本分析
乐享数据DataScientists
12+阅读 · 2017年2月7日
NLP自然语言处理(一)——jieba分词(R vs. python)
乐享数据DataScientists
6+阅读 · 2017年1月15日
Top
微信扫码咨询专知VIP会员