Facebook:FastText 理解和在query意图识别的应用

范涛
发表于2017-04-06

参考文献:

前言
        Facebook 在2016年第一次对外公开FastText算法时候,应该是引起很大一番讨论,因为论文提到他以更快的速度达到和DNN类似的效果。这里不再争论这点。当时吸引我一点的是他在大规模数据集上的扩展性和速度上都很棒,因为这两点十分适合工业界应用。当时正好在做query意图识相关的任务,语料也是几百万。最开始拿的是Navie Bayies做baseline,Navie Bayies这种生成模型在大语料下不仅训练耗时,关键让人失望的是,预测速度变得也不那么快。基于当时的现状,我觉得我可以接受些许准确率损失,来换来模型训练和预测时效性得显著提高。这个时候,我直接拿FastText来进行query 意图识别。结果FastText的效果果然没让我失望,训练耗时从之前几个小时到现在的几分钟,预测速度那叫一个快啊。更让我惊喜的是,准确性上一点也不差,有些场景比NB还好。

FastText 重点解析

FasText中分类模型示意图:


 FastText 代码组织结构图如下(原图源于 https://heleifz.github.io/14732610572844.html博客):


model 模块结构图如下(原图源于 https://heleifz.github.io/14732610572844.html博客):



 训练部分核心代码:
       主要功能就是如何计算梯度和更新,以及输出权重矩阵wo,输入矩阵wi如何更新等。隐层hidden其实就是输入矩阵wi的各个词的平均,是一个一维向量。


 采用二分类,计算logloss,更新梯度和输出权重矩阵。
wo+=hidden*(label-sigmoid(woi * hidden))*lr
隐层的梯度grad+=woi *(label-sigmoid(woi * hidden))* lr
公式的由来可以参考Word2vector中cbow负采样模型求解。截图如下:




         
负采样模式计算loss,更新梯度和更新权重矩阵:
       初正样本外,负样本是随机采样。target可以分类label, 也可以是word。采样命中率和词频或者label频率正相关。
          

层次softmax模式计算loss,更新梯度和更新权重矩阵:
       首先是根据词频或者labels频率建立个huffman树,这个huffman数每层遍历进行二分类LR。



  简单softmax模式计算loss,更新梯度和更新权重矩阵:

         

模型训练更新参数总入口:
     先前向传播计算隐层hidden,计算loss,然后反向更新梯度,再把梯度值进行按输入平均,反向更新到输入矩阵wi
     


 
       skipgram 相对原始的word2vector做了修正,对一个词,扩展了这个词char-ngrams,比如“examples”这个词的char-ngrams可能是“am”,“exa”,“xamp”等,skipgram过程则修正为这个词以及这个词char-ngrams词向量平均来预测这个词的上下文。这么做的好处,《Enriching Word Vectors with Subword Information》这篇文章中给的解释如下:解决word2vector 中同一个词不同形态问题和更好的解决一些不常见词的词向量问题。值得说明的是比如“examples”中char-ngram 的“am”和单独一个单词“am”词向量是不一样的,因为两者对应的索引位置不同。比如char-ngram 出的词索引会放在bucket部分的。

如下面的这块代码:
          char-Ngrams计算方式:
               
          
            skipgram模型:
              
          
           cbow模型:
          


           
            分类模型:
             分类模型每行输入line是个vector,这个vector包含了unigram,还包含wordgram. 分类模型没有采用char-ngrams
              

分类预测模块:
        wi是词向量输入矩阵,维度(词数量,词嵌入维度),隐层hidden其实就是输入向量矩阵wi的各个词的加权平均,是一个一维向量。wo是一个输出权重矩阵,维度(label数,嵌入维度)。最终的分类label确定方式,如果loss_name不是层次softmax的话,就是wo和hidden相乘得到个一维向量,看这个一维向量那个位置值最大,那这个位置对应的label就是最终分类标签。
    

词向量模型如何输出一个词的向量? 
    一个词的最终向量表示由这个词以及这个词char-ngrams词向量的平均值来表示。
       

词是如何存储和索引的?
    可以看Dictionary模块。word是通过hash机制+线性寻址来索引的。下面是相关代码:
    

 总结
        最后想提下,FastText 中分类这块其实一个简单的线性分类器,他最大的优势是快速训练和预测,几百万的训练数据几分钟就搞定了,十分适用于工业界场景。如果要说有什么不足的话?  我觉得是不支持从已有训练好的大规模词向量模型进行fine-tune的机制。我觉得用已有更大规模的语料训练好的词向量模型fine-turn是有好处的,尤其如果分类任务的语料不够大的情形。其实仔细想想,FastText 框架如果想修改成支持fine-turn也是很方便的,就是类似里面“printVectors”函数,加载词向量模型来初始化input矩阵。

猜你喜欢

转载自blog.csdn.net/hero_fantao/article/details/69487744
今日推荐