1. 簡介
一個(gè)非常簡單的框架,用于最先進(jìn)的NLP。由Zalando Research開發(fā)。
Flair是什么:
-
強(qiáng)大的語法 - 語義標(biāo)記器/分類器。
Flair允許應(yīng)用先進(jìn)的模型進(jìn)行命名實(shí)體識(shí)別(NER),詞性標(biāo)注(PoS),分塊和分類文本。 -
文本嵌入庫。
Flair具有簡單的界面,允許使用和組合不同的單詞和文檔嵌入。特別是,可以嘗試提出的上下文字符串嵌入來構(gòu)建自己的NLP方法。 -
Pytorch NLP框架。 框架直接在
Pytorch上構(gòu)建,使您可以輕松地訓(xùn)練自己的模型,并使用Flair嵌入和類來嘗試新方法。
其GitHub的項(xiàng)目地址位于: Flair
2. 安裝
Flair安裝需要Python 3.6
直接通過pip install flair即可

如果之前沒有安裝PyTorch,可以先按照官方的說明,通過如下方式安裝(之前PyTorch不支持Windows版本,2018年已經(jīng)支持Windows安裝并應(yīng)用了):
pip3 install https://download.pytorch.org/whl/cu90/torch-1.0.0-cp36-cp36m-win_amd64.whl
pip3 install torchvision
3. Flair的最主要特性 - 基于預(yù)訓(xùn)練模型做遷移學(xué)習(xí)
Flair的最主要特性,是基于預(yù)訓(xùn)練模型做遷移學(xué)習(xí)。
預(yù)訓(xùn)練模型的聲明,集中在:python安裝路徑\Lib\site-packages\flair\embeddings.py中:

由模塊包含的類可以發(fā)現(xiàn)除了基礎(chǔ)的WordEmbedding之外,還有最近的新貴ELMo,甚至Bert。
值得一提的是,所有支持的預(yù)訓(xùn)練模型,都在代碼提供了下載地址,除了Bert之外,預(yù)訓(xùn)練模型都來自AllenNLP: 如:ELMo_2x_1024_128_2048cnn_1xhighway_options
Bert相關(guān)的預(yù)訓(xùn)練模型處理部分,位于:Python安裝路徑\Lib\site-packages\pytorch_pretrained_bert\modeling.py

其也提供了下載地址,如:bert-base-uncased
具體的使用部分,可以參考官方文檔
4. Flair預(yù)訓(xùn)練模型的存放路徑
Flair相關(guān)的目錄存放在登錄用戶的主目錄,如:
Windows位于C:\Users\登錄用戶名\.flair
Linux對(duì)應(yīng)于~/.flair
4.1 除了Bert與Elmo之外的可直接使用模型以及Embedding的存放路徑
4.1.1 可直接使用模型(.pt擴(kuò)展名,即pytorch訓(xùn)練的模型)
- 用法
通過TextClassifier加載模型,如:classifier = TextClassifier.load('en-sentiment') - 模型種類
目前只有兩個(gè):
en-sentiment: 情緒識(shí)別,基于imdb的英文語料訓(xùn)練
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作用一樣,已經(jīng)被其取代
存放于~/.flair/embeddings
4.2 ElMo預(yù)訓(xùn)練模型的存放路徑
ELMo預(yù)訓(xùn)練的模型包括:small, medium兩種,此外還有一個(gè)葡萄牙語的模型。
存放于~/.allennlp/cache
4.3 Bert預(yù)訓(xùn)練模型的存放路徑
Bert預(yù)訓(xùn)練模型的類型:bert-base-uncased, bert-large-uncased,bert-base-cased,bert-base-multilingual,bert-base-chinese
存放于~/.pytorch_pretrained_bert
可以先根據(jù):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",
}
將預(yù)訓(xùn)練模型先下載到本地,如~/.pytorch_pretrained_bert,然后再進(jìn)行使用,否則在國內(nèi)下載速度非常慢。
下載完畢后,現(xiàn)在Flair的版本居然不檢測bert模型存放地址是否已經(jīng)下載,還會(huì)從AWS S3下載,吐血。。。
出于改配置,不改代碼的原則,我們修改配置字典:PRETRAINED_MODEL_ARCHIVE_MAP的bert-base-uncased的值(默認(rèn)對(duì)應(yīng)這個(gè)模型):
'bert-base-uncased': Path.home() / ".pytorch_pretrained_bert/bert-base-uncased.tar.gz"
然后就OK了。
5 使用訓(xùn)練好的預(yù)置分類模型
最新的Flair 0.4版本包含有兩個(gè)預(yù)先訓(xùn)練好的模型。一個(gè)基于IMDB數(shù)據(jù)集訓(xùn)練的情感分析模型和一個(gè)攻擊性語言探測模型(當(dāng)前僅支持德語)。
只需一個(gè)命令就可以下載、存儲(chǔ)并使用模型,這使得預(yù)置模型的使用過程異常簡單。例如,下面的代碼將使用情感分析模型:
當(dāng)?shù)谝淮芜\(yùn)行以下代碼時(shí),F(xiàn)lair將下載情感分析模型,默認(rèn)情況下會(huì)保存到本地用戶主目錄的.flair子目錄,下載可能需要幾分鐘。(作者太皮了,我下載到本地預(yù)估至少用了3個(gè)小時(shí)??!強(qiáng)烈建議先找到需要下載的預(yù)訓(xùn)練模型路徑,通過迅雷等工具,下載下來,并拷貝到對(duì)應(yīng)目錄,從而縮短等待時(shí)間!)
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)
上面的代碼首先載入必要的庫,然后載入情感分析模型到內(nèi)存中(必要時(shí)先下載),接下來就可以預(yù)測“Flair is pretty neat!”的情感分值了(0~1之間)。最后的命令輸入結(jié)果為:
The sentence above is: [Positive (1.0)].
就是這么簡單!現(xiàn)在你可以將上述代碼整合為一個(gè)REST API,提供類似于google云端情感分析API的功能了!
6. 遷移學(xué)習(xí)練習(xí)
使用預(yù)訓(xùn)練模型,并創(chuàng)建自己的分類模型。
要訓(xùn)練一個(gè)自定義的文本分類器,首先需要一個(gè)標(biāo)注文本集。Flair的分類數(shù)據(jù)集格式基于Facebook的FastText格式,要求在每一行的開始使用label前綴定義一個(gè)或多個(gè)標(biāo)簽。格式如下:
__label__<class_1> <text>
__label__<class_2> <text>
在這篇文章中我們將使用Kaggle的SMS垃圾信息檢測數(shù)據(jù)集來用Flair構(gòu)建一個(gè)垃圾/非垃圾分類器。這個(gè)數(shù)據(jù)集很適合我們的學(xué)習(xí)任務(wù),因?yàn)樗苄?,只?572行數(shù)據(jù),可以在單個(gè)CPU上只花幾分鐘就完成模型的訓(xùn)練。
6.1 預(yù)處理 - 構(gòu)建數(shù)據(jù)集
首先下載Kaggle上的數(shù)據(jù)集,得到spam.csv;然后再數(shù)據(jù)集目錄下,運(yùn)行我們的處理腳本,得到訓(xùn)練集、開發(fā)集和測試集:
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)
上面的腳本會(huì)進(jìn)行剔重和隨機(jī)亂序處理,并按照80/10/10的比例進(jìn)行數(shù)據(jù)集的分割。
腳本成功執(zhí)行后,就會(huì)得到FastText格式的三個(gè)數(shù)據(jù)文件:train.csv、dev.csv和test.csv。
如果需要支持多標(biāo)簽分類,標(biāo)簽之間用空格分隔。
最簡單的方式就是通過label標(biāo)簽1 label標(biāo)簽2實(shí)現(xiàn),如下面所示實(shí)現(xiàn)了三標(biāo)簽分類:
__label__add __label__close __label__merge
6.2 訓(xùn)練自定義文本分類模型
這里使用了WordEmbeddings: GloVe作為預(yù)訓(xùn)練模型,不過DocumentLSTMEmbeddings類,是支持Emedding列表的,所以按照如下代碼去定義包含Bert預(yù)訓(xùn)練模型的embedding列表,然后實(shí)例化DocumentLSTMEmbeddings也是可以的:
# BertEmbeddings模型使用base uncase預(yù)訓(xùn)練模型
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作為預(yù)訓(xùn)練模型進(jìn)行遷移學(xué)習(xí)的源碼:
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'))
第一次運(yùn)行上面這個(gè)腳本時(shí),F(xiàn)lair會(huì)自動(dòng)下載所需要的嵌入模型,這可能需要一段時(shí)間(如果預(yù)先下載,并放入上述提到的Embedding的存放路徑,就可以直接訓(xùn)練模型),然后接下來的整個(gè)訓(xùn)練過程還需要大約5分鐘。
腳本首先載入需要的庫和數(shù)據(jù)集,得到一個(gè)corpus對(duì)象。
接下來,我們創(chuàng)建一個(gè)嵌入列表,包含兩個(gè)Flair上下文字符串嵌入和一個(gè)GloVe單詞嵌入,這個(gè)列表接下來將作為我們文檔嵌入對(duì)象的輸入。
具體訓(xùn)練的截圖如下:

堆疊和文本嵌入是Flair中最有趣的感念之一,它們提供了將不同的嵌入整合在一起的手段,你可以同時(shí)使用單詞嵌入(例如GloVe、word2vector、ELMo,Bert)和Flair的上下文字符串嵌入。
在上面的示例中我們使用一個(gè)基于LSTM的方法來生成文檔嵌入,關(guān)于該方法的詳細(xì)描述可以參考這里。
下面進(jìn)行簡單的垃圾信息預(yù)測,簡直是驚天地泣鬼神的簡易:
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)]
值得一提的是,經(jīng)過加載預(yù)處理的GloVe單詞嵌入生成的模型非常大,即使是Spam這種只有幾千句,492K的訓(xùn)練集,生成的模型,也有200多M,至少比嵌入的預(yù)訓(xùn)練模型要大一丟丟。(通過Bert Base預(yù)訓(xùn)練模型進(jìn)行遷移學(xué)習(xí),訓(xùn)練得到的模型將近500M)
