MENU

fastText细节及实践

June 16, 2020 • Read: 155 • Deep Learning

fastText模型是类似CBOW的三层结构,关于这个结构的介绍,很多博客都讲了,这里我不多赘述,我主要叙述一下其中的部分细节

N-gram

输入层是文档中所有词的词向量和文档中各个单词的n-gram向量。隐藏层是这些向量的叠加平均

从输入开始,fastText和CBOW就不一样,主要在于fastText的输入还包括每个单词的n-gram。举个例子,假设某个文档中只有三个词I like apple,N-gram的N取3,那么隐藏层可表示为

这样做有什么好处?我们知道,"apple"和"apples"在通常情况下几乎是同一个意思,但是如果仅使用传统的方法,以词为单位作为输入,输入的是每个词的one-hot编码,而"apple"和"apples"的one-hot可能并没有任何关系。但如果考虑n-gram,它俩在字符级别是非常相似的,这样最终训练出来的词向量相比传统方法会更好

Hash

由于n-gram的量远比word大的多,完全存下所有的n-gram不太现实。fastText采用的是Hash桶的方式,把所有的n-gram映射到buckets个桶中,而映射到相同桶的n-gram共享同一个embedding vector,如下图所示

图中Win代表整个Embedding矩阵,其中前V行是word Embedding,后Buckets行是n-gram Embedding,每个n-gram通过hash函数之后映射到0~Bucket-1位置,得到对应的embedding向量。用哈希的方式既能保证查找时O(1)的效率,又可能把内存消耗控制在O(buckets * dim)范围内。不过这种方法潜在的问题是存在哈希冲突,不同的n-gram可能会共享同一个embedding。如果桶大小取的足够大,这种影响会很小

实践

实验的平台为google colab

首先安装fastText,可能您看到这篇文章的时候,fastText已经更新了最新版本,在这里查看最新的版本号

!wget https://github.com/facebookresearch/fastText/archive/v0.9.2.zip
!unzip v0.9.2.zip
%cd fastText-0.9.2
!make

自定义一个简单的数据集,做文本分类任务,其中__label__是每个类别的默认前缀

# 0 is positive, 1 is negative
with open('train.txt', 'w') as f:
  f.write('__label__0 i love you\n')
  f.write('__label__0 he loves me\n')
  f.write('__label__0 she likes baseball\n')
  f.write('__label__1 i hate you\n')
  f.write('__label__1 sorry for that\n')
  f.write('__label__1 this is awful')

with open('test.txt', 'w') as f:
  f.write('i like you\n')
  f.write('sorry hate you\n')

然后开始训练,后面所跟的详细参数说明,可以看这篇文章

!./fasttext supervised -input train.txt -output model -dim 2 -wordNgrams 2 -lr 0.7 -epoch 50 -loss ns -neg 2

最后对测试集进行预测

!cat test.txt
!./fasttext predict model.bin test.txt

如果想了解python代码调用fastText的方式,可以查看我的这篇文章

参考文献

N-gram特征,浅谈FastText文本分类利器解读(2)

Archives Tip
QR Code for this page
Tipping QR Code
Leave a Comment

已有 2 条评论
  1. Aiden Aiden

    学长我好崇拜你,目前正在21考研备考,向您看齐!!!

    1. mathor mathor

      @Aiden加油