廣告行業中那些趣事系列8:詳解BERT中分類器源碼

2020-12-14 數據拾光者
最全文章請關注微信公眾號:數據拾光者

摘要:BERT是近幾年NLP領域中具有裡程碑意義的存在。因為效果好和應用範圍廣所以被廣泛應用於科學研究和工程項目中。廣告系列中前幾篇文章有從理論的方面講過BERT的原理,也有從實戰的方面講過使用BERT構建分類模型。本篇從源碼的角度從整體到局部分析BERT模型中分類器部分的源碼。

目錄

01 整體模塊劃分

02 數據處理模塊

03 特徵處理模塊

04 模型構建模塊

05 模型運行模塊

06 其他模塊

總結

01 整體模塊劃分

對於機器學習工程師來說,會調包跑程序應該是萬裡長徵的第一步。這一步主要是幫助我們迅速將模型應用到實際業務中,並且提升自信心,但這還遠遠不夠。要想根據不同的業務場景更好的使用模型,我們需要深層次的理解模型,讀點源碼才能走的更遠。

本篇解讀的是BERT開源項目中分類器部分的源碼,從最開始的數據輸入到模型運行整個流程主要可以分成數據處理模塊、特徵處理模塊、模型構建模塊和模型運行模塊。具體如下圖所示:

圖1 BERT分類器整體模塊劃分

因為原生態BERT預訓練模型動輒幾百兆甚至上千兆的大小,模型訓練速度非常慢,對於BERT模型線上化非常不友好,所以使用目前比較火的BERT最新派生產品ALBERT來完成BERT線上化服務。ALBERT使用參數減少技術來降低內存消耗從而最終達到提高BERT的訓練速度,並且在主要基準測試中均名列前茅,可謂跑的快,還跑的好。本篇解讀的BERT源碼也是基於ALBERT開源項目。

項目開源的github工程:https://github.com/wilsonlsm006/albert_zh

主要解讀分類器部分的源碼,代碼及注釋在run_classifier.py文件,歡迎小夥伴們fork。

02 數據處理模塊

數據處理模塊主要負責數據讀入和預處理功能。

數據處理主要由數據處理器DataProcessor來完成。根據不同的任務會有不同的數據處理器子類,這裡的不同表現在數據讀入方式和數據預處理方面。

1. 數據讀入方式

實際項目中數據讀入的方式多種多樣,比如csv、tsv、txt等。比如有的項目是需要讀取csv文件,而有的則需要tsv或者txt格式。我們可以構建自定義的數據處理器來完成不同的項目需求。

2. 數據預處理

數據預處理是根據不同的NLP任務來完成不同的操作,比如單句分類任務我們需要的是text_a和label格式。而句子相似關係判斷任務需要的是text_a,text_b,label格式。其他任務也是類似的,根據不同的NLP任務來完成數據預處理操作。

通過一個類圖來講解源碼中的數據處理器:

圖2 數據處理器類圖

對應到項目源碼中,我們有一個DataProcessor父類。父類中有五個方法,分別是讀取tsv文件、獲得訓練集、獲得驗證集、獲得測試集和獲得標籤。這裡可根據業務需求增刪改獲取文件類型的函數,比如讀取csv可以添加get_csv(input_file)等等。

下面兩個子類,分別是處理句子關係判斷任務的SentencePairClassificationProcessor數據處理器和LCQMCPairClassificationProcessor分類的數據處理器。前面文章有講過如果需要做單句分類的任務我們可以在這裡添加一個SentenceClassifierProcess進行定製化開發。

對應到項目源碼中,因為我們是句子關係判斷任務,其實就是判斷兩句話是不是有關係,這裡我們得到的最終數據格式是列表類型,具體數據格式如下:

[(guid,text_a,text_b,label),(guid,text_a,text_b,label),....]

其中guid作為唯一識別text_a和text_b句子對的標誌,可以理解為該條樣例的唯一id;

text_a和text_b是需要判斷的兩個句子;

label欄位就是標籤,如果兩句話相似則置為1,否則為0。

上面四個欄位guid和text_a是必須的。text_b是可選的,如果為空則變成單句分類任務,不為空則是句子關係判斷任務。label在訓練集和驗證集是必須的,在測試集中可以不提供。

具體代碼在SentencePairClassificationProcessor子類的_create_examples函數:

03 特徵處理模塊

特徵處理模塊主要的功能是將數據處理模塊得到的數據轉化成特徵並持久化到TFRecord文件中,由file_based_convert_examples_to_features函數完成。

1. 預處理數據轉化成特徵

數據轉化成特徵的操作主要由函數convert_single_example完成。傳統的機器學習需要從數據中抽取特徵,NLP任務是對文本進行分詞等操作獲取特徵。BERT模型中默認每個字字就是一個詞。

論文中BERT模型的輸入轉化成特徵如下圖所示:

圖3 句子輸入轉化成三層Embedding

這裡需要注意下對text_a和text_b的預處理操作。首先會進行標記化將text_a和text_b轉化成tokens_a和tokens_b。如果tokens_b存在,那麼tokens_a和tokens_b的長度就不能超過max_seq_length-3,因為需要加入cls,sep,seq三個符號;如果tokens_b不存在,那麼tokens_a的長度不能超過

max_seq_length -2 ,因為需要加入 cls 和 sep符號。

這裡通過一條具體的數據轉化成特徵說明上述流程。現在我們的example中有一條數據,分別有三個欄位:

text_a: 這種圖片是用什麼軟體製作的?

text_b: 這種圖片製作是用什麼軟體呢?

label: 1

經過分詞之後,我們會得到:

tokens: [CLS] 這 種 圖 片 是 用 什 麼 軟 件 制 作 的 ? [SEP] 這 種 圖 片 制 作 是 用 什 麼 軟 件 呢 ? [SEP]

其中[CLS]是模型額外增加的開始標誌,說明這是句首位置。[SEP]代表分隔符,我們會將兩句話拼接成一句話,通過分隔符來識別。第二句話拼接完成後也會加上一個分隔符。這裡需要注意的是BERT對於中文分詞是以每個字進行切分,並不是我們通常理解的按照中文實際的詞進行切分。

經過特徵提取之後變成了:

input_ids:101

6821 4905 1745 4275 3221 4500 784 720 6763 816 1169 868 46388043 102

6821 4905 1745 4275 1169 868 3221 4500 784 720 6763 816 1450 8043 1020 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 0 0 0 0 0

0 00 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 0

0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

input_mask:1 1 1 1

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 00 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 0 0 0 0 0 0 00 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 0 0 0 0 0

0 00 0 0 0 0 0 0 0 0 0 0 0 0 0

segment_ids:0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 00 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 0 0 0 0 0 0 00 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 0 0 0 0 0 0 00 0 0 0 0

0 0 0 0 0 0 0 0 0

label_id:1

這裡詳細說下我們真正給模型輸入的特徵是什麼。

input_ids代表詞向量編碼。NLP任務中我們會將文本轉化成詞向量的表徵形式提供給模型。通過BERT源碼中的tokenizer將句子拆分成字,並且將字映射成id。比如上面例子中第一句話有14個字,第二句話也有14個字,再加上一個開始標誌和兩個分隔符,一種有31個字。而上面例子中的input_ids列表中前31個位置都有每個字映射的id,並且相同字的映射的id也是一樣的。其他則通過添加0進行填充;

input_mask代表位置編碼。為了transformer感知詞與詞之間的位置關係,源碼中會將當前位置有字的設置為1,其他用0進行填充;

segment_ids代表句子關係編碼。如果是句子關係判斷任務則會將text_b位置對應的句子關係編碼置為1。這裡需要注意,只要是句子關係判斷任務,不管兩句話到底有沒有關係,即標籤是否為1都會將text_b位置對應的句子關係編碼置為1;

label_id就代表兩句話是不是有關係。如果有關係則標籤置為1,否則為0。

2. 特徵存儲在TFRecord格式文件

當我們進行模型訓練的時候,會將全部訓練數據加載到內存中。對於小規模數據集來說沒有問題,但是遇到大規模數據集時我們的內存並不能加載全部的數據,所以涉及到分批加載數據。Tensorflow給開發者提供了TFRecord格式文件。TFRecord內部採用二進位編碼,加載快,對大型數據轉換友好。

小結下,特徵處理模塊主要將預處理得到的數據轉化成特徵並存儲到TFRecord格式文件。BERT會將句子輸入轉化成三層Embedding編碼,第一層是詞編碼,主要表示詞本身;第二層編碼是位置編碼,主要為了transformer感知詞與詞之間的位置關係;第三層編碼則表示句與句之間關係。通過這三層編碼我們就得到了模型的特徵輸入。為了方便大數據集下模型訓練加載數據,我們將特徵持久化到TFRecord格式文件。

04 模型構建模塊

模型構建模塊主要分成模型構建和模型標準輸入。

1. 模型構建

通過函數model_fn_builder來構建自定義模型估計器。

這裡模型構建主要有create_model函數完成,主要完成兩件事:第一是調用modeling.py中的BertModel類創建模型;第二是計算交叉熵損失loss。交叉熵的值越小,兩個概率分布就越接近。

2. 模型標準輸入

因為源項目是基於Tensorflow框架開發,所以需要將前面得到的特徵轉化成標準的Tensorflow模型輸入格式。這塊主要由函數file_based_input_fn_builder來完成。通過輸入文件的不同可以完成訓練集、驗證集和測試集的輸入。

這裡需要注意的是is_training欄位,對於訓練數據,需要大量的並行讀寫和打亂順序;而對於驗證數據,我們不希望打亂數據,是否並行也不關心。

小結下,模型構建模塊主要由模型構建和模型標準輸入兩部分。模型構建負責創建和配置BERT模型。模型標準輸入則讀取TFRecord格式文件並轉化成標準的模型輸入,根據輸入文件的不同完成訓練集、驗證集和測試集的標準輸入。

05 模型運行模塊

上面模型構建好了之後即可運行模型。Tensorflow中模型運行需要構建一個Estimator對象。主要通過源碼中tf.contrib.tpu.TPUEstimator()來構建。

1. 模型訓練

模型訓練通過estimator.train即可完成:

2. 模型驗證

模型驗證通過estimator.evaluate即可完成:

3. 模型預測

模型預測通過estimator.predict即可完成:

06 其他模塊

1. tf日誌模塊

2. 外部傳參模塊

總結

本篇主要講解BERT中分類器部分的源碼。整體來看主要分成數據處理模塊、特徵處理模塊、模型構建模塊和模型運行模塊。數據處理模塊主要負責數據讀入和預處理工作;特徵處理模塊負責將預處理後的數據轉化成特徵並持久化到TFRecord格式文件中;模型構建模塊主要負責構建BERT模型和模型標準輸入數據準備;模型運行模塊主要負責模型訓練、驗證和預測。通過整體到局部的方式我們可以對BERT中的分類器源碼有深入的了解。後面可以根據實際的業務需求對分類器進行二次開發。

最新最全的文章請關注我的微信公眾號:數據拾光者。

相關焦點

  • 廣告行業中那些趣事系列9:一網打盡Youtube深度學習推薦系統
    如果有8個詞,我們就需要長度為8的「01」串來表示詞。每個詞都有自己的順序,那麼對每個詞One-hot編碼的時候在該位置上置1其他都置為0。現在我們把這四個詞對應的編碼輸入到計算機裡,計算機就能明白各個編碼代表的含義。這種形式就是One-hot編碼。通過One-hot編碼我們就能輕鬆的表示這些文本。
  • 廣告行業中那些趣事系列26:基於PoseNet算法的人體姿勢相似度識別
    但是因為我們今年會做一些廣告文案自動生成相關的業務,就是根據一定的生成條件比如標籤分類來自動生成廣告文案。比如現在要創建一個傳奇遊戲標籤類型的廣告,我們會將傳奇遊戲標籤作為條件來自動生成一批廣告文案提供給廣告主選擇,這樣廣告主就不需要自己寫文案了,直接從文案庫裡選一條用就行了。
  • 詞向量詳解:從word2vec、glove、ELMo到BERT
    目前,詞向量(又叫詞嵌入)已經成為NLP領域各種任務的必備一步,而且隨著bert elmo,gpt等預訓練模型的發展,詞向量演變為知識表示方法,但其本質思想不變。學習各種詞向量訓練原理可以很好地掌握NLP各種方法。生成詞向量的方法有很多種,本文重點介紹word2vec,glove和bert。
  • 模型推理加速系列|如何用ONNX加速BERT特徵抽取(附代碼)
    實驗中的任務是利用BERT抽取輸入文本特徵,至於BERT在下遊任務(如文本分類、問答等)上如何加速推理,後續再介紹。PS:本次的實驗模型是BERT-base中文版。", output=Path("onnx/bert-base-chinese.onnx"), opset=11)# 注意:因為convert_graph_to_onnx.convert中默認的pipeline_name是"feature-extraction"。
  • Keras-BERT-NER albert、roberta、bert、wwm四個模型如何去做命名實體識別任務
    GitHub項目地址:https://github.com/liushaoweihua/keras-bert-ner中文命名實體識別任務下的Keras解決方案,下遊模型支持BiLSTM-CRF/BiGRU-CRF/IDCNN-CRF/single-CRF,預訓練語言模型採用BERT系列(谷歌的預訓練語言模型:支持BERT
  • BERT原理解讀及HuggingFace Transformers微調入門
    對於Masked Language Modeling,給定一些輸入句子(圖1中最下面的輸入層),BERT將輸入句子中的一些單詞蓋住(圖1中Masked層),經過中間的詞向量和BERT層後,BERT的目標是讓模型能夠預測那些剛剛被蓋住的詞。還記得英語考試中,我們經常遇到「完形填空」題型嗎?能把完形填空做對,說明已經理解了文章背後的語言邏輯。
  • NLP之文本分類:「Tf-Idf、Word2Vec和BERT」三種模型比較
    NLP常用於文本數據的分類。文本分類是指根據文本數據內容對其進行分類的問題。我們有多種技術從原始文本數據中提取信息,並用它來訓練分類模型。本教程比較了傳統的詞袋法(與簡單的機器學習算法一起使用)、流行的詞嵌入模型(與深度學習神經網絡一起使用)和最先進的語言模型(和基於attention的transformers模型中的遷移學習一起使用),語言模型徹底改變了NLP的格局。
  • 上古捲軸5技能書籍有那些? 上古捲軸5技能書籍分類詳解
    上古捲軸5技能書籍有那些? 上古捲軸5技能書籍分類詳解 上古捲軸5技能書籍分類詳解:上古捲軸5天際已經跟大家見面了,為了玩家更好的遊戲體驗,下面遊戲堡小編為大家帶來了一篇關於技能書分類的攻略,希望對大家有所幫助,更多精彩攻略盡在遊戲堡。
  • 如何修剪BERT達到加速目的?理論與實現
    我們現有的輕量級意圖分類器只需幾毫秒即可處理一條消息,並在數據集的測試部分上獲得測試集的宏平均F1(或簡稱為「 F1」)得分為0.86。我們使用BERT成功達到了約0.92的F1,但是處理一條消息大約需要143ms。在我們的實驗中,我們修剪了經過微調的BERT,因此從非常好的F1開始,然後看它在修剪後如何變化。
  • 科學史趣事——那些無意中被發現的神奇材料
    以下就帶您一起來回顧那些材料誕生的趣事。 不鏽鋼 在第一次世界大戰時期,一位金屬專家受命研究槍筒因生鏽而損壞的問題。在研究中他採用了幾種新型高鉻含量的合金鋼做槍筒。但是用這種新「鉻鋼」製造的槍筒,在開了第一槍後就成了碎片。
  • 宋代廣告到底有多牛?細數《清明上河圖》中那些「亮瞎眼」的廣告
    在《清明上河圖》中,我們可以看到形式多樣的廣告,今天我們就通過畫中廣告的多樣性來感受宋朝經濟的繁榮。02宋代廣告形式層出不窮,主要有以下幾種分類:1.幡子和招牌所謂幡子廣告,就是用一根長竿高高掛起一塊布,布上書寫廣告詞。幡子廣告並不是起源於宋代,到宋朝時幡子廣告已經不足為奇。招牌廣告也同樣是街頭巷尾常見的廣告形式。
  • 口袋妖怪中的奇聞趣事
    小夥伴們好呀,本次小編要帶來的是一些精靈的奇聞趣事,本次的奇聞趣事是一些寶可夢之間的關係,有進化鏈關係的也有不是的,我們來看看分別都是什麼吧。        在設定上,貓鼬斬與飯匙蛇的千年恩怨,圖鑑上描述只要貓鼬斬和飯匙蛇之間相遇就會展開一場大戰,而在動畫中對此也有體現,在第六世代的群聚對戰中,他們會在攻擊玩家前相互攻擊,在現實中,貓鼬斬以及飯匙蛇的原型也是相應的捕食關係
  • 那些年廣告代言中的「大佬們」
    無奈的愛瑪電動車一狠心,掏出了3000萬聘請周杰倫代言,這讓其成為電動車行業內代言費用最高的明星,打破了王菲2000萬元代言洗髮水的紀錄。當然,愛瑪這筆花得很值。周杰倫的代言讓愛瑪一年的品牌價值從5億元翻到了20億,它也成功打入年輕人群體,10年間賣了4100萬輛,登頂電動自行車行業市場第一的寶座。
  • 榮耀趙明旗幟鮮明抵制開機廣告,智慧屏X1系列倒逼行業取消
    榮耀總裁趙明在昨天召開的智慧生活發布會期間,再次旗幟鮮明的抑制大屏行業開關機廣告問題,並透露2299元起步的榮耀智慧屏X1系列,憑藉領先行業的五大標杆以及開關機無廣告,有望倒逼行業重新重視技術創新以及徹底取消開關機廣告。
  • 現代廣告中的軟文廣告!
    文/梁春峰軟文廣告在現代廣告中起著不可替代的作用,軟文廣告所具有的科普性、知識性、新聞性使消費者願意接受這些信息,使它在當今現代廣告宣傳中的作用逐漸加強。軟文廣告在現代廣告宣傳中又稱為軟文,軟文是企業把所要宣傳的廣告很含蓄地表達在一些宣傳媒介或者其他類型的文章裡。
  • 【垃圾分類知識】塑料垃圾有什麼危害? 專家詳解 →
    【垃圾分類知識】塑料垃圾有什麼危害? 塑料是公眾每天都能接觸到的物質,來聽聽市城管局垃圾分類專家講講塑料垃圾那些事。
  • 分享|Facebook廣告架構詳解
    Facebook廣告架構詳解隨著更多的涉足海外社交媒體運營,Facebook也逐漸被大眾所周知,並且更多的跨境電商賣家開始使用Facebook進行廣告投放。很多人都開始進入Facebook廣告中,那麼大家是否真的了解Facebook廣告的構架呢?每個構架層次的內容是什麼呢?
  • 中手遊獲頒騰訊廣告「向陽獎」2019年度行業精耕廣告主獎
    首頁 > 傳媒 > 關鍵詞 > 廣告主最新資訊 > 正文 中手遊獲頒騰訊廣告「向陽獎」2019年度行業精耕廣告主獎
  • 寶石與玉石的基本概念和分類詳解
    概念中並未要求它一定是天然的。 但是人們說,寶石有三大基本條件:稀少(罕見、稀缺)物以稀為貴, 因此,寶石與同樣來自大自然的普通石頭就有了貴賤之分。瑰麗(美觀、漂亮)迎合了人類愛美求異的天性,也是造成寶玉石人為稀缺的另一個重要原因。耐久(長久不變、抗磨防腐性好 )寄託著人們對所擁有的珍貴物品的期待。可見,符合條件者主要是天然產物。
  • BERT 瘦身之路:Distillation,Quantization,Pruning
    經典蒸餾法詳解最早的蒸餾法,一般認為是 Hinton 在 Distilling the Knowledge in a Neural Network 提出,之後得到推廣。之所以取 [CLS] 位置,是因為其在 BERT 分類任務中的重要性。