生活随笔
收集整理的這篇文章主要介紹了
NLP(三十九)使用keras-bert实现完形填空及简单的文本纠错功能
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
??在之前的系列文章中,筆者介紹了如何使用keras-bert來調用BERT模型,實現文本多分類,文本多標簽分類以及序列標注任務,文章如下:
- NLP(三十四)使用keras-bert實現序列標注任務
- NLP(三十五)使用keras-bert實現文本多分類任務
- NLP(三十六)使用keras-bert實現文本多標簽分類任務
在本文中,筆者將介紹如何使用keras-bert來調用BERT模型使用完形填空及簡單的文本糾錯功能。
完形填空
??首先,我們來了解下什么是完形填空。所謂完形填空,指的是將句子中缺失的單詞(或字)補充成正確的單詞(或字)。舉個簡單的例子:
在上圖中,第一行是原始句子,第二行是需要完形填空的句子,在這里我們把閔行區的行字缺失掉,即MASK掉,第三行為補充的漢字:行。
??在BERT模型中,它的任務是由兩個自監督任務組成,即MLM和NSP。我們需要了解下MLM。
??MLM的全稱是Masked Language Model,所謂MLM是指在訓練的時候隨即從輸入預料上mask掉一些單詞,然后通過的上下文預測該單詞,該任務非常像我們在中學時期經常做的完形填空。
??在BERT的實驗中,15%的WordPiece Token會被隨機Mask掉。在訓練模型時,一個句子會被多次喂到模型中用于參數學習,但是Google并沒有在每次都mask掉這些單詞,而是在確定要Mask掉的單詞之后,80%的時候會直接替換為[Mask],10%的時候將其替換為其它任意單詞,10%的時候會保留原始Token。
??基于BERT模型的這個特性,我們嘗試著利用keras-bert來調用它解決完形填空問題。實現完形填空的代碼(cloze_predict.py)如下:
import numpy
as np
from keras_bert
import Tokenizer
from keras_bert
import load_trained_model_from_checkpoint
dict_path
= './chinese_L-12_H-768_A-12/vocab.txt'
token_dict
= {}
with open(dict_path
, 'r', encoding
='utf-8') as reader
:for line
in reader
:token
= line
.strip
()token_dict
[token
] = len(token_dict
)id_token_dict
= {v
: k
for k
, v
in token_dict
.items
()}class OurTokenizer(Tokenizer
):def _tokenize(self
, text
):R
= []for c
in text
:if c
in self
._token_dict
:R
.append
(c
)else:R
.append
('[UNK]')return Rtokenizer
= OurTokenizer
(token_dict
)
model_path
= "./chinese_L-12_H-768_A-12/"
bert_model
= load_trained_model_from_checkpoint
(model_path
+ "bert_config.json",model_path
+ "bert_model.ckpt",training
=True
)
def get_mask_character(start_string
, mask_num
, end_string
):string
= list(start_string
) + ['MASK'] * mask_num
+ list(end_string
)token_ids
, segment_ids
= tokenizer
.encode
(string
, max_len
=512)for i
in range(mask_num
):token_ids
[len(start_string
)+i
+1] = tokenizer
._token_dict
['[MASK]']masks
= [0] * 512for i
in range(mask_num
):masks
[len(start_string
)+i
+1] = 1predicts
= bert_model
.predict
([np
.array
([token_ids
]), np
.array
([segment_ids
]), np
.array
([masks
])])[0]pred_indice
= predicts
[0][len(start_string
)+1:len(start_string
)+mask_num
+1].argmax
(axis
=1).tolist
()return [id_token_dict
[_
] for _
in pred_indice
]if __name__
== '__main__':start_str1
= "白云山,位于"end_str1
= "廣州市白云區,為南粵名山之一,自古就有“羊城第一秀”之稱。"pred_chars
= get_mask_character
(start_str1
, 3, end_str1
)print(pred_chars
)start_str2
= "首先,從"end_str2
= "看,騰訊和阿里市值已經有2500億,而百度才500多億,是BAT體量中最小的一家公司。"pred_chars
= get_mask_character
(start_str2
, 2, end_str2
)print(pred_chars
)start_str3
= "特斯拉CEO埃隆·馬斯克的個人凈資產升至1850億美元,超越亞馬遜CEO貝索斯榮登"end_str3
= "第一大富豪。"pred_chars
= get_mask_character
(start_str3
, 2, end_str3
)print(pred_chars
)start_str4
= "我在上海閔"end_str4
= "區工作。"pred_chars
= get_mask_character
(start_str4
, 1, end_str4
)print(pred_chars
)
注意keras-bert來調用BERT時,如果需要開啟MLM和NSP任務時,需要將training設置為True,然后再調用MLM模型對文本中MASK掉的部分進行預測。運行腳本的輸出結果如下:
['廣', '東', '省']
['市', '值']
['全', '球']
['行']
簡單的文本糾錯功能
??基于上述的完形填空,我們還可以完成簡單的文本糾錯功能,前提是我們已經知道文本的哪個字是錯誤的,并且進行一對一糾錯,即把這個字糾正為正確的字,并不會將其去掉或者添加其它字。我們的思路是這樣的:在知道文本中的哪個字是錯誤的之后,將其MASK掉,轉化為完形填空任務,從而預測出MASK掉的字作為糾正后的字。
??實現簡單的文本糾錯功能的Python代碼如下:
from cloze_predict
import get_mask_charactersentence
= "我要去埃及金子塔玩。"
sentence
= "白云山,位于廣東省廣州市白云區,為南粵名山之一,自古就有“羊城第一秀”只稱。"
sentence
= "請把這個快遞送到上海市閔航區。"
sentence
= "少先隊員因該為老人讓坐"
sentence
= "隨然今天很熱"
sentence
= "我生病了,咳數了好幾天"
sentence
= "一群羅威納犬寶寶打架,場面感忍。"
wrong_char_index
= sentence
.index
("忍")for i
in range(len(sentence
)):if i
== wrong_char_index
:start_string
= sentence
[:i
]end_string
= sentence
[i
+1:]pred_char
= get_mask_character
(start_string
, 1, end_string
)print("wrong char: {}, correct char: {}".format(sentence
[i
], pred_char
[0]))
輸出結果為:
wrong char: 忍, correct char: 人
??這種文本糾錯方式利用了BERT的MLM模型來實現的,有一定的效果,但不能作為文本糾錯的完美實現方式,只是作為文本糾錯的一種實現方式,實際上,現實中的文本糾錯是由多種模型組成的復雜策略實現的,還得考慮效果和運行效率等因素。另外,真正的文本糾錯還應當能指出文本中哪個字錯了并對其糾錯,本文只考慮了后一步,而沒有指出文本中哪個字錯了,只能算文本糾錯的一次嘗試。
總結
??本文給出的腳本已上傳至Github,網址為:https://github.com/percent4/keras_bert_cloze ,上面有更多的例子,歡迎大家參考~
??感謝大家的閱讀~
??2021.1.24于上海浦東
總結
以上是生活随笔為你收集整理的NLP(三十九)使用keras-bert实现完形填空及简单的文本纠错功能的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。