【自然語言處理(NLP)】基于LSTM的命名實體識别(進階)
作者簡介:在校大學生一枚,華為雲享專家,阿裡雲專家部落客,騰雲先鋒(TDP)成員,雲曦智劃項目總負責人,全國高等學校計算機教學與産業實踐資源建設專家委員會(TIPCC)志願者,以及程式設計愛好者,期待和大家一起學習,一起進步~
.
部落格首頁:ぃ靈彧が的學習日志
.
本文專欄:機器學習
.
專欄寄語:若你決定燦爛,山無遮,海無攔
.
(文章目錄)
前言
(一)、任務描述
命名實體識别任務主要識别文本中的實體,并且給識别出的實體進行分類,比如人名、地名、機構名或其它類型。本質上,對于給定的文本,隻需要對其中的每個單詞進行分類,隻不過需要對分類的标簽進行重新定義。
(二)、環境配置
本示例基于飛槳開源架構2.0版本。
import paddle
import numpy as np
import matplotlib.pyplot as plt
print(paddle.__version__)
輸出結果如下圖1所示:
一、優化進階-使用預訓練的詞向量優化模型效果
在Baseline版本中,我們調用了
paddle.nn.Embedding
擷取詞的向量表示。這裡,我們調用
paddlenlp.embeddings
中内置的向量表示
TokenEmbedding
(一)、導入相關包
from paddlenlp.embeddings import TokenEmbedding # EMB
del model
del preds
del network
(二)、定義BiGRUWithCRF2
class BiGRUWithCRF2(nn.Layer):
def __init__(self,
emb_size,
hidden_size,
word_num,
label_num,
use_w2v_emb=True):
super(BiGRUWithCRF2, self).__init__()
if use_w2v_emb:
self.word_emb = TokenEmbedding(
extended_vocab_path='./data/word.dic', unknown_token='OOV')
else:
self.word_emb = nn.Embedding(word_num, emb_size)
self.gru = nn.GRU(emb_size,
hidden_size,
num_layers=2,
direction='bidirectional')
self.fc = nn.Linear(hidden_size * 2, label_num + 2) # BOS EOS
self.crf = LinearChainCrf(label_num)
self.decoder = ViterbiDecoder(self.crf.transitions)
def forward(self, x, lens):
embs = self.word_emb(x)
output, _ = self.gru(embs)
output = self.fc(output)
_, pred = self.decoder(output, lens)
return output, lens, pred
(三)、模型建構
network = BiGRUWithCRF2(300, 300, len(word_vocab), len(label_vocab))
model = paddle.Model(network)
optimizer = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters())
crf_loss = LinearChainCrfLoss(network.crf)
chunk_evaluator = ChunkEvaluator(label_list=label_vocab.keys(), suffix=True)
model.prepare(optimizer, crf_loss, chunk_evaluator)
model.fit(train_data=train_loader,
eval_data=dev_loader,
epochs=10,
save_dir='./results',
log_freq=1)
model.evaluate(eval_data=test_loader)
(四)、模型驗證
outputs, lens, decodes = model.predict(test_data=test_loader)
preds = parse_decodes(test_ds, decodes, lens, label_vocab)
print('\n'.join(preds[:5]))
二、概念解釋
(一)、門控循環單元GRU
BIGRU是一種經典的循環神經網絡(RNN,Recurrent Neural Network),前面一些步驟基本是把該模型當做是黑盒子來用,這裡我們重點解釋下其概念和相關原理。一個 RNN 的示意圖如下所示:
左邊是原始的 RNN,可以看到綠色的點代碼輸入 x,紅色的點代表輸出 y,中間的藍色是 RNN 模型部分。橙色的箭頭由自身指向自身,表示 RNN 的輸入來自于上時刻的輸出,這也是為什麼名字中帶有循環(Recurrent)這個詞。
右邊是按照時間序列展開的示意圖,注意到藍色的 RNN 子產品是同一個,隻不過在不同的時刻複用了。這時候能夠清晰地表示序列标注模型的輸入輸出。
GRU為了解決長期記憶和反向傳播中梯度問題而提出來的,和LSTM一樣能夠有效對長序列模組化,且GRU訓練效率更高。
(二)、條件随機場CRF
長句子的問題解決了,序列标注任務的另外一個問題也亟待解決,即标簽之間的依賴性。舉個例子,我們預測的标簽一般不會出現 P-B,T-I 并列的情況,因為這樣的标簽不合理,也無法解析。無論是 RNN 還是 LSTM 都隻能盡量不出現,卻無法從原理上避免這個問題。下面要提到的條件随機場(CRF,Conditional Random Field)卻很好的解決了這個問題。
條件随機場這個模型屬于機率圖模型中的無向圖模型,這裡我們不做展開,隻直覺解釋下該模型背後考量的思想。一個經典的鍊式 CRF 如下圖所示,
CRF 本質是一個無向圖,其中綠色點表示輸入,紅色點表示輸出。點與點之間的邊可以分成兩類,一類是 $x$ 與 $y$ 之間的連線,表示其相關性;另一類是相鄰時刻的 $y$ 之間的相關性。也就是說,在預測某時刻 $y$ 時,同時要考慮相鄰的标簽解決。當 CRF 模型收斂時,就會學到類似 P-B 和 T-I 作為相鄰标簽的機率非常低。
總結
本系列文章内容為根據清華社出版的《自然語言處理實踐》所作的相關筆記和感悟,其中代碼均為基于百度飛槳開發,若有任何侵權和不妥之處,請私信于我,定積極配合處理,看到必回!!!