最近做命名實(shí)體識(shí)別(NER)的任務(wù)比較多衬吆,也剛剛接觸NER不久,做一下小小的總結(jié)。近兩年中文命名實(shí)體識(shí)別在信息抽取和關(guān)系抽取上的應(yīng)用受到了研究人員的廣泛關(guān)注,很多比賽也以NER為主題來命題供璧。
最開始接觸NER看到的大多數(shù)方法都是以BiLSTM+CRF的框架進(jìn)行,包括工業(yè)界的很多大廠都是在用這個(gè)模型來做序列標(biāo)注任務(wù)冻记,效果也比較理想睡毒。除此之外工業(yè)界的傳統(tǒng)方法還包括Softmax、HMM冗栗、MEMM演顾、CRF、CRF++隅居、IDCNN+CRF等等模型钠至,但是在大多數(shù)情況下的表現(xiàn)不如BiLSTM+CRF。
BiLSTM+CRF一般采用預(yù)練詞向量的方式胎源,底層可以接Word2vec棉钧、Fasttext、CNN涕蚤、Glove宪卿、ELMo等任意預(yù)訓(xùn)練的char級(jí)別的或bichar級(jí)別的Embedding。普遍采用封鎖固定向量的方式万栅,將輸入映射成向量作為輸入層接入雙向的LSTM佑钾,再將前向和后向的結(jié)果拼接,接全連接層輸出每個(gè)字符屬于每個(gè)標(biāo)簽的概率烦粒,再接CRF休溶,最后用Viterbi算法解碼。
BERT及XLNet的出現(xiàn)將預(yù)訓(xùn)練詞向量帶到了一個(gè)前所未有的新高度扰她,BERT無需封鎖向量邮偎,詞向量可以隨著頂層任務(wù)進(jìn)行微調(diào)。自然地义黎,BERT+BiLSTM+CRF的方式逐漸取代了傳統(tǒng)的序列標(biāo)注方法禾进,一躍成為各大比賽榜上的常客廉涕。
可能的模型結(jié)構(gòu)
但是NER任務(wù)想要取得好的效果只能基于BiLSTM+CRF這一種網(wǎng)絡(luò)結(jié)構(gòu)嗎泻云?答案肯定是否定的『桑看了‘達(dá)觀杯’文本智能信息抽取挑戰(zhàn)賽的前幾名的解決方案宠纯,我也找到了一些新的思路,前幾名的方案中包含了以下在序列標(biāo)注中很少見的網(wǎng)絡(luò)結(jié)構(gòu):
- BiLSTM+Attention+CRF
- BiLSTM+CNN+CRF
- BiLSTM+CNN+Attention+CRF
- BiLSTM+SPAN
其中第一名方案的七個(gè)融合模型都采用了BiLSTM+CNN+CRF的網(wǎng)絡(luò)結(jié)構(gòu)层释,所以婆瓜,打算自己實(shí)驗(yàn)一下,看看前三種網(wǎng)絡(luò)的效果如何。
實(shí)驗(yàn)配置
- 采用roberta作為底層的詞向量模型(略優(yōu)于BERT base)
- 實(shí)驗(yàn)基于github上的優(yōu)秀項(xiàng)目BERT-BiLSTM-CRF-NER
- 向量模型為chinese_roberta_wwm_ext_L-12_H-768_A-12
- 訓(xùn)練語料采用人民日?qǐng)?bào)命名實(shí)體識(shí)別語料(LOC:地點(diǎn)廉白;ORG:機(jī)構(gòu)名个初;PER:人名)
設(shè)定參數(shù)
- 網(wǎng)絡(luò)層數(shù)=6層(為了訓(xùn)練得快點(diǎn))
- crf_only=False
- batch_size=8(GPU跑不了更大的batch_size了)
- num_train_epochs=10
其余參數(shù)使用默認(rèn)值
以下實(shí)驗(yàn)可能不夠嚴(yán)謹(jǐn),不具有參考價(jià)值猴蹂,由于訓(xùn)練時(shí)間過長院溺,epoch只選擇了10輪,遠(yuǎn)遠(yuǎn)沒有達(dá)到模型最好的效果磅轻,只是自己單純測(cè)試一下珍逸。每個(gè)模型只訓(xùn)練了一次,沒有多次訓(xùn)練取平均值聋溜。
開始實(shí)驗(yàn)
首先先放上crf_only=True的結(jié)果谆膳,即只用BERT+CRF來做NER任務(wù)
LOC: precision: 93.62%; recall: 94.83%; FB1: 94.22 3509
ORG: precision: 88.61%; recall: 91.27%; FB1: 89.92 2231
PER: precision: 96.69%; recall: 96.43%; FB1: 96.56 1815
接著是crf_only=False的結(jié)果,即BERT+BiLSTM+CRF
LOC: precision: 93.27%; recall: 95.21%; FB1: 94.23 3536
ORG: precision: 87.97%; recall: 91.14%; FB1: 89.52 2244
PER: precision: 96.56%; recall: 97.25%; FB1: 96.91 1833
可以看到加了BiLSTM后撮躁,效果好像有一點(diǎn)提升摹量,但是很多指標(biāo)好像還不如不加BiLSTM
BERT+BiLSTM+CNN+CRF
接下來將四層相同的CNN網(wǎng)絡(luò)加入BiLSTM和CRF之間,卷積核尺寸為5馒胆,400維。沒有drouout等其它層凝果,修改lstm_crf_layer.py中的add_blstm_crf_layer函數(shù)為
def add_blstm_crf_layer(self, crf_only):
"""
blstm-cnn-crf網(wǎng)絡(luò)
:return:
"""
if self.is_training:
# lstm input dropout rate i set 0.9 will get best score
self.embedded_chars = tf.nn.dropout(self.embedded_chars, self.dropout_rate)
if crf_only:
logits = self.project_crf_layer(self.embedded_chars)
else:
# blstm
lstm_output = self.blstm_layer(self.embedded_chars)
conv1 = tf.layers.conv1d(lstm_output, 400, 5, padding='same',
name='conv1')
conv2 = tf.layers.conv1d(conv1, 400, 5, padding='same',
name='conv2')
conv3 = tf.layers.conv1d(conv2, 400, 5, padding='same',
name='conv3')
conv4 = tf.layers.conv1d(conv3, 400, 5, padding='same',
name='conv4')
logits = self.project_bilstm_layer(conv4)
# project
# logits = self.project_bilstm_layer(lstm_output)
# crf
loss, trans = self.crf_layer(logits)
# CRF decode, pred_ids 是一條最大概率的標(biāo)注路徑
pred_ids, _ = crf.crf_decode(potentials=logits, transition_params=trans, sequence_length=self.lengths)
return (loss, logits, trans, pred_ids)
實(shí)驗(yàn)結(jié)果:
LOC: precision: 94.09%; recall: 95.06%; FB1: 94.57 3500
ORG: precision: 88.92%; recall: 91.87%; FB1: 90.37 2238
PER: precision: 96.71%; recall: 96.87%; FB1: 96.79 1823
BERT+BiLSTM+Attention+CRF
采用self-attention祝迂,其中的attention_layer, get_shape_list函數(shù)來自于bert_base.bert.modeling
def add_blstm_crf_layer(self, crf_only):
"""
blstm-attention-crf網(wǎng)絡(luò)
:return:
"""
if self.is_training:
# lstm input dropout rate i set 0.9 will get best score
self.embedded_chars = tf.nn.dropout(self.embedded_chars, self.dropout_rate)
if crf_only:
logits = self.project_crf_layer(self.embedded_chars)
else:
# blstm
lstm_output = self.blstm_layer(self.embedded_chars)
input_shape = get_shape_list(lstm_output, expected_rank=3)
attention_head = attention_layer(
from_tensor=lstm_output,
to_tensor=lstm_output,
attention_mask=None,
num_attention_heads=12,
size_per_head=int(768 / 12),
attention_probs_dropout_prob=0.1,
initializer_range=0.02,
do_return_2d_tensor=True,
batch_size=input_shape[0],
from_seq_length=input_shape[1],
to_seq_length=input_shape[1])
logits = self.project_bilstm_layer(attention_head)
# project
# logits = self.project_bilstm_layer(lstm_output)
# crf
loss, trans = self.crf_layer(logits)
# CRF decode, pred_ids 是一條最大概率的標(biāo)注路徑
pred_ids, _ = crf.crf_decode(potentials=logits, transition_params=trans, sequence_length=self.lengths)
return (loss, logits, trans, pred_ids)
實(shí)驗(yàn)結(jié)果為:
LOC: precision: 92.58%; recall: 92.55%; FB1: 92.57 3463
ORG: precision: 85.48%; recall: 88.87%; FB1: 87.14 2252
PER: precision: 94.16%; recall: 95.66%; FB1: 94.90 1849
BiLSTM+CNN+Attention+CRF
簡單地將上面兩個(gè)模型結(jié)合起來,代碼就不貼了
實(shí)驗(yàn)結(jié)果為
LOC: precision: 93.29%; recall: 94.66%; FB1: 93.97 3515
ORG: precision: 88.22%; recall: 90.26%; FB1: 89.23 2216
PER: precision: 96.26%; recall: 96.15%; FB1: 96.21 1818
總結(jié)
雖然實(shí)驗(yàn)結(jié)果不夠嚴(yán)謹(jǐn)器净,不具有權(quán)威性型雳,但總的來看BERT+BiLSTM+CNN+CRF的效果比較好,其余的幾個(gè)結(jié)果差不多山害,起碼沒有比基準(zhǔn)的BERT+CRF差纠俭。CNN的參數(shù)和一些dropout的搭配可能會(huì)讓效果有所提升,但是加上CNN的原因和原理不得而知浪慌,可能有相關(guān)的論文我沒看到冤荆,等有時(shí)間再看一下SPAN的原理和實(shí)現(xiàn),和NER任務(wù)結(jié)合做一些實(shí)驗(yàn)权纤。