「NLP-NER」如何使用BERT來做命名實體識別

AIBigbull2050發表於2019-09-29

命名實體識別(Named Entity Recognition,NER)是NLP中一項非常基礎的任務。NER是資訊提取、問答系統、句法分析、機器翻譯等眾多NLP任務的重要基礎工具。

上一期我們詳細介紹NER中兩種深度學習模型,LSTM+CRF和Dilated-CNN,本期我們來介紹如何基於BERT來做命名實體識別任務。

作者 | 小Dream哥

編輯 | 言有三

1 引入BERT

筆者在之前的文章中介紹過BERT,想要回顧的同學可以點選下面的連結,這裡就不再介紹BERT的結構了。

「NLP」 如何深入淺出解析BERT原理及其表徵的內容

鑑於BERT的強大,在下游任務中,引入BERT是很自然的想法。像谷歌這些資源豐富的大佬,幫我們預訓練好了模型,並且開源出來,當然要好好利用。這裡就介紹下,如何基於谷歌開源出來的BERT base模型,進行fine tune,做NER任務。

2 獲取BERT預訓練模型

BERT原始碼可以從google-research的github中獲取:



在其GitHub中,也公佈了獲取BERT Chinese的預訓練模型,正是我們需要的,連結如下:



對下載的壓縮檔案進行解壓,可以看到檔案裡有五個檔案,其中bert_model.ckpt開頭的檔案是負責模型變數載入的,而vocab.txt是訓練時中文文字採用的字典,最後bert_config.json是BERT在訓練時,可選調整的一些引數。

BERT的程式碼主要分為兩個部分:

1.預訓練部分,其入口是在run_pretraining.py。

2.Fine-tune部分。Fine-tune的入口針對不同的任務分別在run_classifier.py和run_squad.py。其中run_classifier.py適用的任務為分類任務,如CoLA、MRPC、MultiNLI等。而run_squad.py適用的是閱讀理解任務,如squad2.0和squad1.1。

那麼NER的任務該怎麼辦呢?那就需要自己動手做一些處理了。NER任務與分類任務很接近,基於run_classsifier.py做一些修改,就能夠快速實現我們NER任務的Fine-tune了,下面我們看看,大致需要做哪些修改的工作。

3 修改 processor

任何模型的訓練、預測都是需要有一個明確的輸入,而BERT程式碼中processor就是負責對模型的輸入進行處理。

在run_classsifier.py檔案中我們可以看到,Google對於一些公開資料集已經寫了一些processor,如XnliProcessor,MnliProcessor,MrpcProcessor和ColaProcessor。這給我們提供了一個很好的示例,指導我們如何針對自己的資料集來寫processor。

參照上述的Processor,結合NER任務的特點,我們需要定義一個NerProcessor來處理NER標記語料,主要的工作就是將語料組織成Estimator能夠接受的格式。主要就是實現_read_data,_create_example和get_labels三個函式,具體需要組織成什麼樣的形式,可以看看原始碼。

我們可以實現如下形式的_create_example函式,它讀取語料和標記,並且透過InputExample函式,構造成Estimator能夠接受的格式。

def _create_example(self, lines, set_type):

examples = []
for (i, line) in enumerate(lines):
guid = "%s-%s" % (set_type, i)
text = tokenization.convert_to_unicode(line[1])
label = tokenization.convert_to_unicode(line[0])
examples.append(InputExample(guid=guid, text=text, label=label))
return examples

4 構建模型

首先,我們利用BERT的BertModel類構造BERT結構,然後獲取其最後一層的輸出:

# 使用資料載入BertModel,獲取對應的字embedding

model = modeling.BertModel(

config=bert_config,
is_training=is_training,
input_ids=input_ids,
input_mask=input_mask,
token_type_ids=segment_ids,
use_one_hot_embeddings=use_one_hot_embeddin
)

# 獲取對應的BertModel的輸出

embedding = model.get_sequence_output()

然後增加(BiLSTM)CRF層,進行解碼:

max_seq_length = embedding.shape[1].value

# 算序列真實長度

used = tf.sign(tf.abs(input_ids))

lengths = tf.reduce_sum(used, reduction_indices=1)

# 新增CRF output layer

blstm_crf = 

BLSTM_CRF(embedded_chars=embedding,
hidden_unit=lstm_size,
cell_type=cell,
num_layers=num_layers,
dropout_rate=dropout_rate,
initializers=initializers,
num_labels=num_labels,
seq_length=max_seq_length,
labels=labels,
lengths=lengths,
is_training=is_training)
rst = blstm_crf.add_blstm_crf_layer(crf_only=True)

5 模型訓練

做了上述的準備工作之後,模型的訓練只需參照run_pretraining.py的main函式即可。主要的工作有:

1. processors初始化

2. estimator配置

3. 載入訓練資料

4. 利用model_fn_builder構造模型,載入模型引數 等。這是Tensorflow中新的架構方法,透過定義model_fn函式,定義模型。然後用Estimator API進行模型的訓練,預測,評估等。

5.呼叫Estimator進行訓練過程的控制及正式開始訓練等。

總結

利用BERT模型,進行NER任務Fine Tune的大致步驟如上。總的來說,相比於前面的BiLSTM+CRF模型,就是用BERT模型代替了原來的詞嵌入部分,利用BERT來進行語義編碼,BiLSTM+CRF進行解碼。因為需要用BERT,因此在輸入部分做了調整,本文介紹的使用estimator來構建和最佳化模型,也可以完全棄用這一套,自己構建和最佳化模型。





來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946223/viewspace-2658679/,如需轉載,請註明出處,否則將追究法律責任。

相關文章