歡迎光臨
每天分享高質量文章

使用 Bert 預訓練模型文本分類(內附原始碼)

(給資料分析與開發加星標,提升資料技能

作者:GjZero,轉自:資料派(ID:datapi)

Bert介紹

 

Bert模型是Google在2018年10月發佈的語言表示模型,Bert在NLP領域橫掃了11項任務的最優結果,可以說是現今最近NLP中最重要的突破。Bert模型的全稱是Bidirectional Encoder Representations from Transformers,是通過訓練Masked Language Model和預測下一句任務得到的模型。關於Bert具體訓練的細節和更多的原理,有興趣的讀者可以去看在[arXiv](https://arxiv.org/abs/1810.04805)上的原文。本篇文章從實踐入手,帶領大家進行Bert的中文文本分類和作為句子向量進行使用的教程。

 

 

對於文本分類任務,一個句子中的N個字符對應了E_1,…,E_N,這N個embedding。文本分類實際上是將BERT得到的T_1這一層連接上一個全連接層進行多分類。

 

準備工作

 

1. 下載bert

 

在命令列中輸入

 

git clone 
https://github.com/google-research/bert.git

 

2. 下載bert預訓練模型

 

Google提供了多種預訓練好的bert模型,有針對不同語言的和不同模型大小的。對於中文模型,我們使用[Bert-Base, Chinese](https://storage.googleapis.com/bert_models/2018_11_03/chinese_L-12_H-768_A-12.zip)。為了下載該模型,可能需要使用梯子。如果需要下載其他的模型(英文以及其他語言),可以在[Bert](https://github.com/google-research/bert)里的Pre-trained models找到下載鏈接。

 

3.(可選項)

 

安裝bert-as-service,這是一個可以利用bert模型將句子映射到固定長度向量的服務。

 

在命令列中輸入

 

pip install bert-serving-server # server

pip install bert-serving-client # client, independent of 'bert-serving-server'

 

該服務要求tensorflow的最低版本為1.10。

 

準備資料

 

資料格式

 

作為中文文本分類問題,需要先將資料集整理成可用的形式。不同的格式對應了不同的DataProcessor類。可以將資料儲存成如下格式:

 

game APEX是個新出的吃雞游戲。

technology  Google將要推出tensorflow2.0。

 

一行代表一個文本,由標簽加上一個tab加上正文組成。

 

將文本分割為三個檔案,train.tsv(訓練集),dev.tsv(驗證集),test.tsv(測試集);然後放置在同一個data_dir檔案夾下。

 

編寫DataProcessor類

 

在bert檔案夾下的“run_classifier.py**中的”def main(_):”函式中將processors的內容增加為

 

python

processors = {

     "cola": ColaProcessor,

     "mnli": MnliProcessor,

     "mrpc": MrpcProcessor,

     "xnli": XnliProcessor,

     "mytask": MyTaskProcessor,

 }

 

實現如下的“MyTaskProcessor

 

(DataProcessor)”類,並將這一段代碼放置在“run_classifier.py”和其他Processor併列的位置。

 

“\_\_init\_\_(self)”中的self.labels含有所有的分類label,在這個例子中我們將文本可能分為3類:game, fashion, houseliving。

 

python

class MyTaskProcessor(DataProcessor):

   """Processor for the News data set (GLUE version)."""

   def __init__(self):

       self.labels = ['game', 'fashion', 'houseliving']

   

   def get_train_examples(self, data_dir):

       return self._create_examples(

           self._read_tsv(os.path.join(data_dir, "train.tsv")), "train")

   def get_dev_examples(self, data_dir):

       return self._create_examples(

           self._read_tsv(os.path.join(data_dir, "dev.tsv")), "dev")

   

   def get_test_examples(self, data_dir):

     return self._create_examples(

         self._read_tsv(os.path.join(data_dir, "test.tsv")), "test")

   def get_labels(self):

       return self.labels

   def _create_examples(self, lines, set_type):

       """Creates examples for the training and dev sets."""

       examples = []

       for (i, line) in enumerate(lines):

           guid = "%s-%s" % (set_type, i)

           text_a = tokenization.convert_to_unicode(line[1])

           label = tokenization.convert_to_unicode(line[0])

           examples.append(

               InputExample(guid=guid, text_a=text_a, text_b=None, label=label))

       return examples

 

如果資料格式並不是一個label,一個tab,一段文本;則需要更改“_create_examples()”的實現。

 

編寫運行腳本

 

新建一個運行腳本檔案名為“run.sh”,將檔案內容編輯為:

 

bash

export DATA_DIR=/media/ganjinzero/Code/bert/data/

export BERT_BASE_DIR=/media/ganjinzero/Code/bert/chinese_L-12_H-768_A-12

python run_classifier.py \

 --task_name=mytask \

 --do_train=true \

 --do_eval=true \

 --data_dir=$DATA_DIR/ \

 --vocab_file=$BERT_BASE_DIR/vocab.txt \

 --bert_config_file=$BERT_BASE_DIR/bert_config.json \

 --init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \

 --max_seq_length=128 \

 --train_batch_size=32 \

 --learning_rate=2e-5 \

 --num_train_epochs=3.0 \

 --output_dir=/mytask_output

 

其中DATA_DIR是你的要訓練的文本的資料所在的檔案夾,BERT_BASE_DIR是你的bert預訓練模型存放的地址。task_name要求和你的DataProcessor類中的名稱一致。下麵的幾個引數,do_train代表是否進行fine tune,do_eval代表是否進行evaluation,還有未出現的引數do_predict代表是否進行預測。如果不需要進行fine tune,或者顯卡配置太低的話,可以將do_trian去掉。max_seq_length代表了句子的最長長度,當顯存不足時,可以適當降低max_seq_length。

 

進行預測

 

運行腳本

 

bash
./run.sh

 

可以得到類似如下樣式的結果

 

***** Eval results *****

 eval_accuracy = 0.845588

 eval_loss = 0.505248

 global_step = 343

 loss = 0.505248

 

如果出現了這樣的輸出,就是運行成功了。在“run.sh”里指定的output_dir檔案夾下可以看到模型的evaluation結果和fine-tune(微調)之後的模型檔案。

 

以句子向量的形式使用Bert

 

如果想要將bert模型的編碼和其他模型一起使用,將bert模型作為句子向量使用很有意義(也就是所謂的句子級別的編碼)。我們可以使用bert-as-service來完成這個標的。

 

安裝完bert-as-service以後,就可以利用bert模型將句子映射到固定長度的向量上。在終端中用一下命令啟動服務:

 

bash

bert-serving-start -model_dir /media/ganjinzero/Code/bert/chinese_L-12_H-768_A-12 -num_worker=4

 

model_dir後面的引數是bert預訓練模型所在的檔案夾。num_worker的數量應該取決於你的CPU/GPU數量。

 

這時就可以在Python中呼叫如下的命令:

 

python

from bert_serving.client import BertClient

bc = BertClient()

bc.encode(['一二三四五六七八', '今天您吃了嗎?'])

 

最好以串列的形式,而非單個字串傳給”bc.encode()”引數,這樣程式運行的效率較高。

 

參考文件

 

[Github:bert]

(https://github.com/google-research/bert)

 

[arXiv:bert]

(https://arxiv.org/pdf/1810.04805.pdf)

 

[Github:bert-as-service]

(https://github.com/hanxiao/bert-as-service)

赞(0)

分享創造快樂