Fasttext源于2016年的论文《Bag of Tricks for Efficient Text Classification》,论文地址:https://arxiv.org/pdf/1607.01759.pdf。论文非常短,加上References不过五页,Model architecture只有一页。

深度学习神经网络在自然语言处理中表现非常优秀,但动辄几十层,上亿参数的大型网络速度慢且需要大量算力支持,限制了使用场景。FastText是Facebook开源的一款简单而高效的文本分类器,它使用浅层的神经网络实现了word2vec以及文本分类功能,效果与深层网络差不多,节约资源,且有百倍的速度提升,可谓高效的工业级解决方案。本篇将介绍Fasttext的相关概念、原理及用法。

相关概念

BOW

BOW是词袋Bag of Words的简称,BOW是文本分类中常用的文本向量化的方法,它忽略了顺序和语法,将文本看成词汇的集合,且词汇间相互独立,如同把词放进了一个袋子。在分类任务中使用BOW时,就是根据各个词义综合分析文本的类型,常用于感情色彩分类等领域。

CBOW

CBOW是连续词袋模型Continuous Bag-of-Word Model的简称,它常用于上下文词来预测中间词。

如图所示,使用前两个和后两个词(共C=4个)预测中间的词w,其中每个词被映射成V维的词向量;每个词向量乘以参数矩阵A(VN维矩阵),转换成N维数据,然后将所有词对应的N维的数据相加取均值,计算出N维的隐藏层Hidden;再用隐藏层乘参数矩阵B(NV维),计算待预测的词w对应的V维词向量;最终用预测出的w与真实的w作比较计算误差函数,然后用梯度下降调整A,B两个参数矩阵。由此,使用简单的神经网络就完成了预测任务。

N-gram

N-gram是由N个token(词)组成的有序集合,常用的有Bi-gram (N=2)和Tri-gram (N=3),实际使用中2或3-gram就够用了。Fasttext论文中使用Bi-gram将文本拆成词对。

如I love deep learning可拆成:
Bi-gram : {I, love}, {love, deep}, {deep, learning}
Tri-gram : {I, love, deep}, {love, deep, learning}

这样使一个词它之前的词建立联系。
以Bi-gram为例,Wn-1出现时,Wn出现的概率是:

其中C()表示计数,N-gram技术在自然语言处理中广泛使用。

FastText原理

在文本分类问题中,早期的算法一般将词袋BOW作为输入,使用线性模型作为算法计算类别,这种方法在类别不均衡时效果不好,后来用将线性分类器分解为低秩矩阵或者多层网络的方法解决这一问题。

FastText与CBOW结构类似,如下图所示:

标图片摘自论文题

其中输入是文档中的词,使用词嵌入方法,和CBOW一样,通过乘A矩阵转换到Hidden,再乘B矩阵转换到输出层,与CBOW不同的是它的输出不是空缺的单词,而是分类的类别。

FastText用负对数似然作为损失函数:

其中N是文档数,xn是文档中的词特征。yn是标签,A和B是权重矩阵,A用于转换到文本表示,B用于线性变换计算类别,f是一个softmax函数用于计算最终分类的概率。

当分类的类别较多时,计算的时间复杂度是O(hk),其中k是类别的个数,h是文本表示的维度。Fasttext使用了基于霍夫曼编码树的分级softmax,使训练的时间复杂度降为O(hlog2(k))。每一个节点的概率大小与从树根到该节点经过的路径有关,例如某节点深度为l+1,它的父节点分别是n1…n2,则它的概率是:

这就意味着,节点的概率小于它父节点的概率,因此访问树时,就可以忽略概率小的分枝。如果只需预测取前TopN,则复杂度可降至O(log(TopN))。

下面列出了FastText与深度学习模型的速度比较,可以看到,其提速非常明显。

个人感觉,层次少的好处不只在于运算速度快,而且更容易归因,定位重要特征,以及估计对应的权重,不像深度网络的数据都散布在各层的节点之中。

FastText用法

安装

$ pip install fasttext

训练和预测

数据格式为:label标签 , 已经分词的文档(注意:label两边都需要又下划线)

如下例所示:

import fasttext
def train(): # 训练模型
    model = fasttext.train_supervised("train.txt", lr=0.1, dim=100,
             epoch=5, word_ngrams=2, loss='softmax')
    model.save_model("model_file.bin")

def test(): # 预测
    classifier = fasttext.load_model("model_file.bin")
    result = classifier.test("test.txt")
    print("准确率:", result)
    with open('test.txt', encoding='utf-8') as fp:
        for line in fp.readlines():
            line = line.strip()
            if line == '':
                continue
            print(line, classifier.predict([line])[0][0][0])

if __name__ == '__main__':
    train()
    test()

资料

建议下载源码:
https://github.com/facebookresearch/fastText#

更详细的用法示例请见:
https://github.com/facebookresearch/fastText#example-use-cases

posted on 2020-03-15 09:55  xieyan0811  阅读(69)  评论(0编辑  收藏  举报