<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    一文讀懂 BERT 源代碼

    共 8742字,需瀏覽 18分鐘

     ·

    2022-09-16 10:15

    213db326c461308bf0ee10a5df9ad678.webp

    大數(shù)據(jù)文摘授權轉(zhuǎn)載自數(shù)據(jù)派THU

    作者:陳之炎


    BERT模型架構是一種基于多層雙向變換器(Transformers)的編碼器架構,在tensor2tensor庫框架下發(fā)布。由于在實現(xiàn)過程當中采用了Transformers,BERT模型的實現(xiàn)幾乎與Transformers一樣。


    BERT預訓練模型沒有采用傳統(tǒng)的從左到右或從右到左的單向語言模型進行預訓練,而是采用從左到右和從右到左的雙向語言模型進行預訓練,本文對BERT模型預訓練任務的源代碼進行了詳細解讀,在Eclipse開發(fā)環(huán)境里,對BERT 源代碼的各實現(xiàn)步驟分步解析。


    BERT 模型的代碼量比較大,由于篇幅限制,不可能對每一行代碼展開解釋,在這里,解釋一下其中每一個核心模塊的功能。


    1) 數(shù)據(jù)讀取模塊


    db37dedc17dd7caa92e02be4f805657a.webp

    圖 1


    模型訓練的第一步,是讀取數(shù)據(jù),將數(shù)據(jù)從數(shù)據(jù)集中讀取進來,然后按照BERT 模型要求的數(shù)據(jù)格式,對數(shù)據(jù)進行處理,寫出具體數(shù)據(jù)處理的類以及實際要用到的數(shù)據(jù)集中數(shù)據(jù)處理的方法,如果任務中用到的數(shù)據(jù)集不是MRPC ,這部分的代碼需要依據(jù)特定的任務重新寫一下如何操作數(shù)據(jù)集的代碼,對于不同的任務,需要構造一個新的讀取數(shù)據(jù)的類,把數(shù)據(jù)一行一行地讀進來。


    2) 數(shù)據(jù)預處理模塊


    c342f4c308b39b86c0da8ec91306df59.webp

    圖 2


    利用tensorflow 對數(shù)據(jù)進行預處理,由于用TF-Record 讀數(shù)據(jù)的速度比較快,使用起來比較方便,在數(shù)據(jù)讀取層面,需要將數(shù)據(jù)轉(zhuǎn)換成TF-Record格式。首先,定義一個writer,利用writer函數(shù)將數(shù)據(jù)樣本寫入到TF-Record當中,這樣一來,在實際訓練過程中,不用每次都到原始數(shù)據(jù)中去讀取數(shù)據(jù),直接到TF-Record當中讀取處理好的數(shù)據(jù)。


    把每一個數(shù)據(jù)樣本都轉(zhuǎn)化成一個TF-Record格式的具體做法如下:首先,構建一個標簽,接下來對數(shù)據(jù)做一個判斷,判斷數(shù)據(jù)中由幾句話組成,拿到當前第一句話后,做一個分詞操作。分詞方法為wordpiece 方法。在英文文本中,由字母組成單詞,詞與詞之間利用空格來切分單詞,利用空格切分單詞往往還不充分,需要對單詞做進一步切分轉(zhuǎn)換,在BERT 模型中,通過調(diào)用wordpiece 方法將輸入的單詞再進一步切分,利用wordpiece的貪心匹配方法,將輸入單詞進一步切分成詞片,從而使得單詞表達的含義更加豐富。在這里,利用wordpiece 方法將讀入的單詞進行再次切分,把輸入的單詞序列切分成更為基本的單元,從而更加便于模型學習。


    在中文系統(tǒng)中,通常把句子切分成單個的字,切分完成之后,把輸入用wordpiece轉(zhuǎn)化成wordpiece結(jié)構之后,再做一個判斷,看是否有第二句話輸入,如果有第二句話輸入,則用wordpiece對第二句話做相同的處理。做完wordpiece轉(zhuǎn)換之后,再做一個判斷,判斷實際句子的長度是否超過max_seq_length 的值,如果輸入句子的長度超過max_seq_length規(guī)定的數(shù)值,則需要進行截斷操作。


    3) tf-record 制作


    對輸入句對進行編碼,遍歷wordpiece結(jié)構的每一個單詞以及每一個單詞的type_id ,加入句子分隔符【CLS】、【SEP】,為所有結(jié)果添加編碼信息;添加type_id,把所有單詞映射成索引功,對輸入詞的ID (標識符)進行編碼,以方便后續(xù)做詞嵌入時候進行查找;


    Mask編碼:對于句子長度小于max_seq_length 的句子做一個補齊操作。在self_attention 的計算中,只考慮句子中實際有的單詞,對輸入序列做input_mask 操作,對于不足128個單詞的位置加入額外的mask,目的是讓self_attention知道,只對所有實際的單詞做計算,在后續(xù)self_attention計算中,忽略input_mask=0 的單詞,只有input_mask=1 的單詞會實際參與到self_attention計算中。Mask編碼為后續(xù)的微調(diào)操作做了初始化,實現(xiàn)了任務數(shù)據(jù)的預處理。


    3752c3980b53ce6f5a2a94af3dcf2a83.webp

    圖 3


    對input_Feature做初始化:構建 input_Feature并把結(jié)果返回給BERT。通過一個for 循環(huán),遍歷每一個樣本,再對構造出來一些處理,把input_id、input_mask和segment_id均轉(zhuǎn)換成為int類型,方便后續(xù)tf-record的制作。之所以要做數(shù)據(jù)類型的轉(zhuǎn)換,是因為tensorflow 官方API要求這么做,tensorflow對tf-record的格式做了硬性的規(guī)定,用戶無法自行對其修改。在后續(xù)具體項目任務中,在做tf-record時,只要把原始代碼全部復制過去,按照原有的格式修改即可。構造好input_Feature之后,把它傳遞給tf_example,轉(zhuǎn)換成tf_train_features ,之后,直接寫入構建好的數(shù)據(jù)即可。


    4) Embeding層的作用


    在BERT 模型中有一個creat_model 函數(shù),在creat_model 函數(shù)中一步一步把模型構建出來。首先,創(chuàng)建一個BERT 模型,該模型中包含了transformer的所有結(jié)構,具體操作過程如下:


    da47aff2c3d034ebfb132b873e362e87.webp

    圖 4


    讀入配置文件,判斷是否需要進行訓練,讀入input_id、input_mask和segment_id等變量, one_hot_embedding變量?在利用TPU 訓練時才使用,在用CPU 訓練時不用考慮,默認值設為Faulse。


    構建embedding層,即詞嵌入,詞嵌入操作將當前序列轉(zhuǎn)化為向量。BERT 的embedding層不光要考慮輸入的單詞序列,還需要考慮其它的額外信息和位置信息。BERT 構建出來的詞嵌入向量中包含以下三種信息:即輸入單詞序列信息、其它的額外信息和位置信息。為了實現(xiàn)向量間的計算,必須保持包含這三種信息的詞向量的維數(shù)一致。


    5) 加入額外編碼特征


    接下來,進入到embedding_lookup 層,這個層的輸入是:input_id(輸入標識符)、vocab_size(詞匯表大小)、embedding_size(詞嵌入的維度)、initializer_range(初始化的取值范圍)。embedding_lookup的輸出是一個實際的向量編碼。


    6834f1d240f0593fba7a12088899fa87.webp

    圖 5


    首先,獲取embedding_table,然后到embedding_table里查找每個單詞對應的詞向量,并將最終結(jié)果返回給output,這樣一來,輸入的單詞便成了詞向量。但這個操作只是詞嵌入的一部分,完整的詞嵌入還應在詞嵌入中添加其它額外的信息,即:embedding_post_processor。


    embedding_post_processor是詞嵌入操作必須添加進去的第二部分信息,embedding_post_processor的輸入有:input_tensor、use_token_type、token_type_id、token_type_vocab_size,返回的特征向量將包含這些額外的信息,其維度和輸入單詞的詞向量一致。


    6) 加入位置編碼特征


    利用use_position_embedding 添加位置編碼信息。BERT 的Self_attention 中需要加入位置編碼信息,首先,利用full_position_embedding 初始化位置編碼,把每個單詞的位置編碼向量與詞嵌入向量相加,接著,根據(jù)當前的序列長度做一個計算,如果序列長度為128,則對這128個位置進行編碼。由于位置編碼僅包含位置信息,和句子的上下文語義無關,對于不同的輸入序列來說,雖然輸入序列的內(nèi)容各不相同,但是它們的位置編碼卻是相同的,所以位置編碼的結(jié)果向量和實際句子中傳的什么詞無關,無論傳的數(shù)據(jù)內(nèi)容是什么,它們的位置編碼均是一樣的。獲得位置編碼的輸出結(jié)果之后,在原詞嵌入輸出向量的基礎上,加上額外編碼獲得的特征向量和位置編碼向量,將三個向量求和,返回求和結(jié)果,到此為止,完成了BERT模型的輸入詞嵌入,得到了一個包含位置信息的詞向量,接下來,對這個向量進行深入的操作。


    b5b1da4048cfa632d59ee4b8ef38fb06.webp

    圖 6


    7) mask機制


    在完成詞嵌入之后,接下來便是Transformer結(jié)構了,在Transformer之前,先要對詞向量做一些轉(zhuǎn)換,即attention_mask ,創(chuàng)建一個mask矩陣:create_attention_mask_from_input_mask 。在前文提到的input_mask 中,只有mask=1 的詞參與到attention的計算當中,現(xiàn)在需要把這個二維的mask轉(zhuǎn)換成為一個三維的mask,表示詞向量進入attention的時候,哪幾個向量會參與到實際計算過程當中。即在計算attention時,對輸入序列中128個單詞的哪些個單詞做attention計算,在這里,又額外地加入了一個mask處理操作。


    7060ae92e1fa0e1716b866466241bbcd.webp

    圖 7

    ?

    完成mask處理之后,接下來是構建Transformer的Encode端,首先給Transformer傳入一些參數(shù),如:input_tensor、attention_mask、hiden_size、head_num等等。這些參數(shù)在預訓練過程中已經(jīng)設置好了,在進行微調(diào)操作時,均不得對這些參數(shù)隨意更改。


    在多頭attention機制中,每個頭生成一個特征向量,最終把各個頭生成的向量拼接在一起得到輸出的特征向量。


    8) 構建QKV 矩陣


    接下來,是attention機制的實現(xiàn),BERT 的attention機制是一個多層的架構,在程序具體實現(xiàn)中,采用的是遍歷的操作,通過遍歷每一層,實現(xiàn)多層的堆疊??偣残枰闅v12層,當前層的輸入是前一層的輸出。attention機制中,有輸入兩個向量:from-tensor和to_tensor,而BERT 的attention機制采用的是self_attention,此時:


          

    from-tensor=to_tensor=layer_input;

    4affb4ae07027979924ee0419d7b6e72.webp

    圖 8


    在構建attention_layer過程中,需要構建K、Q、V 三個矩陣,K、Q、V矩陣是transformer中最為核心的部分。在構建K、Q、V矩陣時,會用到以下幾個縮略字符:


    • B ?代表Batch Size ?即批大小 ?在這里的典型值設為 8;

    • F???代表 ?from-tensor??維度是128;

    • T???代表 to_tensor??維度是128;

    • N ? Number of Attention Head attention機制的頭數(shù)(多頭attention機制)在這里的典型值設為 12個頭;

    • H ? Size_per_head 代表每個頭中有多少個特征向量,在這里的典型值設為 64;


    構建Query 矩陣:構建query_layer查詢矩陣,查詢矩陣由from-tensor構建而來,在多頭attention機制中,有多少個attention頭,便生成多少個Query 矩陣,每個頭生成的Query 矩陣輸出對應向量:


          

    query_layer=【 B*F,N*H】, 即1024*768;

    7c2987e0320799a7ae3d4f95301551f3.webp

    圖 9


    構建Key 矩陣: Key 矩陣由to-tensor構建而來, 在多頭attention機制中,有多少個attention頭,便生成多少個Key 矩陣,每個頭生成的Key 矩陣輸出對應向量:


          

    key_layer=【 B*T,N*H】, 即1024*768;


    24cf82028a5465d6b7a0d6ca9fa47825.webp

    圖 10


    構建Value矩陣: Value矩陣的構建和Key 矩陣的構建基本一樣,只不過描述的層面不同而已:



          

    value_layer=【 B*T,N*H】, 即1024*768;


    構建QKV 矩陣完成之后,計算K矩陣和Q 矩陣的內(nèi)積,之后進行一個Softmax操作。通過Value矩陣,幫助我們了解實際得到的特征是什么,Value矩陣和Key矩陣完全對應,維數(shù)一模一樣。


    84530c83e0edcfed6d0f37ba4b79e043.webp

    圖 11


    9) 完成Transformer 模塊構建


    構建QKV 矩陣完成之后,接下來,需要計算K矩陣和Q 矩陣的內(nèi)積,為了加速內(nèi)積的計算,在這里做了一個transpose轉(zhuǎn)換,目的是為了加速內(nèi)積的計算,并不影響后續(xù)的操作。計算好K矩陣和Q 矩陣的內(nèi)積之后,獲得了attention的分值:attention_score,最后需要利用Softmax操作將得到的attention的分值轉(zhuǎn)換成為一個概率:attention_prob。


    在做Softmax操作之前,為了減少計算量,還需要加入attention_mask,將長度為128 的序列中不是實際有的單詞屏蔽掉,不讓它們參與到計算中來。在tensorflow中直接有現(xiàn)成的Softmax函數(shù)可以調(diào)用,把當前所有的attention分值往Softmax里一傳,得到的結(jié)果便是一個概率值,這個概率值作為權重值,和Value矩陣結(jié)合在一起使用,即將attention_prob和Value矩陣進行乘法運算,便得到了上下文語義矩陣,即:



          

    Context_layer=tf.matmul(attention_prob, value_layer);

    8720d9a903c90f4bc225e3d6f49b8dea.webp

    圖 12


    得到當前層上下文語義矩陣輸出之后,這個輸出作為下一層的輸入,參與到下一層attention的計算中去,多層attention通過一個for循環(huán)的多次迭代來實現(xiàn),有多少層attention(在這里是12層)就進行多少層迭代計算。


    10) 訓練BERT 模型


    做完self_attention之后,接下來是一個全連接層,在這里,需要把全連接層考慮進來,利用tf.layer.dese 實現(xiàn)一個全連接層,最后要做一個殘差連接,注意:在全連接層的實現(xiàn)過程中,需要返回最終的結(jié)果,即將最后一層attention的輸出結(jié)果返回給BERT ,這便是整個Transformer 的結(jié)構。


    aac455186286a639eadd701ac89a3db4.webp

    圖 13


    總結(jié)一下上述整個過程,即Transformer 的實現(xiàn)主要分為兩大部分:第一部分是embedding 層,embedding 層將wordpiece詞嵌入加上額外特定信息和位置編碼信息,三者之和構成embedding 層的輸出向量;第二部分是將embedding 層的輸出向量送入transformer結(jié)構,通過構建K、Q、V三種矩陣過,利用Softmax函數(shù),得到上下文語義矩陣C , 上下文語義矩陣C不僅包含了輸入序列中各單詞的編碼特征,還包括了各單詞的位置編碼信息。


    這就是BERT 模型的實現(xiàn)方式,理解了上述兩大部分的詳細過程,對BERT模型的理解便沒有什么太大問題了。以上十大步驟基本涵蓋了BERT 模型中的重要操作。


    經(jīng)過BERT 模型之后,最終獲得的是一個特征向量,這個特征向量代表了最終結(jié)果。以上便是谷歌官方公布的開源MRPC 項目的全部過程。讀者在構建自己特定任務的項目時候,需要修改的是如何將數(shù)據(jù)讀入BERT 模型的部分代碼,實現(xiàn)數(shù)據(jù)預處理。


    0463106851bf24e277a14f8136a5a3d5.webp

    點「在看」的人都變好看了哦!
    瀏覽 46
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報
    評論
    圖片
    表情
    推薦
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    欧美色图第三页 | 无码精品一区二区三区四区五区六区 | 黑人精品XXX一区一二区 | 国产殴美在线播放视频 | 在线免费观看A∨ |