1. 程式人生 > >用最新NLP庫Flair做文字分類

用最新NLP庫Flair做文字分類

a1a7ac947dc9545462907b18b489ba4d33cdfbf8

介紹

文字分類是一種監督機器學習方法,用於將句子或文字文件歸類為一個或多個已定義好的類別。它是一個被廣泛應用的自然語言處理方法,在垃圾郵件過濾、情感分析、新聞稿件分類以及與許多其它業務相關的問題中發揮著重要作用。

目前絕大多數最先進的方法都依賴於一種被稱為文字嵌入的技術。它將文字轉換成高維空間中的數值表示方式。它可以將文件、語句、單詞、字元(取決於我們所嵌入的形式)表示為這個高維空間中的一個向量。

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的情感數值,按01的區間賦值。最後命令的輸出結果是:

The sentence above is: [Positive (1.0)]

就是這麼簡單!例如,現在你可以將上述程式碼合併在一個REST API中,並提供一個與Google的雲自然語言API的情感分析類似的服務,當在有大量請求的生產環境中使用時,這種分析的成本將會非常的高。

3、訓練一個自定義文字分類器

要訓練一個自定義的文字分類器,我們首先需要一個標註過的資料集。Flair的分類資料集格式基於FacebookFastText格式。格式要求在每行的開頭定義一個或多個標籤,以字首__label__開頭。格式如下:

__label__<class_1><text>
__label__<class_2><text>

在本文中,我們將利用KaggleSpam Detection資料集通過Flair構建一個垃圾/非垃圾的分類器。這個資料集比較適合我們的學習任務,因為它足夠小,並且僅包含5572行的資料,可以在一個CPU上只花幾分鐘就可以完成一個模型的訓練。

60323e2f8bcf600ecae6834203305036681c5deb

來自資料集中的標記為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.csvtest.csvdev.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上下文的字串嵌入。在上面的例子中,我們使用了一種基於LSTMLong Short-Term Memory,長短期記憶網路)的方法,將單詞和上下文的字串嵌入結合起來以生成文件嵌入。想要了解更多,請點選這裡

最後,上述程式碼進行模型訓練並生成了final-model.ptbest-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)

這段程式碼會輸出“[ham1.0]”,這意味著該模型100%確定我們的示例訊息不是垃圾郵件。

與其它框架相比表現如何?

FacebookFastText甚至谷歌的AutoML自然語言平臺不同,使用Flair進行文字分類仍然是一項底層的工作。我們可以通過設定諸如學習率、批量大小、退火因子(anneal factor)、損失函式、優化選擇等引數來完全控制文字嵌入和訓練的方式為了獲得最佳表現,需要調整這些超引數。Flair為我們提供了一個有名的超引數調優庫Hyperopt的封裝器,我們可以使用它來對超引數進行調優以獲得最佳的效能。

在本文中,為了簡單起見,我們使用了預設的超引數。在大多數預設引數下,我們的Flair模型在10個訓練週期後獲得了0.973f1-score

為了進行對比,我們使用FastTextAutoML自然語言平臺訓練了一個文字分類模型。首先我們使用預設引數執行FastText,並獲得了0.883f1-score,這意味著模型在很大程度上優於FastText。然而,FastText只需要幾秒鐘的訓練時間,而我們訓練的Flair模型則需要5分鐘。

我們將結果與在谷歌的AutoML自然語言平臺上獲得的結果進行了比較。平臺首先需要20分鐘來解析資料集。之後,我們開始了訓練過程,這幾乎花了3個小時完成,但卻獲得了99.211f1-score——這比我們自己訓練的模型稍微好一點。

本文由北郵@愛可可-愛生活 老師推薦,阿里云云棲社群組織翻譯。

文章原標題《GANs as a loss function

譯者:Mags,審校:袁虎。

文章為簡譯,更為詳細的內容,請檢視原文