自然语言处理之fastText

一、整体结构

fastText的代码整体结构如下图所示:
在这里插入图片描述

1、fastText简介

  • fastText是一个快速文本分类算法,与基于神经网络的分类算法相比有两大优点:
    1、fastText在保持高精度的情况下加快了训练速度和测试速度
    2、fastText不需要预训练好的词向量,fastText会自己训练词向量 3、fastText两个重要的优化:Hierarchical
    Softmax、N-gram

2、fastText模型架构

  • fastText模型架构和word2vec中的CBOW很相似,不同之处是fastText预测标签而CBOW预测的是中间词,即模型架构类似但是模型的任务不同。下面我们先看一下CBOW的架构:

    在这里插入图片描述

  • word2vec将上下文关系转化为多分类任务,进而训练逻辑回归模型,这里的类别数量|V|词库大小。通常的文本数据中,词库少则数万,多则百万,在训练中直接训练多分类逻辑回归并不现实。word2vec中提供了两种针对大规模多分类问题的优化手段,negative sampling 和hierarchical softmax。在优化中,negative sampling只更新少量负面类,从而减轻了计算量。hierarchical softmax将词库表示成前缀树,从树根到叶子的路径可以表示为一系列二分类器,一次多分类计算的复杂度从|V|降低到了树的高度

  • fastText模型架构:其中x1,x2,…,xN−1,xN表示一个文本中的n-gram向量,每个特征是词向量的平均值。这和前文中提到的cbow相似,cbow用上下文去预测中心词,而此处用全部的n-gram去预测指定类别
    在这里插入图片描述

3、层次softmax

  • softmax函数常在神经网络输出层充当激活函数,目的就是将输出层的值归一化到0-1区间,将神经元输出构造成概率分布,主要就是起到将神经元输出值进行归一化的作用
  • 在标准的softmax中,计算一个类别的softmax概率时,我们需要对所有类别概率做归一化,在这类别很大情况下非常耗时,因此提出了分层softmax(Hierarchical Softmax),思想是根据类别的频率构造霍夫曼树来代替标准softmax,通过分层softmax可以将复杂度从N降低到logN,下图给出分层softmax示例:
    在这里插入图片描述
  • 在层次softmax模型中,叶子结点的词没有直接输出的向量,而非叶子节点都有响应的输在在模型的训练过程中,通过Huffman编码,构造了一颗庞大 Huffman树,同时会给非叶子结点赋予向量。我们要计算的是目标词w的概率,这个概率的具体含义,是指从root结点开始随机走,走到目标词w的概率。因此在途中路过非叶子结点(包括root)时,需要分别知道往左走和往右走的概率。

4、N-gram特征

  • n-gram是基于语言模型的算法,基本思想是将文本内容按照子节顺序进行大小为N的窗口滑动操作,最终形成窗口为N的字节片段序列。而且需要额外注意一点是n-gram可以根据粒度不同有不同的含义,有字粒度的n-gram和词粒度的n-gram。

二、fastText实战篇

1、fastText环境要求

  • fastText需要运行在MacOS或Linux上,因为fastText使用了C++11,因此需要很好支持C++11的编译器,支持的编译器包括:
    (1) gcc-4.6.3 或者更新版本
    (2) clang-3.3 或者更新版本
  • 编译是使用Makefile执行的,因此你需要有一个工作的make,对于单词相似度评估脚本则需要如下环境:
    (1) python2.6 或者更新 (2) numpy 和 spicy

2、在本地快速搭建fastText
为了搭建fastText,打开命令窗口依次执行以下命令

$ git clone https://github.com/facebookresearch/fastText.git
$ cd fastText
$ make

上述命令将为所有类和主二进制fastText生成目标文件,如果你不打算使用默认的系统范围编译器,可以更新Makefile(CC和include)开头定义的两个宏

3、fastText-文本分类

  • 首先我们需要做的便是安装搭建fastText,需要系统支持c++
    11的c++编译器,先从GitHub上下载fastText到本地(版本在更新,可以到GitHub上查看最近版本进行下载):
$ wget https://github.com/facebookresearch/fastText/archive/v0.1.0.zip
  • 然后将下载的zip文件夹进行解压,解压后进入目录对fastText项目执行make命令进行编译(因此这里便需要你的系统有支持c++11的编译器)
$ unzip v0.1.0.zip
$ cd fastText-0.1.0
$ make
  • 在根目录下运行名为fasttext的二进制文件,便会打印出fastText支持的各种不同的命令,如:supervised进行模型训练,quantize量化模型以减少内存使用,test进行模型测试,predict预测最可能的标签等,运行结果如下所示:
>> ./fasttext
usage: fasttext <command> <args>

The commands supported by fasttext are:

  supervised              train a supervised classifier
  quantize                quantize a model to reduce the memory usage
  test                    evaluate a supervised classifier
  predict                 predict most likely labels
  predict-prob            predict most likely labels with probabilities
  skipgram                train a skipgram model
  cbow                    train a cbow model
  print-word-vectors      print word vectors given a trained model
  print-sentence-vectors  print sentence vectors given a trained model
  nn                      query for nearest neighbors
  analogies               query for analogies

每个命令分别为:

supervised: 训练一个监督分类器
quantize:量化模型以减少内存使用量
test:评估一个监督分类器
predict:预测最有可能的标签 
predict-prob:用概率预测最可能的标签
skipgram:训练一个 skipgram 模型
cbow:训练一个 cbow 模型
print-word-vectors:给定一个训练好的模型,打印出所有的单词向量
print-sentence-vectors:给定一个训练好的模型,打印出所有的句子向量
nn:查询最近邻居
analogies:查找所有同类词

4、获取数据及数据预处理

  • 我们需要带有标签的数据去训练我们的监督学习的分类器,本教程中,我们使用cooking相关数据构建我们的分类器,因此首先我们下载数据,数据网址为stackexchange,进行如下命令操作:
 wget https://dl.fbaipublicfiles.com/fasttext/data/cooking.stackexchange.tar.gz
 tar xvzf cooking.stackexchange.tar.gz
 head cooking.stackexchange.txt
  • 通过head命令便可看到文档形式,文档的每一行都包含一个标签,标签后面跟着相应的单词短语,所有的标签都以__label__前缀开始,这事fastText便是标签和单词短语的方式,训练的模型便是预测文档中给定单词短语预测其对应的标签。
  • 在训练分类器之前,我们需要将数据分割成训练集和验证集,我们将使用验证集来评估学习到的分类器对新数据的性能好坏,先通过下面命令来查看文档中总共含有多少数据:
>> wc cooking.stackexchange.txt 
   15404  169582 1401900 cooking.stackexchange.txt

可以看到我们数据中总共包含了15404个示例,我们把文档分成一个包含12404个示例的训练集和一个包含3000个示例的验证集,执行如下命令:

 head -n 12404 cooking.stackexchange.txt > cooking.train
 tail -n 3000 cooking.stackexchange.txt > cooking.valid

5、使用fastText快速搭建分类器

  • 接下来我们便开始训练我们的模型,首先执行如下命令进行模型的训练:
>> ./fasttext supervised -input cooking.train -output model_cooking
Read 0M words
Number of words:  14598
Number of labels: 734
Progress: 100.0%  words/sec/thread: 75109  lr: 0.000000  loss: 5.708354  eta: 0h0m
  • input命令选项指示训练数据,-output选项指示的是保存的模型的位置,在训练结束后,文件model_cooking.bin是在当前目录中创建的,model_cooking.bin便是我们保存训练模型的文件。
  • 模型训练好之后,我们可以交互式测试我们的分类器,即单独测试某一个句子所属的类别,可以通过以下命令进行交互式测试:
>> ./fasttext predict model_cooking.bin -

输入以上命令后,命令行会提示你输入句子,然后我们可以进行如下句子测试:

Which baking dish is best to bake a banana bread ?

上面句子可以得到预测的标签是baking,显然这个预测结果是正确的,我们再进行尝试

Why not put knives in the dishwasher?

上面句子预测的标签是food-safety,可以看出是不相关的,显然预测的不正确,为了验证学习到的分类模型的好坏,我们在验证集上对它进行测试,观察模型的精准率precision和召回率recall:

>> ./fasttext test model_cooking.bin cooking.valid                 
N  3000
P@1  0.124
R@1  0.0541
Number of examples: 3000

6、模型优化

  • 上面通过使用默认参数运行fastText训练得到的模型在分类新问题上效果很差,接下来我们通过更改默认参数来提高性能。
    数据预处理:
  • 查看数据,我们发现有些单词包含大写字母和标点符号,因此改善模型性能的第一步就是应用一些简单的预处理,预处理可以使用命令行工具例如sed、tr来对文本进行简单的标准化操作,执行命令如下:
>> cat cooking.stackexchange.txt | sed -e "s/\([.\!?,'/()]\)/ \1 /g" | tr "[:upper:]" "[:lower:]" > cooking.preprocessed.txt
>> head -n 12404 cooking.preprocessed.txt > cooking.train
>> tail -n 3000 cooking.preprocessed.txt > cooking.valid 

接下来我们在预处理的数据集上进行模型训练并进行测试,命令如下:

>> ./fasttext supervised -input cooking.train -output model_cooking
Read 0M words
Number of words:  9012
Number of labels: 734
Progress: 100.0%  words/sec/thread: 82041  lr: 0.000000  loss: 5.671649  eta: 0h0m h-14m 
>> ./fasttext test model_cooking.bin cooking.valid 
N  3000
P@1  0.164
R@1  0.0717
Number of examples: 3000

观察上面的结果,由于对数据预处理,词典变小了,由原来的14K个单词变成了9K,精准率也上升了4%,因此数据预处理起到了一定的效果。

更多的训练次数和更大的学习率:

  • 在默认情况下,fastText在训练期间对每个训练用例仅重复使用五次,这太小,因为我们的训练集只有12k训练样例,因此我们可以通过-epoch选项增加每个样例的使用次数,命令如下:
>> ./fasttext supervised -input cooking.train -output model_cooking -epoch 25 
Read 0M words
Number of words:  9012
Number of labels: 734
Progress: 100.0%  words/sec/thread: 77633  lr: 0.000000  loss: 7.147976  eta: 0h0m

然后测试模型查看效果:

>> ./fasttext test model_cooking.bin cooking.valid                                        
N  3000
P@1  0.501
R@1  0.218
Number of examples: 3000
  • 从上面测试效果可以看出,精准率和召回率都有了大幅度提升,可见增加每个样例的使用次数对于数据集少的情况下效果提升明显。另一个增强算法能力是改变模型的学习速度即学习速率,这对应于处理每个示例后模型的更改程度,当学习率为0时意味着模型根本不会发生改变,因此不会学到任何东西,良好的学习率值在0.1-1.0的范围内,下面我们通过设置算法学习率为learning rate = 1.0进行模型训练:
>> ./fasttext supervised -input cooking.train -output model_cooking -lr 1.0  
Read 0M words
Number of words:  9012
Number of labels: 734
Progress: 100.0%  words/sec/thread: 81469  lr: 0.000000  loss: 6.405640  eta: 0h0m
>> ./fasttext test model_cooking.bin cooking.valid                         
N  3000
P@1  0.563
R@1  0.245
Number of examples: 3000

可以看到效果比上面增加epoch还要好,下面我们来将二者结合起来:

>> ./fasttext supervised -input cooking.train -output model_cooking -lr 1.0 -epoch 25
Read 0M words
Number of words:  9012
Number of labels: 734
Progress: 100.0%  words/sec/thread: 76394  lr: 0.000000  loss: 4.350277  eta: 0h0m
>> ./fasttext test model_cooking.bin cooking.valid                                   
N  3000
P@1  0.585
R@1  0.255
Number of examples: 3000

下面我们来增加一些新的方式来进一步提升模型的性能。

word n-grams:

  • 此方案中,我们使用单词bigrams而不是仅仅是unigrams来提高模型的性能,这对于词序很重要的分类问题尤其重要,例如情感分析。n-gram是基于语言模型的算法,基本思想是将文本内容按照子节顺序进行大小为N的窗口滑动操作,最终形成窗口为N的字节片段序列。训练模型命令如下:
>> ./fasttext supervised -input cooking.train -output model_cooking -lr 1.0 -epoch 25 -wordNgrams 2
Read 0M words
Number of words:  9012
Number of labels: 734
Progress: 100.0%  words/sec/thread: 75366  lr: 0.000000  loss: 3.226064  eta: 0h0m 
>> ./fasttext test model_cooking.bin cooking.valid                                                 
N  3000
P@1  0.599
R@1  0.261
Number of examples: 3000

通过几个步骤,可以看出我们将模型精准率从12.4%提升到了59.9%。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值