BERT的源碼文件主要包括下面幾個部分

顧名思義,模型的描述主要就是在modeling.py這個文件中
pre_training.py,create_pretraining_data.py,extract_feature.py, tokenization.py是預(yù)訓(xùn)練相關(guān)的主要主要描述部分
下面,主要是對BERT模型構(gòu)建的部分進行解析。
其中BERT 模型包括配置和模型兩個部分,下面是配置的主要參數(shù)
模型的輸入包括下面三個部分:
input_ids, ? ? ? ? ? ? #padding過后的token id 序列
input_mask, ?????#輸入的mask
token_type_ids,#token的類型,可能會有一些type類型
下面是主要的模型流程:
1.上面三個的shape都是 ? [batch_size, seq_length]
2.創(chuàng)建embedding_table(embedding_lookup)以及加上position_embedding和token_type_embedding(embedding_postprocessor)
3.創(chuàng)建attention mask :attention_mask ?[batch_size, seq_length, seq_length]
4.transformer_model: -> self.all_encoder_layers?? list of [batch_size, seq_length, hidden_size] #transformer層,輸出結(jié)果到一個列表
5.self.sequence_output =self.all_encoder_layers[-1] ?[batch_size, seq_length, hidden_size] #最后一層作為輸出
6.self.pooled_output ??[batch_size, hidden_size] #奇怪的pool操作,只取第一個位置變量
可以看到,主要部分是tranformer_model這個函數(shù)
這里,trasformer使用了residual的設(shè)計,所以每層輸入和輸出的hidden_size要一樣,這里都是768.
這里先設(shè)置了幾個維度的縮寫
# B = batch size (number of sequences)
#? F = `from_tensor` sequence length
#? T = `to_tensor` sequence length
#? N = `num_attention_heads`
#? H = `size_per_head`
下面是attention的過程
1. attention_head_size =int(hidden_size / num_attention_heads)#設(shè)置每個head里面權(quán)重的維度
2. 每層的transformer 包含三個主要操作,self-attention,intermediate,output
2.1 self-attention : ??from_tensor [B, F,N*H], ? to_tensor[B, T, N*H]是兩個輸入變量,這里兩個變量是一樣的,所以叫做self-attention
? ? query_layer = [B*F, N*H] ?#單獨的權(quán)重轉(zhuǎn)換為多head的一個矩陣
? ? key_layer?= [B*T, N*H] ? ? ?#單獨的權(quán)重轉(zhuǎn)換為多head的一個矩陣
? ? value_layer?= [B*T, N*H] ? #單獨的權(quán)重轉(zhuǎn)換為多head的一個矩陣
????attention_scores?= [B, N, F, T] ? #scaled,這個挺有意思的,先scale
? ??attention_scores ?+= adder (1-mask)*-10000 ?#在softmax之前轉(zhuǎn)化mask表示方式
? ? attention_probs = softmax 操作<-attention_scores #pad部分的attention值很?。ń咏?) ??
? ? drop attention_probs #dropout 操作
? ? context_layer =?tf.matmul(attention_probs, value_layer) ?#? [B, F, N, H]
? ? dropout + layer_norm(context_layer?+ layer_input #residual 操作)
2.2 intermediate 就是一個全連接層
? ? ? ? 輸出[B, N, intermediate_size]
2.3?output 也是一個全連接層,
????????輸出[B, F, N*H]
? ???????dropout + layer_norm(context_layer?+ layer_input #residual 操作)
3.輸出最后一層transformer的輸出[B,F,N*H] 進行pooler操作(取第一個位置的輸出)
然后再進行全連接層+tanh激活作為輸出,也就是[B,N*H]
綜上,其實BERT主要這么深(12層)也是靠的sum residual的設(shè)計。muli-head attention確實有意思,其中的trick很多,比如pool操作,比如scale操作,layer norm操作等。