NLP(十四):Simple-Transformers—用BERT,RoBERTa,XLNet,XLM和DistilBERT文本分類


https://zhuanlan.zhihu.com/p/87760325

https://zhuanlan.zhihu.com/p/89232880

一、前言

Simple Transformers是Hugging Face在的Transformers庫的基礎上構建的。 Hugging Face Transformers庫是供研究人員和其他需要全面控制操作方式的人員使用的庫。 當需要偏離常規,做不同的事情或完全做新的事情時,它也是最佳選擇。 比如NLP中得多分類任務,下面根據我的簡單測試,一起看看。

二、介紹

Simple Transformers專為一些特殊得NLP任務設計得。文本分類非常普遍,如今再NLP任務中也不算比較難的任務了。 Simple Transformers就是這么想的,在這里就是要做到這一點!

所有源代碼都可以在Github Repo上找到。

安裝

  1. 這里安裝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

安裝simpletransformers。

用法

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

下載並提取數據

  1. 從Fast.ai下載數據集。(國內用戶需要FQ下載)
  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的預訓練模型的完整列表,請參閱“當前預訓練模型”。

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

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

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

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方法將在第n個步驟(其中n為self.args ['save_steps'])的第n個步驟創建模型的檢查點(保存)。 訓練完成后,最終模型將保存到self.args ['output_dir']。

驗證:

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

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

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

model_outputs:評估數據集中每個項目的模型輸出列表。 如果需要每個類別的概率而不是單個預測,這很有用。 通過對輸出應用softmax函數來計算預測。

錯誤的預測:每個錯誤預測的InputFeature列表。 可以從InputFeature.text_a屬性獲取文本。 (可以在存儲庫的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}

這個結果是我沒有做任務超參的調整。。。。

預測/測試

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

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

結論

在許多實際應用中,多類分類是常見的NLP任務。 Simple Transformers是將Transformers的功能應用於現實世界任務的一種輕松方法,建議大家開始嘗試。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM