天池nlp學習賽(6)基於機器學習的文字分類3 (Bert)

2020-08-13 14:14:32

基於深度學習的文字分類3


介紹:這一節的主要內容是bert的使用。bert主要內容是預訓練與微調,預訓練可以得到詞之間的關係,可以直接用於特徵提取以及預測上下文,微調在預訓練的基礎上實現文字分類等功能,並對預訓練中的參數進行微調。

主要內容:
(1)瞭解Transformer的原理和基於預訓練語言模型(Bert)的詞表示

(2)學會Bert的使用,具體包括pretrain和finetune(預訓練與微調)

具體的原理和網路結構都在裏面,但是講的有點粗糙

論文原文

一個手把手教原理和實現的up主視訊,超讚!!!!就是手把手教論文細節!和他的有詳細註釋的github程式碼以及知乎專欄

part1:文字表示方法4 — 編碼器:Transformer

transformer block:

(1)自向量與位置編碼
(2)自注意力機制 機製
(3)殘差連線(resnet)與layer normolization
(4)feed forward

具體看這裏
最後講這些block堆疊組合(一般12個layer)

(1)位置編碼

藉助sin cos用以表示文字之間的位置關係(因爲bert裏面沒有像LSTM一樣的前後迭代的過程)
這樣對於一個詞:

表示位置的編碼+文字本身的嵌入編碼=文字的初始embedding(或者理解爲初始的特徵也行?)

(2)自注意力機制 機製

把embedding dimension平等分成h塊
h是embedding dimension分成的份數
得到三個矩陣:Q,K,V維度:[batch size,h,sequence length,embedding dim/h ]

self_attention:QKTQ\cdot K^T
K的轉置只轉置後面兩維,這樣做出來的內積能夠表示出前後的距離關係(因爲sequence length所在的維度表現了語句元的位置關係)

Attention(Q,K,V)=softmax(QKTdk)VAttention(Q,K,V)=softmax(\frac{QK^T}{\sqrt{d_k}})V

dk\sqrt{d_k}是爲了使得注意力矩陣標準化

(3)殘差連線
(4)feed forward

兩層線性變換後用啓用函數啓用再傳入(3)

part2:兩種預訓練的方式

(1)Masked LM (masked language model)

15%的內容(token)做掩碼:
(1)80%機率換成[mask]
(2)10%機率換成其它的任意詞
(3)10%機率不改變

用模型預測這些被掩蓋的內容,計算這些內容的loss
XhiddenX_{hidden}=[batch_size,seq_len,embedding_dim]
Wvocab:W_{vocab}:[embedding_dim,vocab_size] (vocab_size是字典中所有詞的個數)
XhiddenWvocabX_{hidden}\cdot W_{vocab}對vocab_size softmax

(2)Next Sentence Prediction

在原語句中加入以下部分:
每個句子的
開頭[cls]:開始符
結尾[seq]:句子間間隔符

input中對每個詞的嵌入(類似於詞向量)有:

[tokem embedding]:每個字的嵌入
[segment embedding]:每句話的嵌入
[position embedding]:位置的嵌入

最後取XhiddenX_{hidden}中的[:,0,:]來代表每一個句子,得到結果cls_vector=[batch_size,embedding_dim]
輸出分類依據:sigmoid(Linear(clsvector))sigmoid(Linear(cls_vector))

part3:微調

啥是微調
微調的方法由具體採用的分類方法決定
例子

使用方法

對於模型的使用方面有以下情況:

(1)使用自己的數據集進行預訓練(適用於專業性較強或數據集已經過編碼的情況)
這時候參考下面 下麪模型訓練的部分,需要自己做分詞,構造詞典,進行預訓練

(2)呼叫官方的預訓練模型,後面就只需要進行微調

(1)模型訓練

有大佬封裝好了keras模組下的bert

裏面的內容包含:
(1)怎樣分詞
(2)bert模型訓練
(3)構造特徵

內容具體而全面,程式碼簡潔易懂,在這裏就不做複述了。

(2)微調

微調的過程可以理解爲原來的預訓練模型得到了詞語的特徵和關聯,預訓練結束後房子的大致形狀已經確定了,現在在原來的房子裏面加電線水管,通水電煤氣進行測試,測試過程中除了裝管道還需要對房子的一些部分做修改,這就是對測試集的X,Y進行擬合調整參數(之前的預訓練只使用了X)。

官方預訓練模型,其中包含多種大的小的,中文的英文的預訓練模型,進去選擇點集下載

官方例子也在裏面

非官方例子,(基於keras),強烈安利
(1)文字分類
(2)關係抽取
(3)主體抽取

這裏只說明一下其中的文字分類部分:

主要就是在預訓練模型的基礎上加入一個全連線層&sigmoid函數進行分類

 from keras_bert import load_trained_model_from_checkpoint
 #匯入模型
 bert_model = load_trained_model_from_checkpoint(config_path, checkpoint_path, seq_len=None)

#讓原來的模型可訓練
for l in bert_model.layers:
    l.trainable = True
    
#設定輸入格式,每個詞的輸入有兩部分
#(第一部分是這個詞的詞向量,x1代表這一部分的維度;另一部分x2是segment_id代表句子的id,即這個詞屬於哪一個句子)
#上面兩個維度使用Tokenizer中的encode函數能直接輸出
#實際上還可以加上第三個維度來體現詞在句子中的位置.

x1_in = Input(shape=(None,))
x2_in = Input(shape=(None,))

x = bert_model([x1_in, x2_in])
x = Lambda(lambda x: x[:, 0])(x) # 取出句子起始符[CLS]對應的向量用來做分類
p = Dense(1, activation='sigmoid')(x)

#x1_in是預訓練輸入的維度
#x2_in是
model = Model([x1_in, x2_in], p)
model.compile(
    loss='binary_crossentropy',#二分類的情況,多分類用交叉熵
    optimizer=Adam(1e-5), # 用足夠小的學習率
    metrics=['accuracy']
)
model.summary()

ps:由於算力問題&不想再裝包了就不寫這個的demo了
對於大量數據加速計算可以使用TPU,現在在colab上可以氪金用遼。

另外對於bert網路上還有其它一些包可以借鑑(HuggingFace 裏面有transformer封裝好的包據說也很好用,大家可以試試)