日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【NLP】Transformers 源码阅读和实践

發布時間:2025/3/12 编程问答 67 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【NLP】Transformers 源码阅读和实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文主要針對HuggingFace開源的 transformers,以BERT為例介紹其源碼并進行一些實踐。主要以pytorch為例 (tf 2.0 代碼風格幾乎和pytorch一致),介紹BERT使用的Transformer Encoder,Pre-training Tasks和Fine-tuning Tasks。最后,針對預訓練好的BERT進行簡單的實踐,例如產出語句embeddings,預測目標詞以及進行抽取式問答。本文主要面向BERT新手,在閱讀本文章前,假設讀者已經閱讀過BERT原論文。

1. Core Components

Transformers: State-of-the-art Natural Language Processing

參考上面的論文,transformers開源庫的核心組件包括3個:

  • 「Con?guration」:配置類,通常繼承自「PretrainedCon?g」,保存model或tokenizer的超參數,例如詞典大小,隱層維度數,dropout rate等。配置類主要可用于復現模型。

  • 「Tokenizer」:切詞類,通常繼承自「PreTrainedTokenizer」,主要存儲詞典,token到index映射關系等。此外,還會有一些model-specific的特性,如特殊token,[SEP], [CLS]等的處理,token的type類型處理,語句最大長度等,因此tokenizer通常和模型是一對一適配的。比如BERT模型有BertTokenizer。Tokenizer的實現方式有多種,如word-level, character-level或者subword-level,其中subword-level包括Byte-Pair-Encoding,WordPiece。subword-level的方法目前是transformer-based models的主流方法,能夠有效解決OOV問題,學習詞綴之間的關系等。Tokenizer主要為了「將原始的語料編碼成適配模型的輸入。」

  • 「Model」: 模型類。封裝了預訓練模型的計算圖過程,遵循著相同的范式,如根據token ids進行embedding matrix映射,緊接著多個self-attention層做編碼,最后一層task-specific做預測。除此之外,Model還可以做一些靈活的擴展,用于下游任務,例如在預訓練好的Base模型基礎上,添加task-specific heads。比如,language model heads,sequence classi?cation heads等。在代碼庫中通常命名為,「XXXForSequenceClassification」 or 「XXXForMaskedLM」,其中XXX是模型的名稱(如Bert), 結尾是預訓練任務的名稱 (MaskedLM) 或下游任務的類型(SequenceClassification)。

另外,針對上述三大類,transformer還額外封裝了「AutoConfig, AutoTokenizer,AutoModel」,可通過模型的命名來定位其所屬的具體類,比如'bert-base-cased',就可以知道要加載BERT模型相關的配置、切詞器和模型。非常方便。通常上手時,我們都會用Auto封裝類來加載切詞器和模型。

2. Transformer-based Pre-trained model

所有已實現的Transformer-based Pre-trained models:

CONFIG_MAPPING?=?OrderedDict([("retribert",?RetriBertConfig,),("t5",?T5Config,),("mobilebert",?MobileBertConfig,),("distilbert",?DistilBertConfig,),("albert",?AlbertConfig,),("camembert",?CamembertConfig,),("xlm-roberta",?XLMRobertaConfig,),("marian",?MarianConfig,),("mbart",?MBartConfig,),("bart",?BartConfig,),("reformer",?ReformerConfig,),("longformer",?LongformerConfig,),("roberta",?RobertaConfig,),("flaubert",?FlaubertConfig,),("bert",?BertConfig,),("openai-gpt",?OpenAIGPTConfig,),("gpt2",?GPT2Config,),("transfo-xl",?TransfoXLConfig,),("xlnet",?XLNetConfig,),("xlm",?XLMConfig,),("ctrl",?CTRLConfig,),("electra",?ElectraConfig,),("encoder-decoder",?EncoderDecoderConfig,),]

上述是該開源庫實現的模型,包括了BERT,GPT2,XLNet,RoBERTa,ALBERT,ELECTRA,T5等家喻戶曉的預訓練語言模型。

下面將以BERT為例,來介紹BERT相關的源碼。建議仔細閱讀源碼中我做的一些「注釋」,尤其是「步驟的細分」。同時,關注下目錄的層次,「即:不同類之間的關系。」

2.1 BertModel Transformer

「BertModel」, The bare Bert Model transformer outputting 「raw hidden-states」 without any specific head on top。這個類的目標主要就是利用「Transformer」獲取序列的編碼向量。抽象出來的目標是為了適配不同的預訓練任務。例如:MLM預訓練任務對應的類為BertForMaskedLM,其中有個成員實例為BertModel,就是為了編碼序列,獲取序列的hidden states后,再構建MaskedLM task進行訓練或者預測。

核心構造函數和Forward流程代碼如下:

#?BertModel的構造函數 def?__init__(self,?config):super().__init__(config)self.config?=?configself.embeddings?=?BertEmbeddings(config)self.encoder?=?BertEncoder(config)self.pooler?=?BertPooler(config)self.init_weights()def?forward(self,?input_ids=None,?attention_mask=None,token_type_ids=None,????position_ids=None,?head_mask=None,?inputs_embeds=None,encoder_hidden_states=None,?encoder_attention_mask=None,output_attentions=None,?output_hidden_states=None,):#?ignore?some?code?here...#?step?1:?obtain?sequence?embedding,?BertEmbeddings?embedding_output?=?self.embeddings(input_ids=input_ids,?position_ids=position_ids,?token_type_ids=token_type_ids,?inputs_embeds=inputs_embeds)#?step?2:?transformer?encoder,?BertEncoderencoder_outputs?=?self.encoder(embedding_output,attention_mask=extended_attention_mask,head_mask=head_mask,encoder_hidden_states=encoder_hidden_states,encoder_attention_mask=encoder_extended_attention_mask,output_attentions=output_attentions,output_hidden_states=output_hidden_states,)sequence_output?=?encoder_outputs[0]#?step?3:?pooling?to?obtain?sequence-level?encoding,?BertPoolerpooled_output?=?self.pooler(sequence_output)outputs?=?(sequence_output,?pooled_output,)?+?encoder_outputs[1:]return?outputs??#?sequence_output,?pooled_output,?(hidden_states),?(attentions)

「參數如下:」

  • 「input_ids」: 帶特殊標記([CLS]、[SEP])的「token ids」序列, e.g., tensor([[ 101, 1188, 1110, 1126, 7758, 1859, 102]]), 其中101和102分別是[CLS],[SEP]對應的token id。其「shape」: ,「B」為batch size, 「S」為序列的長度,此例即:1x7。

  • 「inputs_embeds:」 和input_ids參數「二選一」。inputs_embeds代表給定了輸入tokens對應的token embeddings,比如用word2vec的word embeddings作為token embeddings,這樣就不需要用input_ids對默認隨機初始化的embedding做lookup得到token embeddings。

  • 「attention_mask」: 「self-attention使用」,可選,shape和input_ids一致。當對encoder端的序列做self-attention時,默認全為1,即都可以attend;decoder端序列做self-attention時,默認為類似下三角矩陣的形式 (對角線也為1)。

  • 「token_type_ids」: 可選,shape和input_ids一致,單語句輸入時,取值全為0;在“語句對“的輸入中,該取值為0或1,即:前一句為0,后一句為1。

  • 「head_mask」: **self-attention使用,**可選,想用哪些head,就為1或者None,不想用的head就為0。shape為[num_heads] or [num_hidden_layers x num_heads],即:可以每層每個head單獨設置mask。

  • 「position_ids」: 可選,位置id,默認就是0~S。

  • 「encoder_hidden_states/encoder_attention_mask」:decoder端對encoder端做cross-attention時使用,此時K和V即通過encoder_hidden_states得到。

其中,

  • 「Step 1」: 「獲取序列的embedding」,對應下文要介紹的「BertEmbeddings」

  • 「Step 2」: 「利用Transformer進行編碼」,對應下文要介紹的「BertEncoder」,獲取sequence token-level encoding.

  • 「Step 3」: 「對 [CLS] 對應的hidden state進行非線性變換得到」 sequence-level encoding,對應下文要介紹的「BertPooler」。

2.2 BertEmbeddings

「第一步Step 1」,獲取序列的embeddings

「token embedding + position embedding + segment embedding」

embedding_output?=?self.embeddings(input_ids=input_ids,?position_ids=position_ids,?token_type_ids=token_type_ids,?inputs_embeds=inputs_embeds)?#?embeddings是BertEmbeddings類
  • 基于input_ids或者inputs_embeds獲取token embeddings。

  • 基于position_ids獲取position embeddings,此處采用的是絕對位置編碼。

  • 基于token_type_ids獲取語句的segment embeddings。

#?BertEmbeddings?core?forward?code:? def?forward(self,?input_ids=None,?token_type_ids=None,position_ids=None,?inputs_embeds=None):#?ignore?some?codes?here...#?step?1:?token?embeddingsif?inputs_embeds?is?None:inputs_embeds?=?self.word_embeddings(input_ids)?#?token?embeddings#?step?2:?position?embeddingsposition_embeddings?=?self.position_embeddings(position_ids)#?step?3:?segment?embeddingstoken_type_embeddings?=?self.token_type_embeddings(token_type_ids)embeddings?=?inputs_embeds?+?position_embeddings?+?token_type_embeddingsembeddings?=?self.LayerNorm(embeddings)embeddings?=?self.dropout(embeddings)return?embeddings

此處還做了layer_norm和dropout。輸出的embedding的shape為,。D默認為768。此處輸出的embeddings標記為。

2.3 BertEncoder

「第二步,step 2」,利用「Transformer」對序列進行編碼

#?encoder是BertEncoder類 encoder_outputs?=?self.encoder(embedding_output,?#?序列embedding,?B?x?S?x?Dattention_mask=extended_attention_mask,?#?序列self-attention時使用head_mask=head_mask,?#?序列self-attention時使用encoder_hidden_states=encoder_hidden_states,?#?decoder,cross-attentionencoder_attention_mask=encoder_extended_attention_mask,?#?cross-attentionoutput_attentions=output_attentions,?#?是否輸出attentionoutput_hidden_states=output_hidden_states)??#?是否輸出每層的hidden?state
  • 「embedding_output」:BertEmbeddings的輸出,batch中樣本序列的每個token的嵌入。

  • 「extended_attention_mask」「self-attention」使用。根據attention_mask做維度廣播,是head數量,此時,方便下文做self-attention時作mask,即:softmax前對logits作處理,「logits+extended_attention_mask」,即:attention_mask取值為1時,extended_attention_mask對應位置的取值為0;否則,attention_mask為0時,extended_attention_mask對應位置的取值為-10000.0 (很小的一個數),這樣softmax后,mask很小的值對應的位置概率接近0達到mask的目的。

  • 「head_mask」「self-attention」使用。同樣可以基于「原始輸入head_mask作維度廣播」,廣播前的shape為H or L x H;廣播后的shape為:「L x B x H x S x S」。即每個樣本序列中每個token對其他tokens的head attentions 值作mask,head attentions數量為L x H。

  • 「encoder_hidden_states」:可選,「cross-attention使用」。即:decoder端做編碼時,要傳入encoder的隱狀態,「B x S x D」。

  • 「encoder_attention_mask」:可選,「cross-attention使用」。即,decoder端做編碼時,encoder的隱狀態的attention mask。和extended_attention_mask類似,「B x S。」

  • 「output_attentions」:是否輸出attention值,bool??捎糜诳梢暬痑ttention scores。

  • 「output_hidden_states」:是否輸出每層得到的隱向量,bool。

#?BertEncoder由12層BertLayer構成 self.layer?=?nn.ModuleList([BertLayer(config)?for?_?in?range(config.num_hidden_layers)]) #?BertEncoder?Forward核心代碼 def?forward(self,?hidden_states,attention_mask=None,?head_mask=None,encoder_hidden_states=None,?encoder_attention_mask=None,output_attentions=False,?output_hidden_states=False):#?ignore?some?codes?here...all_hidden_states?=?()all_attentions?=?()for?i,?layer_module?in?enumerate(self.layer):?#?12層BertLayerif?output_hidden_states:all_hidden_states?=?all_hidden_states?+?(hidden_states,)#?step?1:?BertLayer?iterationlayer_outputs?=?layer_module(hidden_states,attention_mask,head_mask[i],encoder_hidden_states,encoder_attention_mask,output_attentions)?# BertLayer Forward,核心!!!hidden_states?=?layer_outputs[0]?#?overide?for?next?iterationif?output_attentions:all_attentions?=?all_attentions?+?(layer_outputs[1],)?#?存每層的attentions,可以用于可視化#?Add?last?layerif?output_hidden_states:all_hidden_states?=?all_hidden_states?+?(hidden_states,)outputs?=?(hidden_states,)if?output_hidden_states:outputs?=?outputs?+?(all_hidden_states,)if?output_attentions:outputs?=?outputs?+?(all_attentions,)return?outputs??#?last-layer?hidden?state,?(all?hidden?states),?(all?attentions)

2.4 BertLayer

上述代碼最重要的是循環內的「BertLayer」迭代過程,其核心代碼:

def?forward(self,?hidden_states,?attention_mask=None,?head_mask=None,encoder_hidden_states=None,?encoder_attention_mask=None,output_attentions=False,):#?step?1.0:?self-attention,?attention實例是BertAttention類self_attention_outputs?=?self.attention(hidden_states,?attention_mask,?head_mask,?output_attentions=output_attentions,)attention_output?=?self_attention_outputs[0]outputs?=?self_attention_outputs[1:]??#?add?self?attentions?if?we?output?attention?weights# step 1.1:?如果是decoder, 就作cross-attention,此時step1.0的輸出即為decoder側的序列的self-attention結果,并作為step1.1的輸入;step 1.1的輸出為decoder側的cross-attention結果, crossattention實例也是BertAttentionif?self.is_decoder?and?encoder_hidden_states?is?not?None:cross_attention_outputs?=?self.crossattention(attention_output,attention_mask,head_mask,encoder_hidden_states,encoder_attention_mask,output_attentions,)attention_output?=?cross_attention_outputs[0]outputs?=?outputs?+?cross_attention_outputs[1:]??#?add?cross?attentions?if?we?output?attention?weights#?step?2:?intermediate轉化,對應原論文中的前饋神經網絡FFNintermediate_output?=?self.intermediate(attention_output)#?step?3:?做skip-connectionlayer_output?=?self.output(intermediate_output,?attention_output)outputs?=?(layer_output,)?+?outputsreturn?outputs

其中,step 1分為了2個小步驟。如果是encoder (BERT只用了encoder),只有1.0起作用,即只對輸入序列進行self-attention。如果是做seq2seq的模型,還會用到transformer的decoder,此時1.0就是對decoder的seq做self-attention,相應的attention_mask實際上是類下三角形式的矩陣;而1.1步驟此時就是基于1.0得到的self-attention序列的hidden states,對encoder_hidden_states進行cross-attention。這是本部分的重點。

2.4.1 BertAttention

BertAttention是上述代碼中attention實例對應的類,也是transformer進行self-attention的核心類。包括了BertSelfAttention和BertSelfOutput成員。

class?BertAttention(nn.Module):def?__init__(self,?config):super().__init__()self.self?=?BertSelfAttention(config)self.output?=?BertSelfOutput(config)def?forward(self,?hidden_states,?attention_mask=None,head_mask=None,?encoder_hidden_states=None,encoder_attention_mask=None,?output_attentions=False):#?step?1:?self-attention,?B?x?S?x?Dself_outputs?=?self.self(hidden_states,?attention_mask,?head_mask,?encoder_hidden_states,?encoder_attention_mask,?output_attentions)#?step?2:?skip-connection,?B?x?S?x?Dattention_output?=?self.output(self_outputs[0],?hidden_states)outputs?=?(attention_output,)?+?self_outputs[1:]??#?add?attentions?if?we?output?themreturn?outputs
  • 「BertSelfAttention」: 是「self-attention」,BertSelfAttention可以被實例化為encoder側的self-attention,也可以被實例化為decoder側的self-attention,此時attention_mask是非空的 (類似下三角形式的mask矩陣)。同時,還可以實例化為decoder側的cross-attention,此時,hidden_states即為decoder側序列的self-attention結果,同時需要傳入encoder側的encoder_hidden_states和encoder_attention_mask來進行cross-attention。

    def?forward(self,?hidden_states,?attention_mask=None,?head_mask=None,encoder_hidden_states=None,?encoder_attention_mask=None,output_attentions=False):#?step?1:?mapping?Query/Key/Value?to?sub-space#?step?1.1:?query?mappingmixed_query_layer?=?self.query(hidden_states)?#?B?x?S?x?(H*d)#?If?this?is?instantiated?as?a?cross-attention?module,?the?keys#?and?values?come?from?an?encoder;?the?attention?mask?needs?to?be#?such?that?the?encoder's?padding?tokens?are?not?attended?to.#?step?1.2:?key/value?mappingif?encoder_hidden_states?is?not?None:mixed_key_layer?=?self.key(encoder_hidden_states)?#?B?x?S?x?(H*d)mixed_value_layer?=?self.value(encoder_hidden_states)?attention_mask?=?encoder_attention_mask?else:mixed_key_layer?=?self.key(hidden_states)?#?B?x?S?x?(H*d)mixed_value_layer?=?self.value(hidden_states)query_layer?=?self.transpose_for_scores(mixed_query_layer)?#?B?x?H?x?S?x?dkey_layer?=?self.transpose_for_scores(mixed_key_layer)?#?B?x?H?x?S?x?dvalue_layer?=?self.transpose_for_scores(mixed_value_layer)?#?B?x?H?x?S?x?d#?step?2:?compute?attention?scores#?step?2.1:?raw?attention?scores#?B?x?H?x?S?x?d???B?x?H?x?d?x?S?->?B?x?H?x?S?x?S#?Take?the?dot?product?between?"query"?and?"key"?to?get?the?raw?attention?scores.attention_scores?=?torch.matmul(query_layer,?key_layer.transpose(-1,?-2))attention_scores?=?attention_scores?/?math.sqrt(self.attention_head_size)#?step?2.2:?mask?if?necessaryif?attention_mask?is?not?None:#?Apply?the?attention?mask,?B?x?H?x?S?x?Sattention_scores?=?attention_scores?+?attention_mask#?step?2.3:?Normalize?the?attention?scores?to?probabilities,?B?x?H?x?S?x?Sattention_probs?=?nn.Softmax(dim=-1)(attention_scores)#?This?is?actually?dropping?out?entire?tokens?to?attend?to,?which?might#?seem?a?bit?unusual,?but?is?taken?from?the?original?Transformer?paper.attention_probs?=?self.dropout(attention_probs)#?Mask?heads?if?we?want?toif?head_mask?is?not?None:attention_probs?=?attention_probs?*?head_mask#?B?x?H?x?S?x?S???B?x?H?x?S?x?d?->??B?x?H?x?S?x?d#?step?4:?aggregate?values?by?attention?probs?to?form?context?encodingscontext_layer?=?torch.matmul(attention_probs,?value_layer)#?B?x?S?x?H?x?dcontext_layer?=?context_layer.permute(0,?2,?1,?3).contiguous()#?B?x?S?x?Dnew_context_layer_shape?=?context_layer.size()[:-2]?+?(self.all_head_size,)#?B?x?S?x?D,相當于是多頭concat操作context_layer?=?context_layer.view(*new_context_layer_shape)outputs?=?(context_layer,?attention_probs)?if?output_attentions?else?(context_layer,)return?outputs

    不同head均分768維度,12個head則每個為64維度;具體計算的時候合在一起,即同時算multi-head。記本步驟的輸出為: ,輸入即為hidden_states參數。

    • ?; ? ? ?,每個token根據其對序列內其它tokens的attention scores,來加權序列tokens的embeddings,得到每個token對應的上下文編碼向量。

    • reshape后的形狀為,, 。

    • : ?,「transpose_for_scores」。

    • : ?

    • ,

    • , 如果是decoder側的self-attention,則logit加上預先計算好的decoder側對應的序列的每個位置的attention_mask,實際上就是下三角形式(包括對角線)的mask矩陣。

    • , :每個batch每個head內,每個token對序列內其它token的attention score。

    • 、、的shape: ? : 「<Batch Size, Seq Length, Head Num, Embedding Dimension>」,。此處D=768, H=12, d=64。

    • 「attention score計算過程:」

    • 「context_layer」: ?:

  • 「BertSelfOutput」

    • , 「self-connection」,

2.4.2 BertIntermediate

  • , , 其中, 默認值為3072,用到了gelu激活函數。

2.4.3 BertOutput

  • , ,其中,.

上述輸出作為下一個BertLayer的輸入,輸出,依次類推,進行迭代,最終輸出,即共12層BertLayer。

2.5 BertPooler

第三步,step3, 獲取sequence-level embedding。

拿到上述BertEncoder的輸出,shape為,其中每個樣本序列(S維度)的第一個token為[CLS]標識的hidden state,標識為,即:。則得到序列級別的嵌入表征:,shape為。這個主要用于下游任務的fine-tuning。

def?forward(self,?hidden_states):#?We?"pool"?the?model?by?simply?taking?the?hidden?state?corresponding#?to?the?first?token.first_token_tensor?=?hidden_states[:,?0]pooled_output?=?self.dense(first_token_tensor)pooled_output?=?self.activation(pooled_output)?##?nn.tanhreturn?pooled_output

3. Bert Pre-training Tasks

上文介紹了BERT核心的Transformer編碼器,下面將介紹Bert的預訓練任務。

3.1 BertForMaskedLM

Bert Model with 「a language modeling head」 on top。上述介紹了BertModel的源碼,BertModel主要用于獲取序列的編碼。本部分要介紹的BertForMaskedLM將基于BertModel得到的序列編碼,利用MaskedLM預訓練任務進行預訓練。

Bert主要利用了Transformer的Encoder,基于encoder得到的序列編碼進行預訓練,而MLM使得encoder能夠進行雙向的self-attention。

「BertForMaskedLM」的構造函數:

def?__init__(self,?config):super().__init__(config)assert?(not?config.is_decoder),?"If?you?want?to?use?`BertForMaskedLM`?make?sure?`config.is_decoder=False`?for?bi-directional?self-attention."?#?is_decoder為False,不需要用到decoderself.bert?=?BertModel(config)?#?BertModel進行序列編碼self.cls?=?BertOnlyMLMHead(config)?#?多分類預訓練任務,?task-specific?headself.init_weights()

核心Forward代碼:

def?forward(self,?input_ids=None,?attention_mask=None,?token_type_ids=None,position_ids=None,?head_mask=None,?inputs_embeds=None,?labels=None,encoder_hidden_states=None,?encoder_attention_mask=None,output_attentions=None,?output_hidden_states=None,**kwargs):#?step?1:?obtain?sequence?encoding?by?BertModeloutputs?=?self.bert(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,)sequence_output?=?outputs[0]?#?B?x?S?x?D#?step?2:?output?scores?of?each?token?in?the?sequenceprediction_scores?=?self.cls(sequence_output)?#?B?x?S?x?V,?輸出詞典中每個詞的預測概率outputs?=?(prediction_scores,)?+?outputs[2:]??#?Add?hidden?states?and?attention?if?they?are?here#?step?3:?build?loss,?label,?B?x?Sif?labels?is?not?None:loss_fct?=?CrossEntropyLoss()??#?-100?index?=?padding?tokenmasked_lm_loss?=?loss_fct(prediction_scores.view(-1,?self.config.vocab_size),?labels.view(-1))?#?拍扁,?(B*S)?x?Voutputs?=?(masked_lm_loss,)?+?outputsreturn?outputs??#?(masked_lm_loss),?prediction_scores,?(hidden_states),?(attentions)

參數基本上和BertModel一模一樣,多了一個labels參數,主要用于獲取MLM loss。

其中,cls對應的「BertOnlyMLMHead」類 (其實就是類「BertLMPredictionHead」) 做的主要事情如下公式,即:MLM多分類預測任務,其中為BertModel得到的sequence-token-level encoding,shape為。

其中,,為vocab的大小。的shape為:。

特別的,label的形式:

「labels」 (torch.LongTensor of shape (batch_size, sequence_length), optional, defaults to None) – Labels for computing the masked language modeling loss. Indices should be in [-100, 0, ..., config.vocab_size] (see input_ids docstring) Tokens with indices set to -100 are ignored (masked), the loss is only computed for the tokens with labels in [0, ..., config.vocab_size]

即,不打算預測的,「label設置為-100」。一般只設置[MASK]位置對應的label,其它位置設置成-100。這樣只計算了[MASK]待預測位置的token對應的loss。-100實際上是CrossEntropyLos的ignore_index參數的默認值。

3.2 BertForPreTraining

和BertForMaskedLM類似,多了一個next sentence prediction預訓練任務。Bert Model with 「two heads on top」 as done during the pre-training: a 「masked language modeling」 head and 「a next sentence prediction」 (classification) head.

此部分對應的heads的核心代碼為:

class?BertPreTrainingHeads(nn.Module):def?__init__(self,?config):super().__init__()self.predictions?=?BertLMPredictionHead(config)self.seq_relationship?=?nn.Linear(config.hidden_size,?2)def?forward(self,?sequence_output,?pooled_output):prediction_scores?=?self.predictions(sequence_output)seq_relationship_score?=?self.seq_relationship(pooled_output)return?prediction_scores,?seq_relationship_score

其中,BertLMPredictionHead和BertForMaskedLM中的BertLMPredictionHead一樣,通過這個來得到MLM loss。另外,多了一個seq_relationship,即拿pooled encoding接一個線性二分類層,判斷是否是next sentence,因此可以構造得到next-sentence loss。二者Loss相加。

3.3 BertForNextSentencePrediction

Bert Model with a next sentence prediction (classification) head on top。只有上述的seq_relationship head來構造next-sentence loss,不作贅述。

4. Bert Fine-tuning Tasks

下面將介紹利用預訓練好的Bert對下游任務進行Fine-tuning的方式。下文介紹的fine-tuning任務對應的model,已經在BERT基礎上加了task-specific parameters,只需要利用該model,輸入task-specific data,然后optimization一下,就能夠得到fine-tuned model。

4.1 BertForSequenceClassification

句子級別的任務,sentence-level task。Bert Model transformer with a sequence classification/regression head on top ?(a linear layer on top of the pooled output) e.g. 「for GLUE tasks.」

class?BertForSequenceClassification(BertPreTrainedModel):def?__init__(self,?config):super().__init__(config)self.num_labels?=?config.num_labelsself.bert?=?BertModel(config)self.dropout?=?nn.Dropout(config.hidden_dropout_prob)self.classifier?=?nn.Linear(config.hidden_size,?config.num_labels)?#?類別數量self.init_weights()#?forward輸入參數和前文介紹的預訓練任務一樣def?forward(self,?input_ids=None,?attention_mask=None,token_type_ids=None,?position_ids=None,head_mask=None,?inputs_embeds=None,?labels=None,output_attentions=None,?output_hidden_states=None):#?step?1:?transformer?encodingoutputs?=?self.bert(input_ids,attention_mask=attention_mask,token_type_ids=token_type_ids,position_ids=position_ids,head_mask=head_mask,inputs_embeds=inputs_embeds,output_attentions=output_attentions,output_hidden_states=output_hidden_states)#?step?2:?use?the?pooled?hidden?state?corresponding?to?the?[CLS]?token#?B?x?Dpooled_output?=?outputs[1]pooled_output?=?self.dropout(pooled_output)#?B?x?Nlogits?=?self.classifier(pooled_output)outputs?=?(logits,)?+?outputs[2:]??#?add?hidden?states?and?attention?if?they?are?here#?step?3:?build?loss,??labels:?(B,?)if?labels?is?not?None:if?self.num_labels?==?1:#??We?are?doing?regressionloss_fct?=?MSELoss()loss?=?loss_fct(logits.view(-1),?labels.view(-1))else:loss_fct?=?CrossEntropyLoss()loss?=?loss_fct(logits.view(-1,?self.num_labels),?labels.view(-1))outputs?=?(loss,)?+?outputsreturn?outputs??#?(loss),?logits,?(hidden_states),?(attentions)

看上述代碼,非常清晰。先經過BertModel得到encoding,由于是sentence-level classification,直接拿第一個[CLS] token對應的hidden state過一個分類層得到類別的預測分數logits。再基于logits和labels來構造損失函數。這個任務主要用于sentence-level的分類任務,當然也能夠用于sentence-pair-level的分類任務。

4.2 BertForMultipleChoice

句子對級別的任務,「sentence-pair」-level task。Bert Model with a multiple choice classification head on top (a linear layer on top of the pooled output and a softmax) e.g. for 「RocStories/SWAG tasks.」

給一個提示prompt以及多個選擇choice(其中有1個是對的,其它是錯的),判斷其中哪個選擇是對的。「輸入格式會整成[[prompt, choice0], [prompt, choice1]…]的形式」。bertModel得到的pooled基礎上接一個全連接層,輸出在每個“句對“[prompt, choice i]上的logits,然后過一個softmax,構造交叉熵損失。

4.3 BertForTokenClassification

token級別的下游任務,token-level task。Bert Model with a token classification head on top (a linear layer on top of the hidden-states output) e.g. for 「Named-Entity-Recognition (NER) tasks.」

def?forward(self,?input_ids=None,?attention_mask=None,token_type_ids=None,?position_ids=None,?head_mask=None,inputs_embeds=None,?labels=None,output_attentions=None,?output_hidden_states=None):????#?step?1:?Transformeroutputs?=?self.bert(input_ids,?attention_mask=attention_mask,token_type_ids=token_type_ids,?position_ids=position_ids,head_mask=head_mask,?inputs_embeds=inputs_embeds,output_attentions=output_attentions,output_hidden_states=output_hidden_states)#?step?2:?get?sequence-token?encoding,?B?x?S?x?Dsequence_output?=?outputs[0]#?step?3:?fine-tuning?parameterssequence_output?=?self.dropout(sequence_output)#?B?x?S?x?Nlogits?=?self.classifier(sequence_output)?#?nn.Linear(config.hidden_size,?config.num_labels)outputs?=?(logits,)?+?outputs[2:]??#?add?hidden?states?and?attention?if?they?are?here#?step?4:?build?loss,?labels,?B?x?Sif?labels?is?not?None:loss_fct?=?CrossEntropyLoss()#?Only?keep?active?parts?of?the?lossif?attention_mask?is?not?None:active_loss?=?attention_mask.view(-1)?==?1active_logits?=?logits.view(-1,?self.num_labels)active_labels?=?torch.where(active_loss,?labels.view(-1),?torch.tensor(loss_fct.ignore_index).type_as(labels))loss?=?loss_fct(active_logits,?active_labels)else:loss?=?loss_fct(logits.view(-1,?self.num_labels),?labels.view(-1))outputs?=?(loss,)?+?outputsreturn?outputs??#?(loss),?scores,?(hidden_states),?(attentions)

上述代碼一目了然。不作贅述。主要應用于token-level的分類任務,如NER等。

4.4 BertForQuestionAnswering

句子對級別的任務,「sentence-pair」-level task,具體而言,即抽取式問答任務。Bert Model with a 「span classification head on top」 for extractive question-answering tasks like SQuAD (a linear layers on top of the hidden-states output to compute span start logits and span end logits).

class?BertForQuestionAnswering(BertPreTrainedModel):def?__init__(self,?config):super().__init__(config)self.num_labels?=?config.num_labelsself.bert?=?BertModel(config)# num_labels為2, 分別代表start_position/end_position對應的下游參數。self.qa_outputs?=?nn.Linear(config.hidden_size,?config.num_labels)self.init_weights()#?多了倆參數,start_positions,end_positions,抽取式問答的span label,?shape都是(B,?)def?forward(self,?input_ids=None,?attention_mask=None,token_type_ids=None,?position_ids=None,head_mask=None,?inputs_embeds=None,start_positions=None,?end_positions=None,output_attentions=None,?output_hidden_states=None):#?step?1:?Transformer?encodingoutputs?=?self.bert(input_ids,?#?question,?passage?attention_mask=attention_mask,token_type_ids=token_type_ids,position_ids=position_ids,head_mask=head_mask,inputs_embeds=inputs_embeds,output_attentions=output_attentions,output_hidden_states=output_hidden_states,)#?B?x?S?x?Dsequence_output?=?outputs[0]#?step?2:?split?to?obtain?start?and?end?logits#?B?x?S?x?N?(N為labels數量,此處N=2)logits?=?self.qa_outputs(sequence_output)#?split后,?B?x?S?x?1,?B?x?S?x?1start_logits,?end_logits?=?logits.split(1,?dim=-1)#?B?x?S,?B?x?Sstart_logits?=?start_logits.squeeze(-1)end_logits?=?end_logits.squeeze(-1)outputs?=?(start_logits,?end_logits,)?+?outputs[2:]#?step?3:?build?loss,??start_positions,?end_positions:?(B,?)if?start_positions?is?not?None?and?end_positions?is?not?None:#?If?we?are?on?multi-GPU,?split?add?a?dimensionif?len(start_positions.size())?>?1:start_positions?=?start_positions.squeeze(-1)if?len(end_positions.size())?>?1:end_positions?=?end_positions.squeeze(-1)#?sometimes?the?start/end?positions?are?outside?our?model?inputs,?we?ignore?these?termsignored_index?=?start_logits.size(1)start_positions.clamp_(0,?ignored_index)end_positions.clamp_(0,?ignored_index)#?S?分類loss_fct?=?CrossEntropyLoss(ignore_index=ignored_index)start_loss?=?loss_fct(start_logits,?start_positions)end_loss?=?loss_fct(end_logits,?end_positions)total_loss?=?(start_loss?+?end_loss)?/?2outputs?=?(total_loss,)?+?outputsreturn?outputs??#?(loss),?start_logits,?end_logits,?(hidden_states),?(attentions)

上述代碼主要就是拿sequence-token-level hidden states接兩個全連接層,分別輸出start_position預測的logits和end_position預測的logits。

5. Bert Practice

本部分進行Bert的實踐,包括3個部分:

  • 利用預訓練好的BERT模型,輸出目標語句的Embeddings。

  • 利用預訓練好的BERT模型,預測目標語句中[MASK]位置的真實詞。

  • 利用預訓練好的BERT模型,進行抽取式問答系統。

目前該庫實現的預訓練模型如下:

  • bert-base-chinese

  • bert-base-uncased

  • bert-base-cased

  • bert-base-german-cased

  • bert-base-multilingual-uncased

  • bert-base-multilingual-cased

  • bert-large-cased

  • bert-large-uncased

  • bert-large-uncased-whole-word-masking

  • bert-large-cased-whole-word-masking

上述預訓練好的模型的主要差異在于:

  • 預訓練時的文本語言語料,中文、英文、德文、多語言等

  • 有無大小寫區分

  • 層數

  • 預訓練時遮蓋的是 wordpieces 得到的sub-word 還是整個word

接下來主要采用'bert-base-cased'。在QA部分還會使用上述預訓練模型‘bert-large-uncased-whole-word-masking’在SQUAD上的fine-tuning好的模型進行推斷。

首先加載「切割器和模型:」

MODEL_NAME?=?"bert-base-cased"#?step?1:?先獲取tokenizer,?BertTokenizer,? tokenizer?=?AutoTokenizer.from_pretrained(MODEL_NAME,?cache_dir='tmp/token')? #?step?2:?獲取預訓練好的模型,?BertModel model?=?AutoModel.from_pretrained(MODEL_NAME,?cache_dir='tmp/model')

預覽下tokenizer (「transformers.tokenization_bert.BertTokenizer」):

#?共28996詞,包括特殊符號:('[UNK]',?100),('[PAD]',?0),('[CLS]',?101),('[SEP]',?102),?('[MASK]',?103)... tokenizer.vocab?

看下「model」的網絡結構:

BertModel((embeddings):?BertEmbeddings((word_embeddings):?Embedding(28996,?768,?padding_idx=0)(position_embeddings):?Embedding(512,?768)(token_type_embeddings):?Embedding(2,?768)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False))(encoder):?BertEncoder((layer):?ModuleList((0):?BertLayer((attention):?BertAttention((self):?BertSelfAttention((query):?Linear(in_features=768,?out_features=768,?bias=True)(key):?Linear(in_features=768,?out_features=768,?bias=True)(value):?Linear(in_features=768,?out_features=768,?bias=True)(dropout):?Dropout(p=0.1,?inplace=False))(output):?BertSelfOutput((dense):?Linear(in_features=768,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(intermediate):?BertIntermediate((dense):?Linear(in_features=768,?out_features=3072,?bias=True))(output):?BertOutput((dense):?Linear(in_features=3072,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(1):?BertLayer((attention):?BertAttention((self):?BertSelfAttention((query):?Linear(in_features=768,?out_features=768,?bias=True)(key):?Linear(in_features=768,?out_features=768,?bias=True)(value):?Linear(in_features=768,?out_features=768,?bias=True)(dropout):?Dropout(p=0.1,?inplace=False))(output):?BertSelfOutput((dense):?Linear(in_features=768,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(intermediate):?BertIntermediate((dense):?Linear(in_features=768,?out_features=3072,?bias=True))(output):?BertOutput((dense):?Linear(in_features=3072,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(2):?BertLayer((attention):?BertAttention((self):?BertSelfAttention((query):?Linear(in_features=768,?out_features=768,?bias=True)(key):?Linear(in_features=768,?out_features=768,?bias=True)(value):?Linear(in_features=768,?out_features=768,?bias=True)(dropout):?Dropout(p=0.1,?inplace=False))(output):?BertSelfOutput((dense):?Linear(in_features=768,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(intermediate):?BertIntermediate((dense):?Linear(in_features=768,?out_features=3072,?bias=True))(output):?BertOutput((dense):?Linear(in_features=3072,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(3):?BertLayer((attention):?BertAttention((self):?BertSelfAttention((query):?Linear(in_features=768,?out_features=768,?bias=True)(key):?Linear(in_features=768,?out_features=768,?bias=True)(value):?Linear(in_features=768,?out_features=768,?bias=True)(dropout):?Dropout(p=0.1,?inplace=False))(output):?BertSelfOutput((dense):?Linear(in_features=768,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(intermediate):?BertIntermediate((dense):?Linear(in_features=768,?out_features=3072,?bias=True))(output):?BertOutput((dense):?Linear(in_features=3072,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(4):?BertLayer((attention):?BertAttention((self):?BertSelfAttention((query):?Linear(in_features=768,?out_features=768,?bias=True)(key):?Linear(in_features=768,?out_features=768,?bias=True)(value):?Linear(in_features=768,?out_features=768,?bias=True)(dropout):?Dropout(p=0.1,?inplace=False))(output):?BertSelfOutput((dense):?Linear(in_features=768,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(intermediate):?BertIntermediate((dense):?Linear(in_features=768,?out_features=3072,?bias=True))(output):?BertOutput((dense):?Linear(in_features=3072,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(5):?BertLayer((attention):?BertAttention((self):?BertSelfAttention((query):?Linear(in_features=768,?out_features=768,?bias=True)(key):?Linear(in_features=768,?out_features=768,?bias=True)(value):?Linear(in_features=768,?out_features=768,?bias=True)(dropout):?Dropout(p=0.1,?inplace=False))(output):?BertSelfOutput((dense):?Linear(in_features=768,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(intermediate):?BertIntermediate((dense):?Linear(in_features=768,?out_features=3072,?bias=True))(output):?BertOutput((dense):?Linear(in_features=3072,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(6):?BertLayer((attention):?BertAttention((self):?BertSelfAttention((query):?Linear(in_features=768,?out_features=768,?bias=True)(key):?Linear(in_features=768,?out_features=768,?bias=True)(value):?Linear(in_features=768,?out_features=768,?bias=True)(dropout):?Dropout(p=0.1,?inplace=False))(output):?BertSelfOutput((dense):?Linear(in_features=768,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(intermediate):?BertIntermediate((dense):?Linear(in_features=768,?out_features=3072,?bias=True))(output):?BertOutput((dense):?Linear(in_features=3072,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(7):?BertLayer((attention):?BertAttention((self):?BertSelfAttention((query):?Linear(in_features=768,?out_features=768,?bias=True)(key):?Linear(in_features=768,?out_features=768,?bias=True)(value):?Linear(in_features=768,?out_features=768,?bias=True)(dropout):?Dropout(p=0.1,?inplace=False))(output):?BertSelfOutput((dense):?Linear(in_features=768,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(intermediate):?BertIntermediate((dense):?Linear(in_features=768,?out_features=3072,?bias=True))(output):?BertOutput((dense):?Linear(in_features=3072,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(8):?BertLayer((attention):?BertAttention((self):?BertSelfAttention((query):?Linear(in_features=768,?out_features=768,?bias=True)(key):?Linear(in_features=768,?out_features=768,?bias=True)(value):?Linear(in_features=768,?out_features=768,?bias=True)(dropout):?Dropout(p=0.1,?inplace=False))(output):?BertSelfOutput((dense):?Linear(in_features=768,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(intermediate):?BertIntermediate((dense):?Linear(in_features=768,?out_features=3072,?bias=True))(output):?BertOutput((dense):?Linear(in_features=3072,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(9):?BertLayer((attention):?BertAttention((self):?BertSelfAttention((query):?Linear(in_features=768,?out_features=768,?bias=True)(key):?Linear(in_features=768,?out_features=768,?bias=True)(value):?Linear(in_features=768,?out_features=768,?bias=True)(dropout):?Dropout(p=0.1,?inplace=False))(output):?BertSelfOutput((dense):?Linear(in_features=768,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(intermediate):?BertIntermediate((dense):?Linear(in_features=768,?out_features=3072,?bias=True))(output):?BertOutput((dense):?Linear(in_features=3072,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(10):?BertLayer((attention):?BertAttention((self):?BertSelfAttention((query):?Linear(in_features=768,?out_features=768,?bias=True)(key):?Linear(in_features=768,?out_features=768,?bias=True)(value):?Linear(in_features=768,?out_features=768,?bias=True)(dropout):?Dropout(p=0.1,?inplace=False))(output):?BertSelfOutput((dense):?Linear(in_features=768,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(intermediate):?BertIntermediate((dense):?Linear(in_features=768,?out_features=3072,?bias=True))(output):?BertOutput((dense):?Linear(in_features=3072,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(11):?BertLayer((attention):?BertAttention((self):?BertSelfAttention((query):?Linear(in_features=768,?out_features=768,?bias=True)(key):?Linear(in_features=768,?out_features=768,?bias=True)(value):?Linear(in_features=768,?out_features=768,?bias=True)(dropout):?Dropout(p=0.1,?inplace=False))(output):?BertSelfOutput((dense):?Linear(in_features=768,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))(intermediate):?BertIntermediate((dense):?Linear(in_features=768,?out_features=3072,?bias=True))(output):?BertOutput((dense):?Linear(in_features=3072,?out_features=768,?bias=True)(LayerNorm):?LayerNorm((768,),?eps=1e-12,?elementwise_affine=True)(dropout):?Dropout(p=0.1,?inplace=False)))))(pooler):?BertPooler((dense):?Linear(in_features=768,?out_features=768,?bias=True)(activation):?Tanh()) )

模型結構參考BertModel源碼介紹部分。

5.1 Embeddings produced by pre-trained BertModel

text?=?"This?is?an?input?example"#?step?1:?tokenize,?including?add?special?tokens tokens_info?=?tokenizer.encode_plus(text,?return_tensors="pt")? for?key,?value?in?tokens_info.items():print("{}:\n\t{}".format(key,?value)) #?observe?the?enriched?token?sequences print(tokenizer.convert_ids_to_tokens(tokens_info['input_ids'].squeeze(0).numpy()))#?step?2:?BertModel?Transformer?Encoding outputs,?pooled?=?model(**tokens_info) print("Token?wise?output:?{},?Pooled?output:?{}".format(outputs.shape,?pooled.shape))''' step?1:?outputs: ----------------------------------------------------------- input_ids:tensor([[?101,?1188,?1110,?1126,?7758,?1859,??102]]) token_type_ids:tensor([[0,?0,?0,?0,?0,?0,?0]]) attention_mask:tensor([[1,?1,?1,?1,?1,?1,?1]])['[CLS]',?'This',?'is',?'an',?'input',?'example',?'[SEP]']step?2:?outputs: ------------------------------------------------------------ Token?wise?output:?torch.Size([1,?7,?768]),?Pooled?output:?torch.Size([1,?768]) '''

5.2 Predict the missing word in a sentence

from?transformers?import?BertForMaskedLMtext?=?"Nice?to?[MASK]?you"?#?target?token?using?[MASK]?to?mask#?step?1:?obtain?pretrained?Bert?Model?using?MLM?Loss maskedLM_model?=?BertForMaskedLM.from_pretrained(MODEL_NAME,?cache_dir='tmp/model') maskedLM_model.eval()?#?close?dropout#?step?2:?tokenize token_info?=?tokenizer.encode_plus(text,?return_tensors='pt') tokens?=?tokenizer.convert_ids_to_tokens(token_info['input_ids'].squeeze().numpy()) print(tokens)?#?['[CLS]',?'Nice',?'to',?'[MASK]',?'you',?'[SEP]']#?step?3:?forward?to?obtain?prediction?scores with?torch.no_grad():outputs?=?maskedLM_model(**token_info)predictions?=?outputs[0]?#?shape,?B?x?S?x?V,?[1,?6,?28996]#?step?4:?top-k?predicted?tokens masked_index?=?tokens.index('[MASK]')?#?3 k?=?10 probs,?indices?=?torch.topk(torch.softmax(predictions[0,?masked_index],?-1),?k)predicted_tokens?=?tokenizer.convert_ids_to_tokens(indices.tolist()) print(list(zip(predicted_tokens,?probs)))''' output:[('meet',?tensor(0.9712)),('see',?tensor(0.0267)),('meeting',?tensor(0.0010)),('have',?tensor(0.0003)),('met',?tensor(0.0002)),('know',?tensor(0.0001)),('join',?tensor(7.0005e-05)),('find',?tensor(5.8323e-05)),('Meet',?tensor(2.7171e-05)),('tell',?tensor(2.4689e-05))] '''

可以看出,meet的概率最大,且達到了0.97,非常顯著。

5.3 Extractive QA

展示sentence-pair level的下游任務。

from?transformers?import?BertTokenizer,?BertForQuestionAnswering import?torch#?step?1:?obtain?pretrained-model?in?SQUAD tokenizer?=?BertTokenizer.from_pretrained('bert-base-uncased',?cache_dir='tmp/token_qa') model?=?BertForQuestionAnswering.from_pretrained('bert-large-uncased-whole-word-masking-finetuned-squad',?cache_dir='tmp/model_qa')#?step?2:?tokenize,?sentence-pair,?question,?passage question,?text?=?"Who?was?Jim?Henson?",?"Jim?Henson?was?a?nice?puppet" encoding?=?tokenizer.encode_plus(question,?text,?return_tensors='pt') input_ids,?token_type_ids?=?encoding["input_ids"],?encoding["token_type_ids"] print(input_ids,?token_type_ids) #?observe?enriched?tokens all_tokens?=?tokenizer.convert_ids_to_tokens(input_ids.squeeze().numpy()) print(all_tokens)#?step?3:?obtain?start/end?position?scores,?B?x?S start_scores,?end_scores?=?model(input_ids,?token_type_ids=token_type_ids)?#?(B,?S) answer?=?'?'.join(all_tokens[torch.argmax(start_scores)?:?torch.argmax(end_scores)+1]) print(answer) assert?answer?==?"a?nice?puppet"''' output: step?2:input_ids:?tensor([[??101,??2040,??2001,??3958,?27227,??1029,???102,??3958,?27227,??2001,?1037,??3835,?13997,???102]])?token_type_ids:?tensor([[0,?0,?0,?0,?0,?0,?0,?1,?1,?1,?1,?1,?1,?1]])all_tokens:['[CLS]',?'who',?'was',?'jim',?'henson',?'?',?'[SEP]',?'jim',?'henson',?'was',?'a',?'nice',?'puppet',?'[SEP]']???step?3:answer:a?nice?puppet '''

可以看出,模型能準確預測出答案,「a nice puppet」。

6. Summary

之前一直沒有機會閱讀BERT源碼。這篇文章也算是對BERT源碼的一次粗淺的閱讀筆記。想要進一步學習的話,可以參考文章,進擊的 BERT:NLP 界的巨人之力與遷移學習。總之,基于huggingface提供的transfomers進行二次開發和fine-tune還是比較方便的。下一次會嘗試結合AllenNLP,在AllenNLP中使用transformers來解決NLP tasks。

7. References

Transformers: State-of-the-art Natural Language Processing

深入理解NLP Subword算法:BPE、WordPiece、ULM

huggingface transformers doc

huggingface transformers source code

進擊的 BERT:NLP 界的巨人之力與遷移學習

BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統計學習方法》的代碼復現專輯 AI基礎下載機器學習的數學基礎專輯 本站知識星球“黃博的機器學習圈子”(92416895) 本站qq群704220115。 加入微信群請掃碼: 與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的【NLP】Transformers 源码阅读和实践的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

久久亚洲私人国产精品va | 国产资源| 最近中文国产在线视频 | 成人av免费网站 | 久久视频精品在线 | 成人av动漫在线观看 | 国产流白浆高潮在线观看 | 国产一区私人高清影院 | 91在线视频 | 香蕉久久国产 | 国产美女精品视频免费观看 | 一级片免费观看视频 | 日韩欧美亚州 | av在线短片| 日韩精品视频在线观看免费 | 国产精品视频全国免费观看 | 天堂在线免费视频 | 人人搞人人爽 | 中文字幕av电影下载 | www.亚洲精品在线 | 91精品国产高清自在线观看 | 色综合久久精品 | 人人爽人人爽人人片av | 91视频这里只有精品 | 一区三区在线欧 | 亚洲日韩欧美视频 | 国产精品白浆 | 国产成人免费观看久久久 | 国产精品高潮久久av | 久久综合狠狠综合 | 国产一级黄色免费看 | 亚洲综合小说电影qvod | 国产免费作爱视频 | 亚洲黄色免费在线看 | 天天干夜夜夜 | 美女久久久久久久 | 最新av免费 | 蜜桃av久久久亚洲精品 | 久久久2o19精品 | 国产伦精品一区二区三区在线 | 日韩欧美一区二区三区免费观看 | 午夜精品视频一区二区三区在线看 | 久久久久二区 | 日本久久精品视频 | 国产专区精品 | 久久久综合 | 中文字幕中文字幕在线一区 | 精品视频9999| 97av精品| www.超碰 | 久久久久久久久久久久久国产精品 | 日韩黄色免费在线观看 | 一区二区三区四区影院 | 国产成人福利片 | 五月激情丁香图片 | 欧洲一区二区在线观看 | 国产在线不卡一区 | 精品久久久久久国产偷窥 | 国产成人黄色 | 亚洲精品99 | 人人干干人人 | 99精品免费视频 | 国产精品永久免费观看 | 日韩欧美在线高清 | 黄色日视频 | av在线精品 | 亚洲一区网| 麻豆久久 | 成人久久久久久久久久 | 国产伦精品一区二区三区在线 | 69夜色精品国产69乱 | 在线99视频 | 国产精品久久久久久久免费观看 | 91完整版 | 欧美天天干 | 99视频在线免费看 | 美女黄色网在线播放 | 亚洲在线看 | 国产九色91 | 欧美性直播 | 成人黄色小说在线观看 | 久久男人中文字幕资源站 | 在线观看岛国av | 日韩免费视频在线观看 | 日本婷婷色| 久久极品 | 91精品啪在线观看国产81旧版 | 三三级黄色片之日韩 | 久久福利影视 | 欧美二区三区91 | 成人精品视频久久久久 | 国产成人精品一区二区在线 | 国产精品久久久久久久久久东京 | 国产男女爽爽爽免费视频 | 亚洲专区 国产精品 | 欧美在线视频第一页 | 国产午夜一区二区 | 久久午夜精品视频 | 午夜视频二区 | 国产成人黄色av | 欧美一区二区三区免费看 | 日韩成人精品一区二区 | 久久少妇免费视频 | 亚洲欧美日本一区二区三区 | 午夜色场 | 一区二区欧美在线观看 | 久久久久久久久久久网站 | 亚洲欧洲xxxx | 婷婷色资源 | 国产一级精品视频 | 天天综合网 天天综合色 | 国产视频午夜 | 国产丝袜网站 | 日韩中文字幕一区 | 国产黄色精品在线 | av天天干| 91九色网站| 日韩高清 一区 | 国产精品一区二区久久 | 久草久热| 午夜国产一区二区三区四区 | 黄色av电影在线观看 | www亚洲视频 | 狠狠色伊人亚洲综合网站色 | 91.dizhi永久地址最新 | 国产成a人亚洲精v品在线观看 | 欧美另类老妇 | 人人插人人搞 | 久久国产免费视频 | 国产婷婷精品 | 97视频人人免费看 | 国产精品一区二区久久精品爱微奶 | www色| av一级在线 | 成人av免费播放 | 欧美激情精品久久久久久 | 天天爽天天碰狠狠添 | 8x成人在线| 亚洲精品字幕在线 | 国产精品久久久久久一区二区 | 久久久久国产成人免费精品免费 | 玖操 | 久日精品 | 天海冀一区二区三区 | 欧美国产在线看 | 亚洲国产精品一区二区久久,亚洲午夜 | 91桃色在线观看视频 | 成人免费视频网站在线观看 | 日本一区二区免费在线观看 | 国产a高清 | 精品天堂av| 久久欧美视频 | 日本中文字幕观看 | 天天色天天综合 | 亚洲精品国精品久久99热一 | 天天干天天摸天天操 | 国产涩涩在线观看 | 天天色天天操综合 | 黄色国产区 | 日日日日| 国产在线国偷精品产拍 | 久久av免费| 天天操天天干天天操天天干 | 亚洲狠狠婷婷综合久久久 | 婷婷www | 999成人| 右手影院亚洲欧美 | 免费观看国产精品视频 | 久久国产精品视频免费看 | 狠狠地日| 国产婷婷vvvv激情久 | 国产一区二区三区免费在线 | 国产亚洲视频系列 | 日韩视频中文字幕 | 综合色中文 | 手机在线日韩视频 | 成人午夜影院 | 亚洲天堂免费视频 | 国产日韩精品欧美 | 婷婷六月色 | 9草在线| 婷婷激情小说网 | 91亚洲精品久久久蜜桃 | 韩国av三级 | 国产精品国产三级国产不产一地 | 国产视频一区在线播放 | 中文字幕一区二区在线播放 | 久久艹人人 | 中文字幕在线播出 | 男女免费av | 婷婷深爱五月 | 色美女在线 | 久久精品老司机 | 久久久久亚洲最大xxxx | 国产探花 | 久久手机看片 | 国产精品婷婷午夜在线观看 | 久久久精品国产一区二区电影四季 | 500部大龄熟乱视频使用方法 | 国产亚洲午夜高清国产拍精品 | 国产一区二区午夜 | 久久久网页 | 婷婷综合在线 | 国产视频在线观看免费 | 亚洲精品91天天久久人人 | 伊人天堂久久 | 日日操天天爽 | 久久久999免费视频 日韩网站在线 | 欧美小视频在线观看 | 99久久er热在这里只有精品15 | 国产91对白在线播 | 国产精品专区一 | 久久字幕网 | 亚洲欧美在线综合 | 一区二区三区动漫 | 亚洲 欧美 精品 | 国产精品欧美久久 | 欧美欧美| 久久久亚洲精华液 | aaa毛片视频 | 欧美性生活免费看 | 一个色综合网站 | 婷婷激情网站 | 久久精品久久精品久久精品 | 国产一二三精品 | av成人免费在线 | 日韩欧美精品在线观看 | 中文字幕在线观看免费 | 一区二区三区 亚洲 | 亚洲少妇自拍 | 色视频网站免费观看 | 米奇狠狠狠888 | 国产免费一区二区三区网站免费 | 九九视频在线播放 | 欧美性生活免费看 | 成人精品在线 | 九九视频精品免费 | 久久人人爽人人爽人人 | 国产精品一区二区av | 精品嫩模福利一区二区蜜臀 | 精品在线播放 | 久久免费福利视频 | 又黄又爽又色无遮挡免费 | 91久久国产露脸精品国产闺蜜 | 国产精品色 | 日韩三级久久 | 日韩伦理片hd | 五月婷婷六月丁香 | 中文字幕中文中文字幕 | 综合网伊人 | 精品中文字幕在线观看 | 亚洲精品视频在线免费 | 亚洲精品久久久久中文字幕m男 | 欧美精品久久人人躁人人爽 | 久久中文精品视频 | 极品嫩模被强到高潮呻吟91 | 中文在线中文a | 精品一区久久 | 成人午夜网 | 日本精品午夜 | 69av视频在线 | 日日插日日干 | 欧美九九九 | 九色在线 | 天天草天天干 | 狠狠干网址 | 国产成人在线免费观看 | 欧美午夜精品久久久久久浪潮 | 日韩在线首页 | 日韩精品一区二区三区在线播放 | 99热官网 | 色激情在线 | 在线国产福利 | 久久精品电影网 | 国产日产精品一区二区三区四区的观看方式 | 91视频国产高清 | 亚洲一级电影 | 亚洲精品视频网 | 黄色片免费电影 | 国产一级片毛片 | 伊人黄色网 | 在线免费成人 | 国产护士在线 | 欧洲亚洲国产视频 | 午夜精品一区二区三区在线观看 | 日韩成人在线一区二区 | 国产精品日韩久久久久 | 福利网址在线观看 | 91久久黄色 | 一区二区欧美在线观看 | 免费视频你懂的 | 国产精品123 | 久久久免费看 | 日韩在线视频网址 | www.国产毛片 | 91麻豆看国产在线紧急地址 | 亚洲丝袜一区 | 国产一区在线免费 | 日韩在线观看一区 | 五月婷婷操| 日韩视频在线观看视频 | 成人午夜电影在线播放 | 一区二区三区免费在线播放 | 久久九九国产精品 | 亚洲视频电影在线 | 国产精品 中文字幕 亚洲 欧美 | 婷婷 中文字幕 | 久久99精品国产99久久 | 婷婷激情小说网 | 久久国产免费 | 欧洲亚洲激情 | 99精品免费久久久久久久久日本 | 国产亚洲精品福利 | 99久久婷婷国产一区二区三区 | 日韩高清在线一区二区 | 成人免费视频a | 久久视频6| 国产一区二区在线观看免费 | av电影免费在线看 | 2021国产精品 | 国产在线精品一区 | 久草资源在线 | 亚洲国产高清在线观看视频 | 亚洲天堂激情 | 操操操影院 | 欧美一区二区三区激情视频 | 欧美综合色在线图区 | 日韩在线观看高清 | 国产一区二区中文字幕 | 奇米影视8888在线观看大全免费 | 久久dvd | 亚洲国产日韩欧美在线 | 国产精品一区二区无线 | 午夜视频在线观看一区二区三区 | 婷婷激情综合网 | 一区二区精品视频 | 在线观看蜜桃视频 | 国产99久久精品一区二区永久免费 | 亚洲黄色小说网 | 亚洲九九九在线观看 | 色www永久免费 | 18女毛片| 国内丰满少妇猛烈精品播放 | 久久国产综合视频 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 亚洲成人第一区 | 麻豆超碰| 日韩大陆欧美高清视频区 | 精品成人免费 | 91亚洲精品久久久中文字幕 | 91中文字幕一区 | 国产综合片 | 91精品办公室少妇高潮对白 | 91av手机在线观看 | 激情欧美一区二区三区免费看 | 操久久网| 久久免费视频这里只有精品 | 国产精品高潮呻吟久久久久 | 亚洲高清91| 五月天丁香视频 | 久久手机精品视频 | 国模一区二区三区四区 | 99精品视频在线播放免费 | 天天操人人要 | 亚洲精品中文字幕在线观看 | 三级黄色理论片 | 国产原创av在线 | 91中文在线| 国产三级视频在线 | 最近中文字幕完整高清 | 亚洲蜜桃在线 | 亚洲2019精品 | 91传媒视频在线观看 | 国产又粗又硬又长又爽的视频 | 69久久久久久久 | 国产精品对白一区二区三区 | 成 人 黄 色 视频 免费观看 | 亚洲国产高清视频 | 国产精品白丝jk白祙 | 亚洲欧美成人综合 | 国产高清一 | 国产亚洲字幕 | 最新国产福利 | 亚洲日本精品视频 | 91精品综合在线观看 | 亚洲国产片色 | 中文字幕av在线不卡 | 99视频国产精品免费观看 | 国内精品二区 | 五月婷婷视频在线 | 久久婷婷精品视频 | 中文字幕在线成人 | 亚洲综合在线一区二区三区 | 国产精品中文字幕在线 | 三级黄色大片在线观看 | 国产成在线观看免费视频 | 中国精品少妇 | 久久69av| 亚洲欧美国产精品18p | av天天草| 久久精国产 | 91av视屏| 国产又粗又硬又长又爽的视频 | 丝袜制服天堂 | 91传媒在线播放 | 日批视频国产 | 97国产一区 | 在线黄色毛片 | 97超碰成人 | 久久久久久久免费 | 婷婷综合视频 | 在线观看久久 | 欧美一区二区在线免费看 | 欧美成人在线网站 | 国产成人99久久亚洲综合精品 | 国产一区二区视频在线播放 | 久草视频国产 | 国产大片黄色 | 天天色成人 | 美女禁18| 亚洲一区二区三区在线看 | 国产精品久久久久久久久大全 | 国产精品久久中文字幕 | 激情电影在线观看 | 国产传媒一区在线 | 久久久久国产a免费观看rela | 天堂av在线网址 | 91视频高清免费 | 久久一区二 | 国产三级香港三韩国三级 | 在线免费视频一区 | 国产激情久久久 | 精品自拍sae8—视频 | 91亚洲在线观看 | 狠狠久久综合 | 欧美日韩性生活 | 久久婷婷国产 | 黄色www免费 | 狠狠干在线播放 | 午夜精品一区二区三区在线 | 久久夜色精品国产欧美乱 | 国产一区欧美日韩 | 女人魂免费观看 | 手机av永久免费 | 国产精品久久久久久久久搜平片 | 97精品一区 | 五月亚洲婷婷 | 欧美成人69av| 日日摸日日爽 | 久久久久免费精品国产 | 国产精品成人免费一区久久羞羞 | 中文字幕av全部资源www中文字幕在线观看 | 91污视频在线观看 | 久草剧场| 奇米影视8888在线观看大全免费 | 国内揄拍国产精品 | 日韩欧美在线影院 | 国产99在线 | 五月激情电影 | 黄色aaa毛片 | 91网免费观看 | 国产一级一级国产 | 国产激情免费 | 国产在线观看免费 | 国产精品成人av电影 | 97中文字幕 | 国产午夜视频在线观看 | 97超碰国产精品女人人人爽 | 狠狠色噜噜狠狠狠 | 亚洲免费精品视频 | 91视频免费网站 | 免费黄色av片 | 成人午夜剧场在线观看 | 色综合久久88色综合天天 | 国产在线色站 | 成人午夜性影院 | 最新日本中文字幕 | 欧美日韩另类视频 | 欧美激情一区不卡 | 亚洲在线看 | 超级碰碰碰视频 | 天天操月月操 | 麻豆视频成人 | 久久久久欠精品国产毛片国产毛生 | 久久精品一区二区 | 国产馆在线播放 | 免费看一级特黄a大片 | 草草草影院 | 国产中文字幕第一页 | 免费观看v片在线观看 | 久久婷综合 | www久草 | 欧美少妇影院 | 一本到视频在线观看 | 精品久久久久久久久久 | 亚洲电影第一页av | 国产尤物视频在线 | av高清网站在线观看 | 久久99精品久久久久久秒播蜜臀 | 欧美大片mv免费 | 久久久在线观看 | 999国产 | 欧美成年网站 | 一区二三国产 | 啪嗒啪嗒免费观看完整版 | 国产免费又粗又猛又爽 | 毛片激情永久免费 | 福利一区二区三区四区 | 亚洲欧美激情插 | 国产视频精品网 | 久久99电影| 在线观看的av网站 | 国产视频99 | 欧美一级片在线 | 国产日韩精品一区二区三区在线 | 99久久精品久久亚洲精品 | 午夜精品区 | 成年人黄色免费看 | 久草在线久 | 国产黄色片网站 | 一级a性色生活片久久毛片波多野 | 国产一区在线视频播放 | 精品电影一区二区 | 日韩在线视频网 | 美女视频黄频 | 欧美日韩性生活 | 欧美另类一二三四区 | 久久99在线观看 | 在线免费观看国产视频 | 一区二区三区免费网站 | 国产女人40精品一区毛片视频 | 国产福利不卡视频 | 在线黄色毛片 | 一区二区视频在线播放 | 国产精品久久久久一区二区三区 | 欧美有色 | 中文字幕日韩在线播放 | 青春草视频在线播放 | 天天色天天干天天 | 久草视频在线免费播放 | 99视频国产在线 | 国产黄在线| 国产一区二区三区免费观看视频 | 午夜久久久久久久久久影院 | 久久国产精品偷 | 在线观看视频国产 | 最近在线中文字幕 | 精选久久 | 国产黄色精品在线 | av久久在线 | 五月婷婷色丁香 | 久久夜色精品国产欧美一区麻豆 | 国产18精品乱码免费看 | 手机av片| 免费成人结看片 | 伊人婷婷综合 | av在线播放亚洲 | 亚洲综合一区二区精品导航 | 欧美日韩伦理在线 | 国产在线精品播放 | 日韩黄色免费 | www.色国产 | 日日夜夜骑 | 久久久久成人精品免费播放动漫 | 久久国产精品免费观看 | av中文字幕第一页 | 亚洲五月综合 | 国产 视频 久久 | 亚洲一区二区三区在线看 | 日本午夜免费福利视频 | 欧美另类视频 | 99av国产精品欲麻豆 | 日韩视频一区二区在线 | 国产手机视频精品 | 精品一二三四视频 | 久久免费公开视频 | 一区二区三区在线播放 | 亚洲欧美精品在线 | 亚洲天堂网在线播放 | 日韩精品欧美专区 | 91污污| 精品久久久久久久久中文字幕 | 在线久热 | 天天色天天上天天操 | 中文日韩在线 | 久久中文字幕视频 | 日韩电影中文,亚洲精品乱码 | 精品uu| 91高清免费看| 视频在线一区二区三区 | 二区视频在线观看 | 激情文学丁香 | 亚洲欧美日韩在线看 | 国产手机视频在线观看 | 五月婷婷一级片 | 玖玖玖国产精品 | 久久麻豆精品 | 国产黄色免费在线观看 | 日韩精品在线播放 | 国产在线一线 | 国产做aⅴ在线视频播放 | 日韩特级片| 免费视频 三区 | 欧洲亚洲国产视频 | 国产午夜在线观看 | 久久论理 | www.狠狠操.com | 五月激情天 | 丁香激情五月婷婷 | 久久国产精品影片 | 射射射综合网 | 欧美日韩高清国产 | 狠狠干在线| 免费在线观看成人小视频 | 91香蕉视频好色先生 | 91av片 | 亚洲综合色丁香婷婷六月图片 | 在线免费高清一区二区三区 | 在线看的毛片 | 天天操天天爱天天爽 | 成人一级在线 | a在线v | 亚洲精欧美一区二区精品 | 九九九热视频 | 日韩欧美综合 | 久久精品免费看 | 色偷偷88888欧美精品久久 | 99久久日韩精品视频免费在线观看 | 色婷婷综合久久久中文字幕 | 久草视频播放 | 国产精品亚洲成人 | 综合网伊人 | av看片在线观看 | 亚洲激情在线观看 | 日韩动态视频 | 91网页版在线观看 | 91精品久久久久久 | 国产小视频免费观看 | 99人成在线观看视频 | 国产精品一区二区在线看 | 亚洲人人爱 | www.神马久久| 国产精品综合久久久久久 | 国产美女精品人人做人人爽 | 婷婷综合av | 在线中文字幕播放 | 日韩精品免费一区二区三区 | 99在线观看视频网站 | 九九亚洲精品 | 97成人精品| 久久久av电影 | 久久国产精品小视频 | 激情综合色综合久久综合 | 亚州精品一二三区 | 日产乱码一二三区别在线 | 性色视频在线 | 国产高清在线免费观看 | 国产免费午夜 | 中文字幕在线中文 | 五月婷婷操 | 免费看一级| 成人影音av| 久久香蕉国产 | 久久国产精品影片 | 精品免费在线视频 | h网站免费在线观看 | 国产精品久久久久久久久久久杏吧 | 中文在线免费观看 | 深夜免费福利网站 | 午夜视频一区二区三区 | 亚州免费视频 | 欧美日韩精品在线观看视频 | 九九视频一区 | 粉嫩aⅴ一区二区三区 | 日日躁夜夜躁aaaaxxxx | 国产一二三区av | 美女黄频在线观看 | 中午字幕在线观看 | 成人视屏免费看 | 日本精品久久久久中文字幕 | 波多野结衣视频一区 | 日韩久久视频 | 国产91全国探花系列在线播放 | av电影在线观看完整版一区二区 | 手机在线欧美 | 91亚洲欧美 | 伊人久久五月天 | 狠狠久久综合 | 欧美日韩国产伦理 | 久久久精品99| 91在线免费公开视频 | 韩日电影在线观看 | 亚洲精品tv久久久久久久久久 | 一区二区视频电影在线观看 | 中午字幕在线观看 | 日韩精品一卡 | 中文字幕一区二区三区在线视频 | 中日韩免费视频 | 香蕉视频网址 | 999精品| 国产成人在线播放 | 中文字幕av免费 | www.97视频 | 久久久久国产精品www | 久久在现视频 | 亚洲成人精品久久 | 精品亚洲男同gayvideo网站 | 一区二区三区精品在线 | 国产一区欧美在线 | 九九免费在线观看视频 | 亚洲视频综合 | 在线精品亚洲一区二区 | 国产精品免费观看久久 | 亚洲成人黄色在线观看 | 国产99久久九九精品免费 | 亚洲女同ⅹxx女同tv | 国产成人久久精品一区二区三区 | 国产美女视频 | 天天操天天添天天吹 | 中文字幕在线中文 | 亚洲午夜久久久综合37日本 | 国产免费黄视频在线观看 | 青青草国产精品 | 国产精品美女网站 | 精品日本视频 | 777奇米四色 | 亚洲人成人99网站 | 视频99爱 | 亚洲欧美激情精品一区二区 | 成人免费视频观看 | 日日夜夜添 | 一区二区三区不卡在线 | 99久久免费看 | 伊人五月天.com | 国产伦理久久精品久久久久_ | 欧美一级片免费播放 | 日韩精品 在线视频 | 日韩区欠美精品av视频 | 精品一区二区三区久久久 | 久久精品人人做人人综合老师 | 午夜在线观看一区 | 免费日韩视 | 碰超在线97人人 | 少妇自拍av | 91色一区二区三区 | 成人小视频在线免费观看 | 国产日产精品一区二区三区四区 | 黄色avwww | 精品一区二区三区香蕉蜜桃 | 6080yy午夜一二三区久久 | 免费av网址在线观看 | 在线播放 一区 | 色偷偷88欧美精品久久久 | 久久免费电影网 | 伊人va | 久久久久久蜜桃一区二区 | 色偷偷av男人天堂 | 日韩在线精品视频 | 色福利网站 | 中文字幕国产视频 | 一区免费视频 | 国产一级在线 | 久久黄色精品视频 | 97中文字幕| 中文字幕第一 | 五月婷婷毛片 | 97人人艹 | 久久久官网 | 伊人中文网 | 九九久| 99婷婷狠狠成为人免费视频 | 国产精品国产三级国产aⅴ无密码 | 成人综合日日夜夜 | 黄色大全在线观看 | 午夜精品99久久免费 | 西西44人体做爰大胆视频 | 免费久久久久久久 | 国产综合久久 | 久久国产精品影片 | 一本到视频在线观看 | 成人黄色在线视频 | 日本三级不卡视频 | 国产在线观看一 | 欧美午夜理伦三级在线观看 | 色网址99| 欧美亚洲精品一区 | 在线观看国产成人av片 | 久久国产精品久久久久 | 色综合久久99 | 91麻豆精品国产91久久久无限制版 | 欧美日韩高清在线一区 | 99精品视频在线免费观看 | 国产香蕉97碰碰久久人人 | 国产91精品在线观看 | 亚洲国产精久久久久久久 | 国产黄色片免费 | 免费在线播放av电影 | 婷婷色亚洲 | 韩国精品一区二区三区六区色诱 | 国产精品一区二区三区四 | 97在线超碰 | 欧美精品久久久久a | 国产一区播放 | 久久免费看a级毛毛片 | 在线免费色视频 | 欧美日本一二三 | 免费看国产精品 | 97超碰在线久草超碰在线观看 | 最近日韩免费视频 | 国产视频黄 | 日韩高清网站 | 在线播放 亚洲 | 国产精品久久久久久久久久久久午夜 | 999男人的天堂 | 黄色特级片 | 国产精品 欧美 日韩 | 中文字幕在线第一页 | 国产精品日韩在线播放 | 精品自拍sae8—视频 | 国产亚洲精品久久19p | 久久久国产网站 | 色91在线视频 | 日韩成人精品 | 日日狠狠 | 亚洲精品一区二区久 | 国产午夜三级一区二区三桃花影视 | 亚洲国产日韩精品 | 中文字幕制服丝袜av久久 | 国产精品美女久久久久久久久 | 免费视频黄| 日本韩国在线不卡 | 国产亚洲久一区二区 | 午夜婷婷网| 在线免费观看黄网站 | 国产精品久久久一区二区 | 日韩欧美高清在线观看 | 欧美激情视频一区二区三区免费 | 手机看片中文字幕 | 亚洲成人在线免费 | 久久国产一区二区 | 日韩一区二区免费在线观看 | 一区二区三区在线观看免费视频 | av中文在线影视 | 日韩精品免费一区 | 精品少妇一区二区三区在线 | 在线观看国产一区 | 国产午夜精品一区二区三区 | 婷婷丁香国产 | 精品99在线观看 | 国产精品高清在线 | 成人网色 | 人人爽久久久噜噜噜电影 | 免费观看国产成人 | 欧美日韩一区二区在线 | 国产午夜在线观看 | 国产精品99久久久久 | av免费高清观看 | 日韩成人中文字幕 | 欧美精品二区 | 人人澡人人干 | 91久久久久久久 | 午夜三级理论 | 欧美日韩视频精品 | 97精品视频在线播放 | 欧美激情视频免费看 | 天天搞天天干天天色 | 国产精品不卡一区 | 精品国产乱码一区二区三区在线 | 国产精品对白一区二区三区 | 久久国产热 | 国内精品视频一区二区三区八戒 | 亚洲精品成人 | 国产人成精品一区二区三 | 天天曰天天爽 | 在线观看亚洲精品 | 欧美色婷 | 黄色软件视频大全免费下载 | 97在线公开视频 | 久久久久综合网 | 天天色中文 | 国产一区二区在线免费视频 | 日韩在线视频网 | 正在播放一区二区 | 日韩精品久久久久 | 国产一级黄| 久草网在线观看 | 91在线资源 | 91完整视频 | 婷婷在线免费观看 | 成人91视频 | 国产精品1024 | 色综合久久久久综合 | 国产一区 在线播放 | 国产精品白虎 | 片黄色毛片黄色毛片 | 成人a大片 | 婷婷激情久久 | 免费亚洲视频在线观看 | 日韩在线免费视频 | 一区免费观看 | 欧美一区免费在线观看 | 97国产一区| 国产精品久久久久久久久久ktv | 日日碰狠狠躁久久躁综合网 | 在线成人免费电影 | 国产精品免费久久久久久 | 日韩视频一区二区三区在线播放免费观看 | 久久系列 | 久久精品第一页 | 久久精品网站免费观看 | 久久9999久久免费精品国产 | 国产黄在线播放 | 日日操操操 | 不卡av免费在线观看 | 久久av影院 | 日韩免费在线视频观看 | 久久不射影院 | 又黄又爽的免费高潮视频 | 99免费在线| 天堂网av 在线 | 欧美日韩免费在线观看视频 | 欧美日韩中文国产一区发布 | 国产a视频免费观看 | 日本黄色免费看 | 91人人在线 | 五月天av在线 | 国产视频精品久久 | 97精品一区| 99热国内精品 | 91麻豆精品 | 日韩精品一二三 | 99久久精品免费看国产一区二区三区 | 日日操天天射 | 久久国产高清 | 国产视频69 | 国产涩涩在线观看 | 成人av免费在线 | 日本一区二区三区免费观看 | 九九热在线精品视频 | 天天操天天舔天天爽 | 97自拍超碰| 成人中文字幕+乱码+中文字幕 | 香蕉在线观看视频 | 91在线一区二区 | 99热播精品 | 午夜精品一区二区三区可下载 | 免费黄色在线网站 | 玖玖在线精品 | 精品亚洲一区二区 | 日本精品小视频 | 国产一级视频在线 | 91精品国产欧美一区二区成人 | 中文字幕免费看 | 91自拍成人 | 国产精品久久久久久久久大全 | 久久国产精品色av免费看 | 精品国产伦一区二区三区 | av在线专区 | 国产精品嫩草在线 | 中文字幕二区三区 | 久久久久久久久久久免费av | 在线观看免费观看在线91 | 最新成人在线 | 成人免费观看视频网站 | 99热在线免费观看 | 免费高清看电视网站 | 久久不卡av | 色视频在线观看 | 久草视频免费在线播放 | 91视频在线播放视频 | 手机色站 | 亚洲精品中文在线资源 | 久草在线一免费新视频 | 精品国产一区二区三区av性色 | 视频一区二区三区视频 | 国产成人99久久亚洲综合精品 | 日韩精品久久久久久久电影99爱 | 观看免费av | 一区 二区 精品 | 欧美日韩3p | 日韩精品一区电影 | 午夜国产福利在线观看 | 六月婷色 | 久草在线视频在线 | 亚洲专区在线视频 | 91精品久久久久久久久久入口 | 欧美日韩视频在线观看一区二区 | 天天操天天草 | 成人午夜影院在线观看 | 亚洲精品玖玖玖av在线看 | 国产手机在线播放 | 日韩激情视频在线观看 | 久久综合成人网 | 精品九九九九 | 亚洲黄a | 国产 成人 久久 | 中文字幕色站 | 在线激情小视频 |