自然語言處理(NLP):22 BERT中文命名實體識別

本文主要通過不同的數據集來進行 NER 模型驗證驗證,以及指定一些通過訓練 NER 任務的一套標準,通過兩條路線進行分析和總結。
(1)工業界場景-> 學術界 NER 論文-> BERT 實現 NER 方案以及源碼分析
(2)預料數據-> 業務數據可視化分析-> 標準數據格式轉換-> 模型訓練-> 在線預測-> 序列標準任務優化和拓展

作者:走在前方
博客:https://wenjie.blog.csdn.net/
學習交流羣:更多精彩內容加入“NLP技術交流羣” 學習
專注於文本分類、關鍵詞抽取、文本摘要、FAQ 問答系統、對話系統語義理解 NLU、知識圖譜等。結合工業界具體案例和學術界最新研究成果實現 NLP 技術場景落地。


本文主要分享核心要點

  • 命名實體識別初識
    • 什麼是 NER
    • NER 發展以及技術方案
  • 工業界應用場景
    • 人力資源檢索系統
    • 電子病歷系統
    • 聊天機器人對話系統
    • 其他(某團語音平臺,某米音箱。。)
  • 學術界論文方案解讀
    • BiLSTM-CRF
    • Att-BiLSTM-CRF
    • BERT
    • BERT-CRF
  • BERT 源碼分析
    • 詞潛入歷史發展 word2vec、glove、ELMo、BERT
    • BERT 模型詳細介紹
    • BERT 模型演變
  • NER 項目前準備工作
    • 數據庫分析可視化 pyecharts、seaborn、matplotlib
    • NER 項目 CRF 模塊
    • transformer 模型模塊
    • NER 評估模塊
  • 不同數據集實驗
    • 案例 1:CoNLL2003 經典 NER 入門項目
    • 案例 2:航空旅遊項目
    • 案例 3:新聞數據項目
    • 案例 4:NLP 比賽 音樂領域 NER 項目
    • 案例 5: 中文分詞以及詞性標註

命名實體識別初識

Named-entity recognition (NER) (also known as entity identification, entity chunking and entity extraction)

命名實體識別(Named Entity Recognition,簡稱 NER),又稱作“專名識別”,是指識別文本中具有特定意義的實體,主要包括人名、地名、機構名、專有名詞等。簡單的講,就是識別自然文本中的實體指稱的邊界和類別。

一些研究也涉及電影名、書名、項目名、研究領域名稱、電子郵件地址、電話號碼以及生物信息學領域的專有名詞(如蛋白質、DNA、RNA 等)。甚至有一些工作不限定“實體”的類型,而是將其當做開放域的命名實體識別和分類。

NER 一直是 NLP 領域中的研究熱點,從早期基於詞典和規則的方法,到傳統機器學習的方法,到近年來基於深度學習的方法,NER 研究進展的 大概趨勢大致如下圖 所示。

圖片

工業界應用場景

簡歷自動檢索系統

https://dataturks.com/blog/named-entity-recognition-in-resumes.php

圖片

圖片

人力資源檢索系統,可以通過 NER 來完成,從三個方面提供給我們一些思路

1。簡歷自動彙總

2。優化搜索引擎算法

3。強大的推薦系統

4。簡化客戶支持

  • 簡歷自動彙總

圖片

各公司人力資源部面臨的一個關鍵挑戰是評估一大堆求職者的簡歷。爲了增加他們的亮點,申請者往往過於詳細化他們的簡歷,其中大部分信息與評估者所尋求的無關。爲了簡化這一過程,通過我們的 NER 模型,我們可以方便地對簡歷進行快速評估,從而簡化在一堆簡歷中篩選候選人所需的工作。

  • 優化搜索引擎算法

圖片

爲了設計一種搜索引擎算法,而不是在數百萬篇在線文章和網站上搜索輸入的查詢,一種更有效的方法是對文章運行一次 NER 模型,並永久存儲與之相關的實體。然後,可以將搜索查詢中的關鍵標記與與網站文章關聯的標記進行比較,以實現快速高效的搜索。

  • 強大的推薦系統

圖片

NER 可用於開發推薦系統的算法,自動過濾我們可能感興趣的相關內容,並據此指導我們根據以前的行爲發現相關和未訪問的相關內容。這可以通過提取與我們的歷史或以前活動中的內容相關聯的實體,並將它們與分配給其他未公開內容的標籤進行比較,以篩選相關的實體來實現。

  • 簡化客戶支持

圖片

NER 可用於識別客戶投訴和反饋中的相關實體,如產品規格、部門或公司分支機構的詳細信息,以便對反饋進行相應分類,並轉發給負責識別產品的相應部門。

電子病例命名實體識別

電子病歷結構化是讓計算機理解病歷、應用病歷的基礎。基於對病歷的結構化,可以計算出症狀、疾病、藥品、檢查檢驗等多個知識點之間的關係及其概率,構建醫療領域的知識圖譜,進一步優化醫生的工作. 對於給定的一組電子病歷純文本文檔,識別並抽取出其中與醫學臨牀相關的實體,並將它們歸類到預先定義好的類別中。例如,我們可以識別含解剖部位、獨立症狀、症狀描述、手術和藥物等實體。

圖片

舉例說明,根據病例描述抽取信息:

  • 輸入數據

女性,88 歲,農民,雙灤區應營子村人,主因右髖部摔傷後疼痛****腫脹,活動受限 5 小時於 2016-10-29;11:12 入院。

  • 輸出結果

右髖部 21 23 身體部位

疼痛 27 28 症狀和體徵

腫脹 29 30 症狀和體徵

聊天機器人的對話系統

圖片圖片圖片

圖片圖片

對話系統在聊天機器人中應用以及發展歷史

  • 1950: Turing Test
  • 1966: ELIZA, MIT chatbot
  • 1995: ALICE, pattern recognition chatbot
  • 2011-2012: Siri, Watson, Google Assistant
  • 2015: Amazon Alexa, Microsoft Cortana
  • 2016: Bot 元年:Microsoft Bot Framework, FB Messenger, Google Assistant …
  • 2017: 百度度祕,騰訊雲小微,阿里小蜜 …

對話系統主要包括三個方面的內容

  • NLU 自然語言理解

對話系統中語義理解部分主要包括:領域分類、意圖識別和槽位抽取。

領域分類:針對一個 query 的短文本分類

意圖識別:也可以看成文本分類問題

槽位抽取:可以看成 NER 技術領域的問題

  • 領域分類

例如: 音樂、天氣、指令。。。。

  • 意圖識別(slot filling)

對於音樂來說,比如:播放,暫停,下一首等。。。

  • 槽位填充(命名實體識別)

例如: 播放一週周杰倫東風破。 {‘singer’:’'周杰倫 ,‘song’:'東風破 '}

  • DM 對話管理
  • NLG 自然語言生成

2018 年 Alexa Prize Challenge 亞馬遜舉辦的聊天機器人大賽

2018 年冠軍** **

Gunrock: Building A Human-Like Social Bot By Leveraging Large Scale Real User Data

圖片

系統的整體架構

圖片

學術界論文方案解讀

BiLSTM-CRF vs Att-BiLSTM-CRF 論文

BiLSTM-CRF 論文

Attention+BiLSTM-CRF 論文

BiLSTM-CRF baidu

圖片

Att-BiLSTM-CRF

圖片

接下來我們重點看下 Att-BiLSTM-CRF 這篇論文,我們重點了解。

其中: 論文的代碼

  • attention 的計算方法

https://github.com/lingluodlut/Att-ChemdNER/blob/81db44f5cbd5bbbb1d1dee72a528280425de7bc9/src/nn.py#L628

  • Att-BiLSTM-CRF VS 其他模型效果對比

該論文中提供了4個計算attention 的方法

圖片

四種計算 attention 方法對比效果

圖片

其他模型 VS Att-BiLSTM-CRf 對比

圖片

BiLSTM-CRF VS Att-BiLSTM-CRF 架構

圖片

The architectures of BiLSTM-CRF model and our Att-BiLSTM-CRF model.

(A) The basic BiLSTM-CRF model.

(B) Our Att-BiLSTM-CRF model. In the models, the BIO (Begin, Inside, Outside) tagging scheme are used. In the figure (B), only the attention weights of the target word are illustrated for clarity. The attention weight is larger when the word is more related to the target word, and the color of attention line is darker

BERT vs BERT-CRF 論文

2018 《 BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》

2020 《 A New Active Learning Strategy for Bert-CRF Based Named Entity Recognition》

BERT 論文

圖片

圖片

BERT-CRF 論文

圖片

圖片

本論文我們主要關注幾個核心點即可

論文主要通過增加一些策略機制來進行一些實驗的實驗

  • 實驗證明 Bert-BiLSTM-CRF 和 Bert-CRF 這兩種方式沒有太大的區別,反而 Bert-BiLSTM-CRF 增加 BiLSTM 層使得模型訓練和推理速度變慢。
  • BERT BIO 編碼格式輸入(注意:pad 補充),這裏同 BERT 原始論文保持一致

圖片

  • dropout 參數設置

在 fc 層減少過擬合設置 dropout = 0.9 ,後續我們實驗也可以嘗試 。

In the fully connected layer, we set the dropout rate to be 0.9 to prevent overfitting

  • 學習濾參數設置

learning rate to 0.00001

BERT 源碼分析

BERT系列預訓練模型

NER 項目準備

NER 評估標準

seqeval 是一個用於序列標記評估的 python 框架。seqeval 可以評估命名實體識別、詞性標註、語義角色標註等分塊任務的性能。

seqeval 支持格式:IOB 和 IOBES

seqeval 安裝方法:pip install seqeval

安裝完成後,爲保持使用我們把源碼拷貝到自己的工程下。

seqeval 代碼使用

from seqeval.metrics import accuracy_score
from seqeval.metrics import classification_report
from seqeval.metrics import f1_score
y_true = [['O', 'O', 'O', 'B-MISC', 'I-MISC', 'I-MISC', 'O'], ['B-PER', 'I-PER', 'O']]
y_pred = [['O', 'O', 'B-MISC', 'I-MISC', 'I-MISC', 'I-MISC', 'O'], ['B-PER', 'I-PER', 'O']]
# score
print( f1_score(y_true, y_pred) )
# acc
print(accuracy_score(y_true, y_pred))
# report
print( classification_report(y_true, y_pred) )

上述代碼運行的效果:

0.5
0.8
           precision    recall  f1-score   support

      PER       1.00      1.00      1.00         1
     MISC       0.00      0.00      0.00         1

micro avg       0.50      0.50      0.50         2
macro avg       0.50      0.50      0.50         2

BERT 預訓練模型下載

**英文 BERT 預訓練模型,預訓練模型以及文件 rename 後 **

bert-base-uncased

├── config.json

├── pytorch_model.bin

└── vocab.txt

**BERT 預訓練中文模型,預訓練模型以及文件 rename 後 **

圖片

BERT CRF 模塊

直接使用 torchcrf

pip install torchcf

安裝成功後,我們找到 torchcf 模塊,拷貝自己的項目中即可直接使用了。

transformers

transformers下載 ,下載完成後,把項目拷貝到自己的項目中。

數據分析可視化

數據可視化可以幫助我們理解業務數據,重點選擇 pyecharts、seaborn、matplotlib 工具庫。

CoNLL2003 數據集項目

我們使用指定服務器,需要執行下面內容。

https://blog.csdn.net/ShiMengRan107/article/details/100152211

PS1='${debian_chroot:+($debian_chroot)}ailib@ubuntu:\w\$ '
export PATH=/usr/share/anaconda3/bin:$PATH
source activate
conda activate torch1.4-gpu
export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64:$LD_LIBRARY_PATH  
export CUDA_HOME=/usr/local/cuda-10.0:$CUDA_HOME  
export PATH=/usr/local/cuda-10.0/bin:$PATH  
export LD_LIBRARY_PATH=/usr/local/cuda-10.0/extras/CUPTI/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

CoNLL2003 數據集[1]

實體被標註爲四種類型:

LOC (location, 地名)

ORG (organisation, 組織機構名)

PER (person, 人名)

MISC (miscellaneous, 其他)

一條標註數據的組織形式如下:

[word][POS tag][chunk tag][NER tag]

DATA FORMAT

The data files contain one word per line. Empty lines have been usedfor marking sentence boundaries and a line containing the keyword-DOCSTART- has been added to thebeginning of each article in order to mark article boundaries. Each non-empty line contains the following tokens:

  1. the current word

  2. the lemma of the word (German only)

  3. the part-of-speech (POS) tag generated by a tagger

  4. the chunk tag generated by a text chunker

  5. the named entity tag given by human annotators

數據預處理

原始數據處理

提供 train.txt,dev.txt,test.txt 的數據格式如下


-DOCSTART- -X- -X- O

CRICKET NNP B-NP O
- : O O
LEICESTERSHIRE NNP B-NP B-ORG
TAKE NNP I-NP O
OVER IN B-PP O
AT NNP B-NP O
TOP NNP I-NP O
AFTER NNP I-NP O
INNINGS NNP I-NP O
VICTORY NN I-NP O
. . O O

LONDON NNP B-NP B-LOC
1996-08-30 CD I-NP O

上述數據處理生成三個文件

  • seq.in 每行表示一個完整的句子,然後以空格分割
CRICKET - LEICESTERSHIRE TAKE OVER AT TOP AFTER INNINGS VICTORY .
LONDON 1996-08-30
  • seq.out 對應每個單詞的 TAG,空格分割
O O B-ORG O O O O O O O O
B-LOC O
  • slot_label.txt NER 標籤的類型,這裏增加 PAD 和 UNK 兩個特殊的標籤
PAD
UNK
O
B-LOC
I-LOC
B-MISC
I-MISC
B-ORG
I-ORG
B-PER
I-PER

特徵工程

原始數據進行數字化表示

圖片

定義保存 words 和 slot_labels 的類 ,我們把每個句子使用 InputExample 來表示

class InputExample(object):
    """
    A single training/test example for simple sequence classification.

    Args:
        guid: Unique id for the example.
        words: list. The words of the sequence.
        slot_labels: (Optional) list. The slot labels of the example.
    """

    def __init__(self, guid, words, slot_labels=None):
        self.guid = guid
        self.words = words
        self.slot_labels = slot_labels

模型訓練

圖片

python3 main.py \
--model_name_or_path ../pretrained_models/bert-base-uncased/ \
--task CoNLL-2003 \
--model_type bert \
--model_dir CoNLL-2003_model \
--do_train --do_eval --use_crf \
--num_train_epochs 5 \
--train_batch_size 64 \
--eval_batch_size 64 

這裏對幾個重要的參數進行說明

  • model_name_or_path

bert 的 pre_trained_model 的路徑

  • task

指定數據集處理器

  • model_type

指定模型的類型,例如 bert,albert 等

  • do_train do_eval use_crf 分別爲訓練、驗證和使用 crf 預測 tag
  • num_train_epoches 設置模型迭代的次數
  • train_batch_size,eval_batch_size 分別爲訓練和驗證數據集每個批次加載的記錄數

在線服務預測

在線服務啓動

python3 api.py \
--model_name_or_path ../pretrained_models/bert-base-uncased/ \
--task CoNLL-2003 \
--model_type bert \
--model_dir CoNLL-2003_model \
--use_crf 

這裏我們使用的是 CoNLL2013 的數據集,如果是其它的數據,需要替換相應的目錄

這裏對幾個重要的參數進行說明

  • model_name_or_path

bert 的 pre_trained_model 的路徑

  • model_type

指定模型的類型,例如 bert,albert 等

  • use_crf 使用 crf 預測 tag
  • num_train_epoches 設置模型迭代的次數
  • train_batch_size,eval_batch_size 分別爲訓練和驗證數據集每個批次加載的記錄數
  • no_cuda 如果設置使用 cpu 進行推理,不設置的話如果有 cuda 可以 gpu 下推理

在線文本預測

curl -H “Content-Type:application/json” -X POST --data ‘{“text”: “Steve went to Paris”}’ http://localhost:8000/predict

返回結果

{ “errno”: 0, “errmsg”: “success”, “time”: 69, “data”: [{ “word”: “Steve”, “tag”: “B-PER” }, { “word”: “went”, “tag”: “O” }, { “word”: “to”, “tag”: “O” }, { “word”: “Paris”, “tag”: “B-LOC” }] }

預測代碼分析

  • 數據輸入

text = 'Steve went to Paris

  • 構建模型輸入數據

圖片

  • 特徵數據離散化處理
tokenizer = load_tokenizer(args)
text_dataset = load_examples(args, tokenizer, text)

圖片

獲取三個字段數據分別

input_ids 文本中每個 token 在字典中表示

attention_mask 存在 token 的設置 1,不足 max_seq_len 長度的內容設置 0

token_type_ids 表示第一個句子,這全部 0

  • 預測 predict 函數定義(重點)

圖片

航空旅遊數據集項目

ATIS (Airline Travel Information System)

我們在完成 CoNLL2003 數據集下的 BERT-NER 訓練和預測後,在進行別的數據集就非常容易了。關鍵在於我們的程序是通用的,唯一我們需要做的時候轉換成一個數據集即可。

ATIS 數據集分析

首先,我們熟悉下處理成標準的格式數據(以後我們在處理 NER 問題時候,都可以處理成 CoNLL2003 中標準格式即可)

seq.in

seq.out

slot_label.txt

同時生成對應的 train、test、dev。 每個數據都對應上述 seq.in 和 seq.out,其中 slot_label.txt 是所有的 TAG 以及增加兩個特殊的標籤 PAD、UNK。

然後,需要對 seq.in seq.out 進行處理,針對每個句子處理後生成 tokens、input_ids、attention_mask、token_type_ids、slot_labels。

05/16/2020 23:19:06 - INFO - data_loader -   guid: dev-1
05/16/2020 23:19:06 - INFO - data_loader -   tokens: [CLS] show me all round trip flights between houston and las vegas [SEP]
05/16/2020 23:19:06 - INFO - data_loader -   input_ids: 101 2265 2033 2035 2461 4440 7599 2090 5395 1998 5869 7136 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
05/16/2020 23:19:06 - INFO - data_loader -   attention_mask: 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
05/16/2020 23:19:06 - INFO - data_loader -   token_type_ids: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
05/16/2020 23:19:06 - INFO - data_loader -   slot_labels: 0 2 2 2 98 99 2 2 73 2 114 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

我們分析後發現 slot_labels.txt 中每個標籤數量差別很大,存在 TAG 分佈不均衡問題。 我們在實際工作中如果入到這種問題,可以想辦法補充,使其儘可能均衡(這裏我們不在處理

ATIS 模型訓練

模型採用 BERT-CRF 進行

圖片

python3 main.py \
--model_name_or_path ../pretrained_models/bert-base-uncased/ \
--task atis \
--model_type bert \
--model_dir atis_model \
--do_train --do_eval --use_crf \
--num_train_epochs 15 \
--train_batch_size 64 \
--eval_batch_size 64 \
--max_seq_len 32   

我們這裏訓練 **15 **次迭代,訓練完成後我們查看下效果。

  • 驗證數據集效果

圖片

  • 測試數據集下的效果

圖片

我們的 f1 在 dev 數據集達到 97%+,在 test 數據集下也達到 94%+。證明我們 BERT -CRF 在 NER 效果上還是不錯的。

注意:BERT-CRF 在 NER 領域效果已經非常好的了,我們唯一需要重點關注的是數據。如果使用過程某些地方需要處理,我們需要把 TAG 的數據進行擴展,是提升效果最重要的方法。切切記!!!

ATIS 模型預測

在線服務啓動。 默認據服務器自動採用 cpu 還是 gpu 進行推理 (gpu 效果>> 好遠 cpu)

圖片

python3 api.py \
--model_name_or_path ../pretrained_models/bert-base-uncased/ \
--task atis \
--model_type bert \
--model_dir atis_model \
--use_crf 

啓動完成後,我們來進行預測

curl http://localhost:8000/predict \
-H "Content-Type:application/json" \
-X POST \
--data '{"text": "i want to fly boston to san francisco","lang":"en"}'

返回結果如

{
	"errno": 0,
	"errmsg": "success",
	"time": 13,
	"data": [{
			"word": "i",
			"tag": "O"
		},
		{
			"word": "want",
			"tag": "O"
		},
		{
			"word": "to",
			"tag": "O"
		},
		{
			"word": "fly",
			"tag": "O"
		},
		{
			"word": "boston",
			"tag": "B-fromloc.city_name"
		},
		{
			"word": "to",
			"tag": "O"
		},
		{
			"word": "san",
			"tag": "B-toloc.city_name"
		},
		{
			"word": "francisco",
			"tag": "I-toloc.city_name"
		}
	]
}

返回的結果:(其中 time 是在 cpu 推理的情況下花費 58 毫秒,cuda 運行在 17ms 左右,可以滿足上線的條件)

同時我們看看服務端後端的日誌記錄

127.0.0.1 - - [16/May/2020 23:00:28] "POST /predict HTTP/1.1" 200 -
text =  i am flying from boston to the bay area
seq_len =  9
0	i	O
1	am	O
2	flying	O
3	from	O
4	boston	B-fromloc.city_name
5	to	O
6	the	O
7	bay	I-toloc.city_name
8	area	O

MSRA 新聞數據集項目

我們項目的數據集 中文數據集下載 ,點擊下載即可,這個 MSRA-NER 數據集是在新聞語料上進行的序列標註。下載完成得到 dh_msra.zip,解壓即可使用。

BiLSTM_CRF tensorflow 實現一個版本 ,這是我從 github 上找的一個版本,大家可以學習。

我們接下來會實現一個 BERT_CRF PyTorch 版本。主要考慮 PyTorch 語法簡單易上手,BERT 在 NLP 領域各個比賽榜單都刷爆了。總之,BERT 重要,太重要了,學習 NLP 就必須掌握 BERT,並且在工業界得到了應用。

數據分析

對 dh_msra.zip 中文的數據集切分訓練集、驗證集、測試集。

關於數據分析我們通過 pyecharts 進行一個可視化分析,便於我們的效果展示。 我們實際算法工作中關於數據分析以及特徵提取佔用我們 70%左右的時間,故瞭解我們的業務數據非常重要的。

關於更多的 pyecharts 內容請參考

Python數據可視化 pyecharts實戰

Python數據分析案例實戰 視頻課程

  • 數據 Example 分佈

圖片

這裏給出訓練數據、驗證數據以及測試數據句子的長度

  • 標籤類別數據分佈
from pyecharts import  options as opts
from pyecharts.charts import Bar
def bar_charts()->Bar():
    c = Bar()
    c.add_xaxis(xaxis_data=keys)
    c.add_yaxis(series_name='train_TAG-數量統計',yaxis_data=train_tags) 
    return c
c = bar_charts()
c.render_notebook()

圖片

圖片

圖片

從上述 train、dev、test 發現,數據的 TAG

  • 文章句子長度分佈

通過分析自己業務句子的長度,可以在訓練的時候 max_seq_len 進行設置合理的數值。

圖片圖片

通過上述分析:

數據長度最大的長度整體在 80 左右,我們在通過 boxplot 那麼我們在訓練 bert 的時候 max_seq_len 可以設置 60 左右

NER 模型訓練

python3 main.py  \
--model_name_or_path ../pretrained_models/bert-base-chinese/ \
--task  msra \
--model_type  bert \
--model_dir msra_bert_base_zh_model  \
--do_train  --do_eval --use_crf   \
--num_train_epochs  3 \
--train_batch_size 64 \
--eval_batch_size 64  \
--max_seq_len 64 

NVIDIA GeForce GTX 1080 12G 顯存,我們 3 次迭代單卡運行 20 分鐘 。如果大家是 cpu 環境下進行訓練的話,可以自己抽取一部分小的數據進行訓練,保障可以允許即可。如果機器資源允許的情況下,可以調大 train_batch_size ,可以加快訓練的速度。訓練結果如下:

INFO - train -   ***** Eval [**dev**] results 
INFO - train -              precision    recall  f1-score   support
      ORG       0.86      0.94      0.90      1601
      LOC       0.92      0.96      0.94      2562
      PER       0.97      0.97      0.97      1811
micro avg       0.92      0.96      0.94      5974
macro avg       0.92      0.96      0.94      5974

INFO - train -     loss = 1.0743800858999122
INFO - train -     sementic_frame_acc = 0.9231186685962374
INFO - train -     slot_**f1 = 0.9369517094367467**
INFO - train -     slot_precision = 0.918206652739836
INFO - train -     slot_recall = 0.9564780716437897

INFO - train -   ***** Eval [**test**] results *****
INFO - train -              precision    recall  f1-score   support
      LOC       0.95      0.93      0.94      2935
      PER       0.96      0.96      0.96      1998
      ORG       0.85      0.91      0.88      1426
micro avg       0.93      0.94      0.94      6359
macro avg       0.93      0.94      0.94      6359
INFO - train -     loss = 1.006102637312878
INFO - train -     sementic_frame_acc = 0.9249547920433996
INFO - train -     slot_**f1 = 0.9350995453832889**
INFO - train -     slot_precision = 0.9321769026410377
INFO - train -     slot_recall = 0.9380405724170467

NER 模型在線預測

我們通過 gpu 下訓練的模型,也可以直接運行在 cpu 下。

python3 api.py \
--model_name_or_path ../pretrained_models/bert-base-chinese/ \
--task  msra  \
--model_type  bert  \
--model_dir msra_bert_base_zh_model \
--use_crf 

注意:model_name_or_path 和 model_dir 換成自己預訓練模型路徑和模型文件路徑

預測效率對比:gpu 單條記錄預測 13ms 左右,cpu 大概 60ms(和服務器配置有關係)。對於 cpu 下推理速度慢的問題我們也可以針對模型進行優化(比如:albert-tiny…)

**在線預測命令行如下: **

curl http://127.0.0.1:8000/predict \
-H "Content-Type:application/json" \
-X POST \
--data '{"text": "沈福利畢業於北京工業大學,位於北京市朝陽區","lang":"zh"}'  

圖片

返回結果 :


{

  "errno": 0, 

  "errmsg": "success", 

**  "time": 16, **

  "data": [

    {

      "word": "沈", 

      "tag": "B-PER"

    }, 

    {

      "word": "福", 

      "tag": "I-PER"

    }, 

    {

      "word": "利", 

      "tag": "I-PER"

    }, 

    {

      "word": "畢", 

      "tag": "O"

    }, 

    {

      "word": "業", 

      "tag": "O"

    }, 

    {

      "word": "於", 

      "tag": "O"

    }, 

    {

      "word": "北", 

      "tag": "B-ORG"

    }, 

    {

      "word": "京", 

      "tag": "I-ORG"

    }, 

    {

      "word": "工", 

      "tag": "I-ORG"

    }, 

    {

      "word": "業", 

      "tag": "I-ORG"

    }, 

    {

      "word": "大", 

      "tag": "I-ORG"

    }, 

    {

      "word": "學", 

      "tag": "I-ORG"

    }, 

    {

      "word": ",", 

      "tag": "O"

    }, 

    {

      "word": "位", 

      "tag": "O"

    }, 

    {

      "word": "於", 

      "tag": "O"

    }, 

    {

      "word": "北", 

      "tag": "B-LOC"

    }, 

    {

      "word": "京", 

      "tag": "I-LOC"

    }, 

    {

      "word": "市", 

      "tag": "I-LOC"

    }, 

    {

      "word": "朝", 

      "tag": "B-LOC"

    }, 

    {

      "word": "陽", 

      "tag": "I-LOC"

    }, 

    {

      "word": "區", 

      "tag": "I-LOC"

    }

  ]

}

我們看下後臺服務器日誌數據

圖片

我們可以得出這樣的結果:

**沈福利**畢業於北京工業大學,位於北京市朝陽區

我們就可以把每個類型的 TAG 都提取出來了。

NLP 比賽 音樂領域語義理解

數據是主要來自人機對話系統中音樂領域以及非音樂領域的真實用戶請求記錄。

音樂類槽位填充項目

中文分詞以及詞性標註

針對中文分詞以及詞性標註問題實際上是一個序列標註任務,屬於 NER 功能,下面我們簡單瞭解下。一般選擇的方案:BiLSTM-CRF 或者 BERT_CRF.。下面我們採用 BERT_CRF 來進行實驗,實際使用的過程,規則字典+模型一起來完成的,我們這裏學習下如何使用NER 模型來進行分詞( 大家可以嘗試bilstm_crf ,目前工業界常用,主要基於推測性能來考慮的 ) ,本文實驗我們選擇了幾種詞性進行( [‘N’, ‘V’, ‘NZ’, ‘W’, ‘VN’, ‘MQ’, ‘D’, ‘T’, ‘UDE1’, ‘A’, ‘P’, ‘NR’, ‘VI’, ‘NNT’, ‘NT’, ‘NS’, ‘M’, ‘F’, ‘C’, ‘RR’])

數據分析

對 people-2014 人民日報 POS 詞性標註數據數據集切分訓練集、驗證集、測試集。

關於數據分析我們通過 pyecharts 進行一個可視化分析,便於我們的效果展示。 我們實際算法工作中關於數據分析以及特徵提取佔用我們 70%左右的時間,故瞭解我們的業務數據非常重要的。

關於更多的 pyecharts 內容請參考

Python數據可視化 pyecharts實戰

Python數據分析案例實戰 視頻課程

  • 數據 Example 分佈

這裏給出訓練數據、驗證數據以及測試數據句子的記錄數

圖片

  • 標籤類別數據分佈

圖片

圖片

圖片

從上述 train、dev、test 發現,數據的 TAG

  • 文章句子長度分佈

通過分析自己業務句子的長度,可以在訓練的時候 max_seq_len 進行設置合理的數值。

圖片圖片

通過上述分析:

數據長度最大的長度整體在 200 左右,我們在通過 boxplot 那麼我們在訓練 bert 的時候 max_seq_len 可以設置 200 左右(多數據分佈在 64 左右,爲加速訓練速度,可以訓練時候可以設置一個比較小的數值)

NER 模型訓練

這裏給出 ubuntu 環境下 pytorch 配置環境

export PATH=/home/ubuntu/anaconda3/bin:$PATH

export PATH=/usr/local/cuda-9.0/bin:$PATH

export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64:$LD_LIBRARY_PATH

export LIBRARY_PATH=/usr/local/cuda-9.0/lib64:$LIBRARY_PATH

python3 main.py  \
--model_name_or_path ../pretrained_models/bert-base-chinese/ \
--task  people-2014  \
--model_type  bert \
--model_dir people2014_bert_base_zh_model  \
--do_train  --do_eval --use_crf   \
--num_train_epochs 3  \
--train_batch_size 32 \
--eval_batch_size 64  \
--max_seq_len 64

我們實驗使用單卡 GTX1080ti GPU,每個迭代1.5 小時。這裏訓練3次迭代效果(大家可以可以嘗試更多):

 INFO - train -              precision    recall  f1-score   support

       NT       0.89      0.90      0.90      7307
        V       0.99      0.98      0.99    165986
        D       0.99      0.99      0.99     61665
        T       0.99      0.99      0.99     28097
     UDE1       1.00      1.00      1.00     51574
        N       0.97      0.97      0.97    185587
       VN       0.98      0.98      0.98     45969
       NZ       0.90      0.90      0.90     69613
        P       1.00      1.00      1.00     47142
      NNT       0.98      0.99      0.98     18146
        F       0.99      0.99      0.99     23310
        M       0.99      0.98      0.98     12727
       VI       0.98      0.98      0.98     22278
       MQ       0.98      0.99      0.99     34141
       RR       1.00      1.00      1.00     17288
       NR       0.97      0.97      0.97     21167
        A       0.98      0.98      0.98     31482
        C       1.00      1.00      1.00     14431
       NS       0.96      0.96      0.96     17992

micro avg       0.98      0.98      0.98    875902
macro avg       0.98      0.98      0.98    875902

INFO - train -     loss = 1.8359935450942124
INFO - train -     sementic_frame_acc = 0.8029136970713302
INFO - train -     slot_f1 = 0.9759650342340757
INFO - train -     slot_precision = 0.9765579723812039
INFO - train -     slot_recall = 0.975372815680293

大家可以自己嘗試更多的參數進行訓練

  • 增大 num_train_epochs
  • max_seq_len 可以設置 256(通過數據分析發現)
  • 在進行這類序列任務,如果有多卡,可以利用多卡並行提高訓練數據

這裏對主要的詞性進行說明,更多可以參考 。 具體實際應用,大家可以標準更多地數據來進分詞效果實驗。

 NR(人名)    
 VI(動詞)   
  DE1(的)    
  C( 連詞)  
  V(動詞)    
 NS(地名)    
 MQ     
  D       
  N(名詞)    
  A(形容詞)  
 NT(機構團體)
 NZ(其它專名)
 VN(名動詞)  
   RR       
  T(時間詞)  
  M(數詞)    
  NNT       
  F(方位詞)  
  P(介詞)    

NER 模型在線預測

python3 api.py \
--model_name_or_path ../pretrained_models/bert-base-chinese/ \
--task  people-2014  \
--model_type  bert  \
--model_dir people2014_bert_base_zh_model  \
--use_crf 

注意:model_name_or_path 和 model_dir 換成自己預訓練模型路徑和模型文件路徑

預測效率對比:gpu 單條記錄預測 13ms 左右,cpu 大概 60ms(和服務器配置有關係)。對於 cpu 下推理速度慢的問題我們也可以針對模型進行優化(比如:albert-tiny…)

**在線預測命令行如下: **

query = 從北京到上海怎麼走

識別介詞:從

識別地名:北京、上海

其他名詞:怎麼走

1)執行命令
curl http://127.0.0.1:8000/predict -H "Content-Type:application/json" -X POST --data '{"text": "從北京到上海怎麼走","lang":"zh"}'2) 返回結果
text =  從北京到上海怎麼走
seq_len =  9
0       從      S-P
1       北      B-NS
2       京      I-NS
3       到      S-V
4       上      B-NS
5       海      I-NS
6       怎      B-NZ
7       麼      I-NZ
8       走      I-NZ
  • query = 我要去北京市海淀區中關村大街

地名識別 NS: 北京市、海淀區

專有名詞: 中關村大街

(1)執行命令
curl http://127.0.0.1:8000/predict -H "Content-Type:application/json" -X POST --data '{"text": "我要去北京市海淀區中關村大街","lang":"zh"}'
(2)返回結果
text =  我要去北京市海淀區中關村大街
seq_len =  14
0       我      S-RR
1       要      S-V
2       去      O
3       北      B-NS
4       京      I-NS
5       市      I-NS
6       海      B-NS
7       澱      I-NS
8       區      I-NS
9       中      B-NZ
10      關      I-NZ
11      村      I-NZ
12      大      I-NZ
13      街      I-NZ
  • query =播放一首周杰倫的歌曲

動詞: 播放

人名:周杰倫

普通名稱: 歌曲

(1) 執行命令
curl http://127.0.0.1:8000/predict -H "Content-Type:application/json" -X POST --data '{"text": "播放一首周杰倫的歌曲","lang":"zh"}'
(2)返回結果
text =  播放一首周杰倫的歌
seq_len =  9
0       播      B-V
1       放      I-V
2       一      B-MQ
3       首      I-MQ
4       周      B-NR
5       傑      I-NR
6       倫      I-NR
7       的      S-UDE1
8       歌      B-N
9       曲      I-N

附錄-拓展學習資料

下面給大家提供一些學習資料,供大家自己學習,作爲課堂外的內容。

CoNLL-2003

https://www.aclweb.org/anthology/W03-0419.pdf

https://www.clips.uantwerpen.be/conll2003/ner/

https://yuanxiaosc.github.io/2018/12/26/%E5%91%BD%E5%90%8D%E5%AE%9E%E4%BD%93%E8%AF%86%E5%88%ABCoNLL2003/

https://github.com/yuanxiaosc/BERT-for-Sequence-Labeling-and-Text-Classification

如何訓練小模型

NLPCC2020 NER 項目

https://github.com/CLUEbenchmark/CLUENER2020

https://www.cluebenchmarks.com/introduce.html

https://www.cluebenchmarks.com/NLPCC.html

https://zhuanlan.zhihu.com/p/102676719?utm_source=wechat_timeline

把BERT的推斷速度提升17倍

下面我們做一些的嘗試

1/9 的 bert_base < 12M

**數據 **

  • 160G+原始數據
  • 35G+的通用數據
  • 3700+預訓練模型
  • 256 的預處理長度

模型

我們可以考慮 bert_base 修改 6 層看看效果 。

“num_hidden_layers”: 12-> “num_hidden_layers”: 6

“max_position_embeddings”: 512-> “max_position_embeddings”: 256

v100-32G 8 卡混合精度訓練

wwm-mlm

結果

  • loss 在 1.5->1.8 抖動

2000qps 20gpu-> 2000qps 1gpu

推理優化方案

  • Tensorflow serving Batching
  • FP16 量化
  • Faster Transformer

中文版本 zh-albert

我們直接使用 albert_zh 中已經轉好的版本, 點擊下載

對話系統

[1] 小愛:語音識別和 NLP 在語音交互中的實踐

[2] 美團對話理解技術及實踐

[3] 小米NLU2018

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章