Simple Transformer:用BERT、RoBERTa、XLNet、XLM和DistilBERT進行多類文本分類

  • 2019 年 10 月 31 日
  • 筆記

作者 | Thilina Rajapakse

譯者 | Raku

編輯 | 夕顏

【導讀】本文將介紹一個簡單易操作的Transformers庫——Simple Transformers庫。它是AI創業公司Hugging Face在Transformers庫的基礎上構建的。Hugging Face Transformers是供研究與其他需要全面控制操作方式的人員使用的庫,簡單易操作。

簡介

Simple Transformers專為需要簡單快速完成某項工作而設計。不必拘泥於源程式碼,也不用費時費力地去弄清楚各種設置,文本分類應該非常普遍且簡單——Simple Transformers就是這麼想的,並且專為此實現。

一行程式碼建立模型,另一行程式碼訓練模型,第三行程式碼用來預測,老實說,還能比這更簡單嗎?

所有源程式碼都可以在Github Repo上找到,如果你有任何問題或疑問,請在這上面自行尋求答案。

GitHub repo:

https://github.com/ThilinaRajapakse/simpletransformers

安裝

1、從這裡(https://www.anaconda.com/distribution/)安裝Anaconda或Miniconda Package Manager。

2、創建一個新的虛擬環境並安裝所需的包。

conda create -n transformers python pandas tqdm  conda activate transformers

如果是cuda:

conda install pytorch cudatoolkit=10.0 -c pytorch

其他:

conda install pytorch cpuonly -c pytorch  conda install -c anaconda scipy  conda install -c anaconda scikit-learn  pip install transformers  pip install tensorboardx

3、安裝simpletransformers。

pip install simpletransformers

用法

讓我們看看如何對AGNews數據集執行多類分類。

對於用Simple Transformers簡單二分類,參考這裡。

下載並提取數據

1、從Fast.ai(https://s3.amazonaws.com/fast-ai-nlp/ag_news_csv.tgz)下載數據集。

2、提取train.csv和test.csv並將它們放在目錄data/ 中。

為訓練準備數據

import pandas as pd        train_df = pd.read_csv('data/train.csv', header=None)    train_df['text'] = train_df.iloc[:, 1] + " " + train_df.iloc[:, 2]    train_df = train_df.drop(train_df.columns[[1, 2]], axis=1)    train_df.columns = ['label', 'text']    train_df = train_df[['text', 'label']]    train_df['text'] = train_df['text'].apply(lambda x: x.replace('\', ' '))        eval_df = pd.read_csv('data/test.csv', header=None)    eval_df['text'] = eval_df.iloc[:, 1] + " " + eval_df.iloc[:, 2]    eval_df = eval_df.drop(eval_df.columns[[1, 2]], axis=1)    eval_df.columns = ['label', 'text']    eval_df = eval_df[['text', 'label']]    eval_df['text'] = eval_df['text'].apply(lambda x: x.replace('\', ' '))    eval_df['label'] = eval_df['label'].apply(lambda x:x-1

Simple Transformers要求數據必須包含在至少兩列的Pandas DataFrames中。你只需為列的文本和標籤命名,SimpleTransformers就會處理數據。或者你也可以遵循以下約定:

• 第一列包含文本,類型為str。

• 第二列包含標籤,類型為int。

對於多類分類,標籤應該是從0開始的整數。如果數據具有其他標籤,則可以使用python dict保留從原始標籤到整數標籤的映射。

模型

from simpletransformers.model import TransformerModel        # Create a TransformerModel    model = TransformerModel('roberta', 'roberta-base', num_labels=4)

這將創建一個TransformerModel,用於訓練,評估和預測。第一個參數是model_type,第二個參數是model_name,第三個參數是數據中的標籤數:

• model_type可以是['bert','xlnet','xlm','roberta','distilbert']之一。

• 有關可用於model_name的預訓練模型的完整列表,請參閱「當前預訓練模型」(https://github.com/ThilinaRajapakse/simpletransformers#current-pretrained-models)。

要載入以前保存的模型而不是默認模型的模型,可以將model_name更改為包含已保存模型的目錄的路徑。

model = TransformerModel('xlnet', 'path_to_model/', num_labels=4)

TransformerModel具有dict參數,其中包含許多屬性,這些屬性提供對超參數的控制。有關每個屬性的詳細說明,請參閱repo。默認值如下所示:

self.args = {        'output_dir': 'outputs/',        'cache_dir': 'cache_dir',          'fp16': True,        'fp16_opt_level': 'O1',        'max_seq_length': 128,        'train_batch_size': 8,        'gradient_accumulation_steps': 1,        'eval_batch_size': 8,        'num_train_epochs': 1,        'weight_decay': 0,        'learning_rate': 4e-5,        'adam_epsilon': 1e-8,        'warmup_ratio': 0.06,        'warmup_steps': 0,        'max_grad_norm': 1.0,          'logging_steps': 50,        'save_steps': 2000,          'overwrite_output_dir': False,        'reprocess_input_data': False,        'process_count': cpu_count() - 2 if cpu_count() > 2 else 1,        }

在創建TransformerModel或調用其train_model方法時,只要簡單地傳遞包含要更新的鍵值對的字典,就可以修改這些屬性中的任何一個。下面給出一個例子:

# Create a TransformerModel with modified attributes  model = TransformerModel('roberta', 'roberta-base', num_labels=4,  args={'learning_rate':1e-5, 'num_train_epochs': 2,  'reprocess_input_data': True, 'overwrite_output_dir': True})

訓練

# Train the model  model.train_model(train_df)

這就是訓練模型所需要做的全部。你還可以通過將包含相關屬性的字典傳遞給train_model方法來更改超參數。請注意,即使完成訓練,這些修改也將保留。

train_model方法將在第n個步驟(其中n為self.args ['save_steps'])的第n個步驟創建模型的檢查點(保存)。訓練完成後,最終模型將保存到self.args ['output_dir']。

評估

result, model_outputs, wrong_predictions = model.eval_model(eval_df)

要評估模型,只需調用eval_model。此方法具有三個返回值:

• result:dict形式的評估結果。默認情況下,僅對多類分類計算馬修斯相關係數(MCC)。

• model_outputs:評估數據集中每個項目的模型輸出list。用softmax函數來計算預測值,輸出 每個類別的概率而不是單個預測。

• wrong_predictions:每個錯誤預測的InputFeature list。可以從InputFeature.text_a屬性獲取文本。(可以在存儲庫 https://github.com/ThilinaRajapakse/simpletransformers 的utils.py文件中找到InputFeature類)

你還可以包括在評估中要使用的其他指標。只需將指標函數作為關鍵字參數傳遞給eval_model方法。指標功能應包含兩個參數,第一個是真實標籤,第二個是預測,這遵循sklearn標準。

對於任何需要附加參數的度量標準函數(在sklearn中為f1_score),你可以在添加了附加參數的情況下將其包裝在自己的函數中,然後將函數傳遞給eval_model。

from sklearn.metrics import f1_score, accuracy_score    def f1_multiclass(labels, preds):        return f1_score(labels, preds, average='micro')    result, model_outputs, wrong_predictions = model.eval_model(eval_df, f1=f1_multiclass, acc=accuracy_score

作為參考,我使用這些超參數獲得的結果如下:

{'mcc': 0.937104098029913, 'f1': 0.9527631578947369, 'acc': 0.9527631578947369}

考慮到我實際上並沒有進行任何超參數調整,效果還不錯。感謝RoBERTa!

預測/測試

在實際應用中,我們常常不知道什麼是真正的標籤。要對任意示例執行預測,可以使用predict方法。此方法與eval_model方法非常相似,不同之處在於,該方法採用簡單的文本列表並返回預測列表和模型輸出列表。

predictions, raw_outputs = model.predict(['Some arbitary sentence'])

結論

在許多實際應用中,多分類是常見的NLP任務,Simple Transformers是將Transformers的功能應用於現實世界任務的一種簡單方法,你無需獲得博士學位才能使用它。

關於項目

我計劃在不久的將來將「問答」添加到Simple Transformers 庫中。敬請關注!

Simple Transformers 庫:https://github.com/ThilinaRajapakse/simpletransformers

原文鏈接:https://medium.com/swlh/simple-transformers-multi-class-text-classification-with-bert-roberta-xlnet-xlm-and-8b585000ce3a