摘要:Flair 是一个基于 PyTorch 构建的 NLP 开发包,它在解决命名实体识别(NER)、部分语音标注(PoS)、语义消歧和文本分类等 NLP 问题达到了当前的最高水准。它是一个建立在 PyTorch 之上的 NLP 框架。本文将介绍如何使用已有的和构建自定义的文本分类器。
介绍
文本分类是一种监督机器学习方法,用于将句子或文本文档归类为一个或多个已定义好的类别。它是一个被广泛应用的自然语言处理方法,在垃圾邮件过滤、情感分析、新闻稿件分类以及与许多其它业务相关的问题中发挥着重要作用。
目前绝大多数最先进的方法都依赖于一种被称为文本嵌入的技术。它将文本转换成高维空间中的数值表示方式。它可以将文档、语句、单词、字符(取决于我们所嵌入的形式)表示为这个高维空间中的一个向量。
Flair 之所以对 NLP 来说是一个令人兴奋的消息,是因为 Zalando Research 最近发表的一篇论文《Contextual String Embeddings for Sequence Labelling(用于序列标注的上下文相关字符串的嵌入)》,其中涵盖了一种始终优于以前最先进方案的方法。该算法在 Flair 中得到了完整的支持和实现,可以用来构建文本分类器。
1、准备
安装 Flair 需要 Python 3.6,如果你还没有,请点击这里查看安装向导。然后执行 pip 命令安装即可:
pip install flair
上面的命令将安装运行 Flair 所需的所有依赖包,当然也包括了 PyTorch。
2、使用一个预训练的分类模型
最新的 0.4 版本包含了两个预训练的模型,还有一个基于 IMDB 数据集上训练的情感分析模型和“攻击性语言检测”模型(当前仅支持德语)。
使用、下载和存储模型都被整合到了一个单一的方法中,这使得使用预训练模型的整个过程都非常简单。
要使用情感分析模型,只需执行以下代码片段:
fromflair.models import TextClassifier
from flair.data import Sentence
classifier = TextClassifier.load(‘en-sentiment’)
sentence = Sentence(‘Flair is pretty neat!’)
classifier.predict(sentence)
# print sentence with predicted labels
print(‘Sentence above is: ‘, sentence.labels)
当第一次运行时,Flair 将下载情感分析模型,默认情况下将其存储到 home 目录下的.flair 子目录中,这大概得需要几分钟。
上面的代码首先加载必需的库,然后将情感分析模型加载到内存中(必要时先进行下载),接下来可以预测句子“Flair is pretty neat!”的情感数值,按 0 到 1 的区间赋值。最后命令的输出结果是:
The sentence above is: [Positive (1.0)]
就是这么简单!例如,现在你可以将上述代码合并在一个 REST API 中,并提供一个与 Google 的云自然语言 API 的情感分析类似的服务,当在有大量请求的生产环境中使用时,这种分析的成本将会非常的高。
3、训练一个自定义文本分类器
要训练一个自定义的文本分类器,我们首先需要一个标注过的数据集。Flair 的分类数据集格式基于 Facebook 的 FastText 格式。格式要求在每行的开头定义一个或多个标签,以前缀__label__开头。格式如下:
__label__<class_1><text>
__label__<class_2><text>
在本文中,我们将利用 Kaggle 的 Spam Detection 数据集通过 Flair 构建一个垃圾 / 非垃圾的分类器。这个数据集比较适合我们的学习任务,因为它足够小,并且仅包含 5572 行的数据,可以在一个 CPU 上只花几分钟就可以完成一个模型的训练。
来自数据集中的标记为 spam(垃圾邮件)或 ham(非垃圾邮件)的 SMS 信息
3.1 预处理 - 构建数据集
我们首先从 Kaggle 上的这个链接下载数据集来获得 spam.csv 文件。然后,在与数据集相同的目录中,我们运行下面的预处理代码片段,该代码将执行一些预处理,并将数据集拆分为训练集、开发集和测试集三个部分。
确保安装了 Pandas。如果还没有,请先运行命令:
pip install pandas
import pandas as pd
data = pd.read_csv(“./spam.csv”, encoding=’latin-1’).sample(frac=1).drop_duplicates()
data = data[[‘v1’, ‘v2’]].rename(columns={“v1″:”label”, “v2″:”text”})
data[‘label’] = ‘__label__’ + data[‘label’].astype(str)
data.iloc[0:int(len(data)*0.8)].to_csv(‘train.csv’, sep=’\t’, index = False, header = False)
data.iloc[int(len(data)*0.8):int(len(data)*0.9)].to_csv(‘test.csv’, sep=’\t’, index = False, header = False)
data.iloc[int(len(data)*0.9):].to_csv(‘dev.csv’, sep=’\t’, index = False, header = False);
上面的代码将从数据集中删除一些重复数据,并对其进行无序处理(随机化行),并按照 80/10/10 的比例将数据拆分为训练集、开发集和测试集。
如果运行成功,你将会得到 FastText 格式的三个数据文件:train.csv、test.csv 和 dev.csv,它们可以与 Flair 一起使用。
3.2 训练自定义文本分类模型
请在生成数据集的目录中运行以下代码片段用以训练模型:
fromflair.data_fetcher import NLPTaskDataFetcher
from flair.embeddings import WordEmbeddings, FlairEmbeddings, DocumentLSTMEmbeddings
from flair.models import TextClassifier
from flair.trainers import ModelTrainer
from pathlib import Path
corpus = NLPTaskDataFetcher.load_classification_corpus(Path(‘./’), test_file=’test.csv’, dev_file=’dev.csv’, train_file=’train.csv’)
word_embeddings = [WordEmbeddings(‘glove’), FlairEmbeddings(‘news-forward-fast’), FlairEmbeddings(‘news-backward-fast’)]
document_embeddings = DocumentLSTMEmbeddings(word_embeddings, hidden_size=512, reproject_words=True, reproject_words_dimension=256)
classifier = TextClassifier(document_embeddings, label_dictionary=corpus.make_label_dictionary(), multi_label=False)
trainer = ModelTrainer(classifier, corpus)
trainer.train(‘./’, max_epochs=10)
第一次运行上述代码时,Flair 将会自动下载需要的所有嵌入模型,这可能需要几分钟,然后接下来的整个培训过程还需要大约 5 分钟。
程序首先将所需的库和数据集加载到一个 corpus 对象中。
接下来,我们创建一个嵌入列表,包含两个 Flair 上下文的字符串嵌入和一个 GloVe 单词嵌入。然后将此列表作为文档嵌入对象的输入。堆叠和文档嵌入是 Flair 中最有趣的概念之一,提供了将不同的嵌入整合在一起的方法。你可以同时使用传统的单词嵌入(如 GloVe, word2vec, ELMo)和 Flair 上下文的字符串嵌入。在上面的例子中,我们使用了一种基于 LSTM(Long Short-Term Memory,长短期记忆网络)的方法,将单词和上下文的字符串嵌入结合起来以生成文档嵌入。想要了解更多,请点击这里。
最后,上述代码进行模型训练并生成了 final-model.pt 和 best-model.pt 两个文件,它们表示我们存储的训练模型。
3.3 用训练过的模型进行预测
我们现在可以从同一目录通过运行以下代码,使用导出的模型来生成预测结果:
fromflair.models import TextClassifier
from flair.data import Sentence
classifier = TextClassifier.load_from_file(‘./best-model.pt’)
sentence = Sentence(‘Hi. Yes mum, I will…’)
classifier.predict(sentence)
print(sentence.labels)
这段代码会输出“[ham(1.0)]”,这意味着该模型 100% 确定我们的示例消息不是垃圾邮件。
与其它框架相比表现如何?
与 Facebook 的 FastText 甚至谷歌的 AutoML 自然语言平台不同,使用 Flair 进行文本分类仍然是一项底层的工作。我们可以通过设置诸如学习率、批量大小、退火因子(anneal factor)、损失函数、优化选择等参数来完全控制文本嵌入和训练的方式…为了获得最佳表现,需要调整这些超参数。Flair 为我们提供了一个有名的超参数调优库 Hyperopt 的封装器,我们可以使用它来对超参数进行调优以获得最佳的性能。
在本文中,为了简单起见,我们使用了默认的超参数。在大多数默认参数下,我们的 Flair 模型在 10 个训练周期后获得了 0.973 的 f1-score。
为了进行对比,我们使用 FastText 和 AutoML 自然语言平台训练了一个文本分类模型。首先我们使用默认参数运行 FastText,并获得了 0.883 的 f1-score,这意味着模型在很大程度上优于 FastText。然而,FastText 只需要几秒钟的训练时间,而我们训练的 Flair 模型则需要 5 分钟。
我们将结果与在谷歌的 AutoML 自然语言平台上获得的结果进行了比较。平台首先需要 20 分钟来解析数据集。之后,我们开始了训练过程,这几乎花了 3 个小时完成,但却获得了 99.211 的 f1-score——这比我们自己训练的模型稍微好一点。
本文作者:【方向】阅读原文
本文为云栖社区原创内容,未经允许不得转载。