【NLP实战系列】Tensorflow命名实体识别实战
實戰是學習一門技術最好的方式,也是深入了解一門技術唯一的方式。因此,NLP專欄計劃推出一個實戰專欄,讓有興趣的同學在看文章之余也可以自己動手試一試。
本篇介紹自然語言處理中一種非常重要的任務:命名實體識別。因為最常見的是Bilstm+CRF模型進行實體識別,本文介紹介紹另外一種有效的模型,Dilated-CNN+CRF模型,但是兩種模型的代碼都會給出。
作者&編輯 | 小Dream哥
1 命名實體識別任務介紹?
筆者在這篇文章中,曾經系統的介紹過命名實體識別任務的相關概念和語料標注方式,不了解的同學可以先閱讀這篇文章:
關于Bilstm和Dilated-CNN兩個模型理論方面的內容,筆者在這篇文章中做了詳細的介紹,不了解的同學可以先閱讀這篇文章:
話不多說,既然是實戰篇,我們就趕緊開始吧。
2 數據預處理
1) 查看數據格式
先了解一下數據格式,方便后面進行處理。如下圖所示,語料為標準的BIO標注方式,每個字和標記之間用空格隔開,語料之間用一個空行隔開。
2)讀取訓練數據
def load_sentences(path, lower, zeros):? ?加載訓練,測試,驗證數據的函數
上面這個函數是用來讀取訓練,測試,驗證數據的,該函數返回一個列表,如下圖所示:
3) 標記格式轉化
因為原始語料用的是BIO標注方法,但是BIOES標注形式包含了實體內更多的位置和邊界信息,最好將其轉化為BIOES的形式,方法如下:
def update_tag_scheme(sentences, tag_scheme):將IOB格式轉化為BIOES格式。 保證語料上BIO格式##產生異常轉化為BIOES
看看效果如何:
4)構造字典
經過上述步驟,雖然我們將數據讀到了一個列表里組織了起來,但是一個一個的漢字及其標簽,后面的LSTM或者CNN網絡是沒有辦法處理的,需要進行詞嵌入。在此之前需要構造2個字典,漢字字典和標簽字典,然后將上面的漢字和標簽轉化成字典里的序號。看看代碼是怎么做的:
def char_mapping(sentences, lower):#生成字典和mapping
def create_dico(item_list):? #根據傳入的列表,生成一個字典
#生成連個字典,id->word word->id
上述過程并不難理解,大家好好看看,我們看看生成的字典:
5) 根據字典組織好訓練數據
訓練時,應該是輸入漢字序列,然后預測出一個BIO序列,所以我們的輸入數據還需要整理,將漢字和標記分開,得到漢字序列及其標記序列,并且要將漢字及其標記轉換成他們在字典里的序號,轉化結果如下:
至此,我們將訓練數據結構化的組織了起來,放在一個大列表里,并且列表里的數據通過生成的字典轉化成了id。
3 模型實現
1)word embedding
我們將語料中的中文換成了他們在字典里的ID,了解詞向量的同學都知道我們還需要對詞進行詞嵌入,后面的深度學習模型才能進行處理。不了解的同學可以找詞向量的文章看一下。
下面看看如何實現:
def embedding_layer(self, char_inputs, seg_inputs, config, name=None)::param char_inputs: one-hot encoding of sentence
# 生成一個表,用于后面查表
# 查表,將詞向量化?
? ? ? ? embedding.append(tf.nn.embedding_lookup(self.char_lookup, char_inputs))
# 分詞的維度,可先不關注
? ? ? ? embedding.append(tf.nn.embedding_lookup(self.seg_lookup, seg_inputs))
也許有同學會問,這里的詞向量表是隨機初始化的。如果我之前訓練好了一份詞向量,該如何使用呢?可以在定義好模型之后,char_lookup.assign函數為該詞向量表賦值,參考如下:
通過embedding_layer,就將形狀為[bacth_size, seq_length]的輸入數據轉化為形狀為[bacth_size, seq_length,embeding_dim]的矩陣了。詞向量化幾乎是所有自然語言處理任務所必須要經過的步驟,讀者務必弄明白。
2)構建dilated CNN模型
首先,做一些數據的維度變化,并做一次CNN特征提取。
def IDCNN_layer(self, model_inputs,param idcnn_inputs: [batch_size, num_steps, emb_size]
? ?model_inputs = tf.expand_dims(model_inputs, 1)輸入的尺寸?= [batch, in_height, in_width, in_channels]
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?use_cudnn_on_gpu=True)
#重復4次增強特征提取能力
#每次有3次卷積操作,前兩次卷積膨脹系數為
? ? ? ? ? ? ? 1,后一次膨脹系數為2
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? %d" % i, #卷積核
????????????????????w = tf.get_variable(
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? self.num_filter,
? ? ? ? ? ? ? ? ? ? ? ?initializer=tf.contrib.layers.
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?xavier_initializer())
重復做卷積操作進行特征提取,膨脹卷積可以擴大卷積核的感受野,提高卷積操作對長序列特征的提取能力。同時加深深度,也可以進一步提高特征提取能力。如下,repeat times為4,dilation數組為[1,1,2]。
3)project層
用一個中間層,將CNN的輸出轉化為shape為[batch_size, num_steps, num_tags]的輸出,后面可以接softmax作為輸出,也可以接crf計算loss
4)CRF層計算loss
采用CRF計算損失幾乎是序列標注問題的標準做法,關于CRF的相關問題,筆者在機器學習模型介紹條件隨機場CRF一文中做了詳細介紹,不了解的讀者可以出門看看。
4 開始訓練
在main文件開頭的參數配置中,選擇train為True:
flags.DEFINE_boolean("train",? ? ? ?True, ? ? ?"Whether train the model")
執行python main.py即可以開始進行訓練,學習率,batch_size,dropout等超參數,讀者可以自行調整。
訓練開始后,會有如下的打印信息,讀者可以觀察loss下降的趨勢。
訓練結束后,會在ckpt文件夾生成模型文件。
5 模型測試
在main文件開頭的參數配置中,選擇train為False:
flags.DEFINE_boolean("train", ? ? ? False, ? ? ?"Whether train the model")
我們看看結果是怎么樣的:
輸入“明天我想去深圳市”模型將“明天”作為TIME提取出來了,將“深圳市”作為LOC提取出來了。
至此,介紹了如何利用構建DI-CNN模型進行命名實體識別,代碼在我們有三AI的github可以下載:https://github.com/longpeng2008/yousan.ai/tree/master/natural_language_processing
找到ner文件夾,執行python3 main.py就可以訓練或者測試了。
總結
NER是一個非常基礎,但是非常重要的任務,在具體的操作中,相信大家能夠更為細致的體會NER任務的真正作用和意涵。
我們也會在知識星球還介紹了基于BERT來做NER的方法,感興趣掃描下面的二維碼了解。
讀者們可以留言,或者加入我們的NLP群進行討論。感興趣的同學可以微信搜索jen104,備注"加入有三AI NLP群"。
下期預告:命名實體識別實踐
知識星球推薦
掃描上面的二維碼,就可以加入我們的星球,助你成長為一名合格的自然語言處理算法工程師。
知識星球主要有以下內容:
(1) 聊天機器人。考慮到聊天機器人是一個非常復雜的NLP應用場景,幾乎涵蓋了所有的NLP任務及應用。所以小Dream哥計劃以聊天機器人作為切入點,通過介紹聊天機器人的原理和實踐,逐步系統的更新到大部分NLP的知識,會包括語義匹配,文本分類,意圖識別,語義匹配命名實體識別、對話管理以及分詞等。
(2) 知識圖譜。知識圖譜對于NLP各項任務效果好壞的重要性,就好比基礎知識對于一個學生成績好壞的重要性。他是NLP最重要的基礎設施,目前各大公司都在著力打造知識圖譜,作為一個NLP工程師,必須要熟悉和了解他。
(3) NLP預訓練模型。基于海量數據,進行超大規模網絡的無監督預訓練。具體的任務再通過少量的樣本進行Fine-Tune。這樣模式是目前NLP領域最火熱的模式,很有可能引領NLP進入一個全新發展高度。你怎么不深入的了解?
轉載文章請后臺聯系
侵權必究
往期精選
總結
以上是生活随笔為你收集整理的【NLP实战系列】Tensorflow命名实体识别实战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【每周CV论文推荐】 初学深度学习人脸识
- 下一篇: 【AutoML】激活函数如何进行自动学习