当前位置:   article > 正文

情感分类——glove_glove情感句子

glove情感句子

序言

  • glove自己很早就看完过,但是一直没有空看看源码,今天趁前面分类模型实验基本结束,抽空看看它的源码。
  • glove理论讲解
  • glove源码

Why is it?

glove简介

  • GloVe的全称叫Global Vectors for Word Representation,它是一个基于全局词频统计(count-based & overall statistics)的词表征(word representation)工具
  • 请注意,在看glove之前,抛弃word2vec的神经网络思想,glove里没有神经网络!!
  • 代码没有像word2vec那样需要手写,所以没有细看,大致了解了他的思想。

GloVe实现的

代码逻辑

GloVe代码包括了四个.c文件

  • 首先执行vocab_count.c这个文件的功能是扫一遍语料,建立一个字典。
  • 执行cooccur.c文件。它的功能是从语料中建立共现矩阵,GloVe是在共现矩阵上面进行训练的。所谓共现矩阵,在GloVe中是大量的三元组<eat, food, 150>,<of, the, 100000>…cooccur.c文件生成的三元组的顺序是根据词频排好序的。比如<of, the, 100000>在<eat, food, 150>前面,因为of的频数大于eat。<of, the, 100000>在<of, mine, 1000>前面,因为the的频数大于mine。
  • 执行第三个文件shuffle.c。这个文件是用来打乱之前生成的共现矩阵(也就是打乱三元组的顺序)。
  • 最后执行glove.c。它会在打乱顺序的三元组上面训练词向量。

具体代码

  • vocab_count.c:
  • vocab_count的功能就是生成词典。它的输入是整个语料,它的输出是词典。词典的形式是单词以及单词在语料中出现的次数(频数)。词典是按照频数从高到低排好序的。

根据语料库(corpus)构建一个共现矩阵(Co-ocurrence Matrix)

  • 常理来说,统计共现矩阵就是一个统计问题,但是如果内存不够呢?
  • glove采取了一种很神奇的方式解决,具体可以看下面博文的解释。(自lu不动了…)
  • GloVe源码解析之cooccur
思路
  • 如何存储共现矩阵?

  • 一个很直接简单的方法就是用二维数组去存

  • 这么做忽略了一个问题,就是共现矩阵太过稀疏,大多数的单词从来没有共现过,通过二维矩阵存非常浪费内存。实际上一般内存也根本存不下甚至中等规模大小的语料。所以用二维数据存储共现矩阵,在大规模语料上面是不可行的。

  • 既然显示的存储共现矩阵不行,我们可以用稀疏矩阵的方式压缩去存储。扫描语料的过程中不断地更新稀疏矩阵,从而得到最终的共现矩阵。

  • 所以现在我们的目标是,压缩存储稀疏矩阵!

  • 常见的方式是行压缩和列压缩,数据结构用数组,但glove并不是!

  • glove的思路是:首先不断地从文件中读取单词对(pair),读到内存写满为止。对这些pair进行排序以及汇总,然后写出到文件。以此类推,我们就能得到很多文件,每个文件里面存的都是对部分的语料的共现矩阵。然后我们对这些共生矩阵再进行汇总。

  • 这种方法对内存更友好(当然,这是一种大数据思想)

  • 当然,最秒的还在后面:

  • 在GloVe代码中,它使用了混合的数据结构去存储共现矩阵。当我们的单词按照它们的频数排好序以后,比如the的id是1,of的id是2然后以此类推。我们会发现共现矩阵的左上角是非常稠密的。当一个pair中两个单词的id都很小(它们的频数很大),他们很有可能共现。而共现矩阵的其它地方很稀疏。比如右下角,低频词不大可能共现。基于这个观察,GloVe中使用二维矩阵去显式的存储共现矩阵的左上角,剩下的部分用我上段中提到的方法建立共现矩阵。所以,共现矩阵的左上角是一直在内存中的,剩余部分会写出最后再汇总。这里再说一下什么是左上角,GloVe中认为word pair中两个单词的id的乘积小于某个阈值时算是在左上角( d越小,词频越高 )。阈值时100的时候,id为9和id为10的单词组成的pair就算在共现矩阵的左上角,因为9乘以10小于100.

  • 一种"内存读取"的思路铺面而来。

  • 最后,还有一个很秒的地方是:

  • 共现矩阵左上角以外的部分使用一个三元组去存储的。分别是第一个单词的id第二个单词的id以及他们的共现次数。GloVe对共现次数的计算是随着单词之间距离递减的,比如两个单词距离为5,那么算他们共现五分之一。所以共现次数是浮点型。建立共现矩阵自然也需要词典,所以内存中会维护词典。词典中记录单词的字符串和id,不再记录频数,单词的id是根据频数来的,频数越高id越小

  • 这简直就是:在有限的内存情况下,尽可能压榨代码的效率和空间使用情况。

  • 代码内的hash是为了提高查找效率。

  • 第一阶段:统计共现的策略就和上面说的一样:循环读取单词,按照索引存入“显存数组”还是三元组内,达到指定大小后,就把三元组写到文件里。

  • 第一阶段完成,进入第二阶段,对临时文件进行汇总。利用的是最小堆思想:

  • 将overflow_0000.bin、0001.bin、0002.bin整理到一起,保存到cooccurrence.bin中。整合的时候,使用priority queue(最小堆,以词在字典中的序号为键,从小到大)来实现,从每个bin文件中读取一条记录插入到堆中,即堆中只保存一个bin文件的一条记录。堆建成后,取出堆顶元素保存到变量old后调整堆,从old的来源的bin文件中再读取一条记录保存到new,并插入堆中。此后,开始迭代处理,比较堆顶元素与old是否标记了同样两个词,如果是,则将堆顶元素合并到old中,否则,将old写入到cooccurence.bin中,并将堆顶元素赋值给old,记录堆顶元素的来源文件i,然后删除堆顶元素并读入i文件的下一条记录,并加入到堆中;重复这样的循环过程,直到所有的bin文件都读完。再次注意:堆只保存了每个bin文件的一条记录。

  • 构造loss function

训练

  • 使用的是adagrad梯度下降

参考

[ 1 ]glove详解

[ 2 ]GloVe源码解析之cooccur

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/794522
推荐阅读
相关标签
  

闽ICP备14008679号