1. 简介
一个非常简单的框架,用于最先进的NLP
。由Zalando Research开发。
Flair是什么:
-
强大的语法 - 语义标记器/分类器。
Flair
允许应用先进的模型进行命名实体识别(NER),词性标注(PoS),分块和分类文本。 -
文本嵌入库。
Flair
具有简单的界面,允许使用和组合不同的单词和文档嵌入。特别是,可以尝试提出的上下文字符串嵌入来构建自己的NLP
方法。 -
Pytorch NLP框架。 框架直接在
Pytorch
上构建,使您可以轻松地训练自己的模型,并使用Flair
嵌入和类来尝试新方法。
其GitHub的项目地址位于: Flair
2. 安装
Flair安装需要Python 3.6
直接通过pip install flair即可
如果之前没有安装PyTorch,可以先按照官方的说明,通过如下方式安装(之前PyTorch不支持Windows版本,2018年已经支持Windows安装并应用了):
pip3 install https://download.pytorch.org/whl/cu90/torch-1.0.0-cp36-cp36m-win_amd64.whl
pip3 install torchvision
3. Flair的最主要特性 - 基于预训练模型做迁移学习
Flair的最主要特性,是基于预训练模型做迁移学习。
预训练模型的声明,集中在:python安装路径\Lib\site-packages\flair\embeddings.py中:
由模块包含的类可以发现除了基础的WordEmbedding之外,还有最近的新贵ELMo,甚至Bert。
值得一提的是,所有支持的预训练模型,都在代码提供了下载地址,除了Bert之外,预训练模型都来自AllenNLP: 如:ELMo_2x_1024_128_2048cnn_1xhighway_options
Bert相关的预训练模型处理部分,位于:Python安装路径\Lib\site-packages\pytorch_pretrained_bert\modeling.py
其也提供了下载地址,如:bert-base-uncased
具体的使用部分,可以参考官方文档
4. Flair预训练模型的存放路径
Flair相关的目录存放在登录用户的主目录,如:
Windows位于C:\Users\登录用户名\.flair
Linux对应于~/.flair
4.1 除了Bert与Elmo之外的可直接使用模型以及Embedding的存放路径
4.1.1 可直接使用模型(.pt扩展名,即pytorch训练的模型)
- 用法
通过TextClassifier加载模型,如:classifier = TextClassifier.load('en-sentiment') - 模型种类
目前只有两个:
en-sentiment: 情绪识别,基于imdb的英文语料训练
de-offensive-language:基于德语的是否有攻击语言判断分类
存放于~/.flair/models
4.1.2 Embedding
- WordEmbeddings,包括:GloVe, EXTVec, Crawl, Twitter, Wiki,
- FlairEmbeddings, 包括:
multilingual forward (English, German, French, Italian, Dutch, Polish)
multilingual backward (English, German, French, Italian, Dutch, Polish)
multilingual forward fast (English, German, French, Italian, Dutch, Polish)
multilingual backward fast (English, German, French, Italian, Dutch, Polish)
news-english-forward
news-english-backward
news-english-forward-fast
news-english-backward-backward
mix-english-forward
mix-english-backward
mix-german-forward
mix-german-backward
common crawl Polish forward
common crawl Polish backward
Slovenian forward
Slovenian backward
Bulgarian forward
Bulgarian backward
Dutch forward
Dutch backward
Swedish forward
Swedish backward
French forward
French backward
Czech forward
Czech backward
Portuguese forward
Portuguese backward - CharLMEmbeddings:即将被去除,与FlairEmbeddings作用一样,已经被其取代
存放于~/.flair/embeddings
4.2 ElMo预训练模型的存放路径
ELMo预训练的模型包括:small, medium两种,此外还有一个葡萄牙语的模型。
存放于~/.allennlp/cache
4.3 Bert预训练模型的存放路径
Bert预训练模型的类型:bert-base-uncased, bert-large-uncased,bert-base-cased,bert-base-multilingual,bert-base-chinese
存放于~/.pytorch_pretrained_bert
可以先根据:Python安装路径\Lib\site-packages\pytorch_pretrained_bert\modeling.py中的PRETRAINED_MODEL_ARCHIVE_MAP所声明的路径:
PRETRAINED_MODEL_ARCHIVE_MAP = {
'bert-base-uncased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-uncased.tar.gz",
'bert-large-uncased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-uncased.tar.gz",
'bert-base-cased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-cased.tar.gz",
'bert-large-cased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-large-cased.tar.gz",
'bert-base-multilingual-uncased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-uncased.tar.gz",
'bert-base-multilingual-cased': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-multilingual-cased.tar.gz",
'bert-base-chinese': "https://s3.amazonaws.com/models.huggingface.co/bert/bert-base-chinese.tar.gz",
}
将预训练模型先下载到本地,如~/.pytorch_pretrained_bert,然后再进行使用,否则在国内下载速度非常慢。
下载完毕后,现在Flair的版本居然不检测bert模型存放地址是否已经下载,还会从AWS S3下载,吐血。。。
出于改配置,不改代码的原则,我们修改配置字典:PRETRAINED_MODEL_ARCHIVE_MAP的bert-base-uncased的值(默认对应这个模型):
'bert-base-uncased': Path.home() / ".pytorch_pretrained_bert/bert-base-uncased.tar.gz"
然后就OK了。
5 使用训练好的预置分类模型
最新的Flair 0.4版本包含有两个预先训练好的模型。一个基于IMDB数据集训练的情感分析模型和一个攻击性语言探测模型(当前仅支持德语)。
只需一个命令就可以下载、存储并使用模型,这使得预置模型的使用过程异常简单。例如,下面的代码将使用情感分析模型:
当第一次运行以下代码时,Flair将下载情感分析模型,默认情况下会保存到本地用户主目录的.flair子目录,下载可能需要几分钟。(作者太皮了,我下载到本地预估至少用了3个小时!!强烈建议先找到需要下载的预训练模型路径,通过迅雷等工具,下载下来,并拷贝到对应目录,从而缩短等待时间!)
from flair.models import TextClassifier
from flair.data import Sentence
print('load en-sentiment begin')
classifier = TextClassifier.load('en-sentiment')
print('load en-sentiment end')
sentence = Sentence('Flair is pretty neat!')
print('load predict begin')
classifier.predict(sentence)
print('load predict end')
# print sentence with predicted labels
print('Sentence above is: ', sentence.labels)
上面的代码首先载入必要的库,然后载入情感分析模型到内存中(必要时先下载),接下来就可以预测“Flair is pretty neat!”的情感分值了(0~1之间)。最后的命令输入结果为:
The sentence above is: [Positive (1.0)].
就是这么简单!现在你可以将上述代码整合为一个REST API,提供类似于google云端情感分析API的功能了!
6. 迁移学习练习
使用预训练模型,并创建自己的分类模型。
要训练一个自定义的文本分类器,首先需要一个标注文本集。Flair的分类数据集格式基于Facebook的FastText格式,要求在每一行的开始使用label前缀定义一个或多个标签。格式如下:
__label__<class_1> <text>
__label__<class_2> <text>
在这篇文章中我们将使用Kaggle的SMS垃圾信息检测数据集来用Flair构建一个垃圾/非垃圾分类器。这个数据集很适合我们的学习任务,因为它很小,只有5572行数据,可以在单个CPU上只花几分钟就完成模型的训练。
6.1 预处理 - 构建数据集
首先下载Kaggle上的数据集,得到spam.csv;然后再数据集目录下,运行我们的处理脚本,得到训练集、开发集和测试集:
import pandas as pd
# The frac keyword argument specifies the fraction of rows to return in the random sample,
# so frac=1 means return all rows (in random order).
data = pd.read_csv("./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('./csv/spamtrain.csv', sep='\t', index = False, header = False)
data.iloc[int(len(data)*0.8):int(len(data)*0.9)].to_csv('./csv/spamtest.csv', sep='\t', index = False, header = False)
data.iloc[int(len(data)*0.9):].to_csv('./csv/spamdev.csv', sep='\t', index = False, header = False)
上面的脚本会进行剔重和随机乱序处理,并按照80/10/10的比例进行数据集的分割。
脚本成功执行后,就会得到FastText格式的三个数据文件:train.csv、dev.csv和test.csv。
如果需要支持多标签分类,标签之间用空格分隔。
最简单的方式就是通过label标签1 label标签2实现,如下面所示实现了三标签分类:
__label__add __label__close __label__merge
6.2 训练自定义文本分类模型
这里使用了WordEmbeddings: GloVe作为预训练模型,不过DocumentLSTMEmbeddings类,是支持Emedding列表的,所以按照如下代码去定义包含Bert预训练模型的embedding列表,然后实例化DocumentLSTMEmbeddings也是可以的:
# BertEmbeddings模型使用base uncase预训练模型
word_embeddings = [BertEmbeddings(),
FlairEmbeddings('news-forward-fast'),
FlairEmbeddings('news-backward-fast')]
document_embeddings = DocumentLSTMEmbeddings(word_embeddings,
hidden_size=512,
reproject_words=True,
reproject_words_dimension=256,
bidirectional=True)
通过GloVe作为预训练模型进行迁移学习的源码:
from flair.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
import os
if not os.path.exists('./nlpmodel/flair/spam/best-model.pt'):
corpus = NLPTaskDataFetcher.load_classification_corpus(Path('./csv'),
test_file='spamtrain.csv',
dev_file='spamdev.csv',
train_file='spamtest.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('./nlpmodel/flair/spam', max_epochs=20)
else:
print('model: {0} existed!'.format('./nlpmodel/flair/spam/best-model.pt'))
第一次运行上面这个脚本时,Flair会自动下载所需要的嵌入模型,这可能需要一段时间(如果预先下载,并放入上述提到的Embedding的存放路径,就可以直接训练模型),然后接下来的整个训练过程还需要大约5分钟。
脚本首先载入需要的库和数据集,得到一个corpus对象。
接下来,我们创建一个嵌入列表,包含两个Flair上下文字符串嵌入和一个GloVe单词嵌入,这个列表接下来将作为我们文档嵌入对象的输入。
具体训练的截图如下:
堆叠和文本嵌入是Flair中最有趣的感念之一,它们提供了将不同的嵌入整合在一起的手段,你可以同时使用单词嵌入(例如GloVe、word2vector、ELMo,Bert)和Flair的上下文字符串嵌入。
在上面的示例中我们使用一个基于LSTM的方法来生成文档嵌入,关于该方法的详细描述可以参考这里。
下面进行简单的垃圾信息预测,简直是惊天地泣鬼神的简易:
classifier = TextClassifier.load_from_file('./nlpmodel/flair/spam/best-model.pt')
textlist= ["Hi. Yes mum, I will...",
"Want 2 get laid tonight? Want real Dogging locations sent direct 2 ur mob? Join the UK's largest Dogging Network bt Txting GRAVEL to 69888! Nt. ec2a. 31p.msg@150p"
]
for text in textlist:
sentence = Sentence(text)
classifier.predict(sentence)
print('Text: {0} is belong to: {1}'.format(text, sentence.labels))
输入大致如下:
Text: Hi. Yes mum, I will... is belong to: [ham (1.0)]
Text: Want 2 get laid tonight? Want real Dogging locations sent direct 2 ur mob? Join the UK's largest Dogging Network bt Txting GRAVEL to 69888! Nt. ec2a. 31p.msg@150p is belong to: [spam (1.0)]
值得一提的是,经过加载预处理的GloVe单词嵌入生成的模型非常大,即使是Spam这种只有几千句,492K的训练集,生成的模型,也有200多M,至少比嵌入的预训练模型要大一丢丢。(通过Bert Base预训练模型进行迁移学习,训练得到的模型将近500M)