EasyNLP整合K-BERT演算法,藉助知識圖譜實現更優Finetune 導讀

阿里雲大資料AI技術發表於2022-08-15
作者:汪誠愚 張濤林 黃俊

導讀

知識圖譜(Knowledge Graph)的概念⾸次出現2012年,由Google提出,它作為⼀種⼤規模語義⽹絡, 準確地描述了實體以及實體之間的關係。知識圖譜最早應⽤於搜尋引擎,⽤於準備返回⽤戶所需的知識。隨著預訓練語⾔模型的不斷髮展,將知識圖譜中的知識三元組融⼊預訓練模型,對提升模型的效果有重要的作⽤。經典的知識注⼊演算法直接將知識圖譜中實體的詞嵌⼊向量注⼊預訓練模型的詞嵌⼊向量中;然⽽,知識圖譜中實體的詞嵌⼊向量和預訓練模型的詞嵌⼊向量的向量空間不⼀致,⽽且容易引起知識噪⾳(Knowledge Noise)的問題。K-BERT演算法提出利⽤Visible Matrix在BERT模型中引⼊外部知識,具有較好的效果。 因此,我們在EasyNLP這⼀演算法框架中整合了K-BERT演算法,使⽤戶在具有知識圖譜的情況下,取得更好的模型Finetune效果。

EasyNLP( )是阿⾥雲機器學習PAI 團隊基於 PyTorch 開發的易⽤且豐富的中⽂NLP演算法框架,⽀持常⽤的中⽂預訓練模型和⼤模型落地技術,並且提供了從訓練到部署的⼀站式 NLP 開發體驗。EasyNLP 提供了簡潔的接⼝供⽤戶開發 NLP 模型,包括NLP應⽤ AppZoo 和預訓練 ModelZoo,同時提供技術幫助⽤戶⾼效的落地超⼤預訓練模型到業務。由於跨模態理解需求的不斷增加,EasyNLP也⽀持各種跨模態模型,特別是中⽂領域的跨模態模型,推向開源社群,希望能夠服務更多的 NLP 和多模態演算法開發者和研 究者,也希望和社群⼀起推動 NLP /多模態技術的發展和模型落地。

本⽂簡要介紹K-BERT的技術解讀,以及如何在EasyNLP框架中使⽤K-BERT模型。

K-BERT模型詳解

BERT等預訓練語言模型從大規模語料庫中捕獲文字語言表示,但缺乏領域特定的知識。而領域專家在閱讀領域文字時,會利用相關知識進行推理。為了實現這一功能,K-BERT提出了面向知識圖譜的知識增強語言模型,將三元組作為領域知識注入到句子中。然而,過多的知識融入會導致知識噪音,使句子偏離其正確的含義。為了克服知識噪音, K-BERT引入了Soft-position和Visibel Matrix來限制知識的影響。由於K-BERT能夠從預訓練的BERT中載入模型引數,因此透過配備KG,可以很容易地將領域知識注入到模型中,而不需要對模型進行預訓練。K-BERT的模型架構和知識注入的應用示例如下所示:


特別地,在模型的輸入層,K-BERT表徵層透過位置索引將語句樹轉換為句子,構造三種表徵方式:Token表徵、Soft-position表徵和Segment表徵。其中Soft-position表徵作為位置嵌入,為重排的序列提供句子結構資訊。此外,透過Visible Matrix來覆蓋不應該看到的Token,避免了知識噪聲問題。如下圖所示,以Beijing為例,給定知識三元組(Beijing,capital,China),K-BERT透過Visible Matrix限制只有Beijing能“看到”其相關的關係詞和賓語,分別為“capital”和“China”。與之相反,一個知識無關的詞now則無法“看到”“capital”和“China”。

從作者論文中我們也可以看到K-BERT中的Attention Matrix的計算過程:

其中,M即為Visible Matrix,為了表示K-BERT輸入Token序列能否互相“看見”,定義M如下:

因此,當兩個Token互相可以“看見”,M矩陣對應的元素值為0,因此Attention Matrix的計算過程和普通BERT相同。反之,當兩個Token不能互相“看見”,M矩陣對應的元素值為負無窮,對應SoftMax函式後的權重則會趨於0,這使得這兩個Token在Self-Attention計算過程中互無影響。這就在計算過程中,大大緩解了知識圖譜增強過程的知識噪聲問題。

K-BERT模型的實現與效果

在EasyNLP框架中,我們在模型層構建了K-BERT模型的Backbone,其核⼼程式碼如下所示:

self.kbert = KBertModel(config, add_pooling_layer=False)
self.cls = KBertOnlyMLMHead(config)
outputs = self.kbert(
    input_ids,
    attention_mask=attention_mask,
    token_type_ids=token_type_ids,
    position_ids=position_ids,
    head_mask=head_mask,
    inputs_embeds=inputs_embeds,
    encoder_hidden_states=encoder_hidden_states,
    encoder_attention_mask=encoder_attention_mask,
    output_attentions=output_attentions,
    output_hidden_states=output_hidden_states,
    return_dict=return_dict,
)
sequence_output = outputs[0]
prediction_scores = self.cls(sequence_output)
loss_fct = CrossEntropyLoss()
masked_lm_loss = loss_fct(prediction_scores.view(-1, self.config.vocab_size), labels.view(-1))

其中,在K-BERT中,模型Backbone的Attention Mask由兩個Matrix加和而成,分別為普通的Attention Mask和Visible Matrix,實現核心程式碼如下:

extended_attention_mask = self.get_extended_attention_mask(attention_mask, input_shape, device) + self.get_extended_attention_mask(visible_matrix, input_shape, device)

在資料預處理過程中,我們需要獲得當前樣本的輸入文字和知識三元組,從而計算出Visible Matrix:

 if self.kbert_model_prefix:
        encoding['input_ids'], encoding['token_type_ids'], encoding['attention_mask'], encoding['position_ids'], encoding['visible_matrix'] = self.kbert_row_data_process(encoding['input_ids'], encoding['token_type_ids'], encoding['attention_mask'])

為了驗證EasyNLP框架中K-BERT模型在各種任務上的精度,我們在多個公開資料集上驗證了句子分類和NER任務的效果。我們使用EasyNLP載入了BERT模型,對比復現結果和K-BERT官方論文的結果,如下所示:

可以透過上述結果,驗證EasyNLP框架中K-BERT演算法實現的正確性。

K-BERT模型使⽤教程

以下我們簡要介紹如何在EasyNLP框架使⽤K-BERT模型。

安裝EasyNLP

⽤戶可以直接參考 )上的說明安裝EasyNLP演算法框架。

資料準備

K-BERT是一個finetune模型,需要使用者準備下遊任務的訓練與驗證資料,為tsv檔案。對於文字分類任務,這⼀⽂件包含以製表符\t分隔的三列,第一列是標籤,第二列是句子序號,第三列是文字句子。樣例如下:

0	25	作者肯定是手頭有一本年表和名冊的,人物事件行動完全扣合正史,人物性格也多有《百家講壇》為證,人物年齡的bug比紅樓夢還少,敘述事件某某年某某月某某伐某某不厭其煩,可是切合歷史絕不是說它是好小說的理由啊!我覺得瑪麗蘇都不是致命傷,關鍵是情節幼稚看不下去啊!

對於NER任務,同樣為一個tsv檔案,由\t分隔為文字和label兩列,文字字與字之間用空格隔開。樣例如下:

獵 豹 移 動 方 面 解 釋 稱 , 移 動 收 入 和 海 外 收 入 的 增 長 主 要 得 益 於 L i v e . m e 產 品 在 海 外 市 場 的 快 速 增 長 。	B-ORG I-ORG I-ORG I-ORG O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O

下列⽂件已經完成預處理,可⽤於測試:


K-BERT⽂本分類示例

在文字分類任務中,我們採⽤以下命令對K-BERT模型進⾏finetune,模型在finetune過程中也會自動輸出評估結果。其中,使用者可以在前述預處理示例檔案中找到訓練集chnsenticorp/train.tsv、評測集chnsenticorp/dev.tsv以及知識圖譜檔案kbert_kgs/HowNet.spo。kbert_cls.py位於EasyNLP專案下的examples/kbert/下。相關示例程式碼如下:

python kbert_cls.py \
--mode train \
--tables tmp/kbert_data/chnsenticorp/train.tsv,tmp/kbert_data/chnsenticorp/dev.tsv \
--input_schema label:str:1,sid1:str:1,sent1:str:1 \
--first_sequence sent1 \
--label_name label\
--label_enumerate_values 0,1 \
--checkpoint_dir ./tmp/kbert_classification_model/ \
--learning_rate 2e-5 \
--epoch_num 2 \
--random_seed 42 \
--save_checkpoint_steps 50 \
--sequence_length 128 \
--micro_batch_size 16 \
--app_name text_classify \
--user_defined_parameters "pretrain_model_name_or_path=kbert-base-chinese kg_file=tmp/kbert_data/kbert_kgs/HowNet.spo"

K-BERT命名實體識別示例

在NER任務中,我們採⽤以下命令對K-BERT模型進⾏finetune,其使用方式與文字分類相同:

python kbert_ner.py \
--mode train \
--tables tmp/kbert_data/financial_ner/train.tsv,tmp/kbert_data/financial_ner/dev.tsv \
--input_schema content:str:1,label:str:1 \
--first_sequence content \
--label_name label\
--label_enumerate_values B-ORG,B-PER,B-POS,I-ORG,I-PER,I-POS,O \
--checkpoint_dir ./tmp/kbert_ner_model/ \
--learning_rate 2e-5 \
--epoch_num 2 \
--random_seed 42 \
--save_checkpoint_steps 50 \
--sequence_length 128 \
--micro_batch_size 16 \
--app_name sequence_labeling \
--user_defined_parameters "pretrain_model_name_or_path=kbert-base-chinese kg_file=tmp/kbert_data/kbert_kgs/HowNet.spo"

未來展望

在未來,我們計劃在EasyNLP框架中整合更多中⽂知識模型,覆蓋各個常⻅中⽂領域,敬請期待。我們 也將在EasyNLP框架中整合更多SOTA模型(特別是中⽂模型),來⽀持各種NLP和多模態任務。此外, 阿⾥雲機器學習PAI團隊也在持續推進中⽂多模態模型的⾃研⼯作,歡迎⽤戶持續關注我們,也歡迎加⼊ 我們的開源社群,共建中⽂NLP和多模態演算法庫!

Github地址:

Reference

  1. Chengyu Wang, Minghui Qiu, Taolin Zhang, Tingting Liu, Lei Li, Jianing Wang, Ming Wang, Jun Huang, Wei Lin. EasyNLP: A Comprehensive and Easy-to-use Toolkit for Natural Language Processing. arXiv
  2. Weijie Liu, Peng Zhou, Zhe Zhao, Zhiruo Wang, Qi Ju, Haotang Deng, and Ping Wang. 2020. K-BERT: Enabling Language Representation with Knowledge Graph. In AAAI. 2901–2908
  3. K-BERT原作者開原始碼:

阿里靈傑回顧


    來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70004426/viewspace-2910422/,如需轉載,請註明出處,否則將追究法律責任。

    相關文章