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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人工智能 > pytorch >内容正文

pytorch

[深度学习] 自然语言处理---Transformer实现(二)

發(fā)布時(shí)間:2023/12/15 pytorch 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [深度学习] 自然语言处理---Transformer实现(二) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

Encoder-Decoder框架

一 整體架構(gòu)

動(dòng)態(tài)流程圖

二 Encoder

2.1 Encoder Layer和殘差網(wǎng)絡(luò)

Residual Connection

2.2 Attention

Self Attention

Multi-head Attention

2.3 Add & Norm

LayerNormalization 層歸一化

2.4 前饋網(wǎng)絡(luò) Feed Forward Neural Network

2.5 詞向量

Positional Encoding 位置編碼

三 Decoder

3.1 Masked Mutil-head Attention

3.2 線性層和softmax

3.3 完整模型代碼

四、相關(guān)問(wèn)題

4.1 Transformer為什么需要進(jìn)行Multi-head Attention?

4.2 Transformer相比于RNN/LSTM,有什么優(yōu)勢(shì)?為什么?

4.3 為什么說(shuō)Transformer可以代替seq2seq?

4.4 Transformer如何并行化的?

4.5 訓(xùn)練-模型的參數(shù)在哪里?

參考文獻(xiàn)


看完本文,你大概能夠:

  • 掌握Encoder-Decoder框架
  • 掌握殘差網(wǎng)絡(luò)
  • 掌握BatchNormalization(批歸一化)和LayerNormalization(層歸一化)
  • 掌握Position Embedding(位置編碼)

Notes: 本文代碼?參考哈弗大學(xué)的The Annotated Transformer

引入必要的庫(kù)

import numpy as np import torch import torch.nn as nn import torch.nn.functional as F import math, copy, time from torch.autograd import Variable import matplotlib.pyplot as plt import seaborn# Seaborn作為一個(gè)帶著定制主題和高級(jí)界面控制的Matplotlib擴(kuò)展包,能讓繪圖變得更輕松. seaborn.set_context(context="talk")

模型結(jié)構(gòu)--Encoder-Decoder框架

Encoder-Decoder是為seq2seq(序列到序列)量身打造的一個(gè)深度學(xué)習(xí)框架,在機(jī)器翻譯、機(jī)器問(wèn)答等領(lǐng)域有著廣泛的應(yīng)用。這是一個(gè)抽象的框架,由兩個(gè)組件:Encoder(編碼器)和Decoder(解碼器)組成。

  • encoder將使用符號(hào)表示的輸入inputs序列,映射到一個(gè)連續(xù)表示的序列Z。
  • decoder一次一個(gè)元素地生成符號(hào)輸出序列Y。
    在每一步模型均為自動(dòng)回歸(auto-regressive),即在生成下一個(gè)符號(hào)時(shí)將先前生成的符號(hào)作為附加輸入。
class EncoderDecoder(nn.Module):# A standard Encoder-Decoder architecture. Base for this and many other models.def __init__(self, encoder, decoder, src_embed, tgt_embed, generator):super(EncoderDecoder, self).__init__()self.encoder = encoderself.decoder = decoderself.src_embed = src_embedself.tgt_embed = tgt_embedself.generator = generatordef forward(self, src, tgt, src_mask, tgt_mask):"Take in and process masked src and target sequences."return self.decode(self.encode(src, src_mask), src_mask,tgt, tgt_mask)def encode(self, src, src_mask):return self.encoder(self.src_embed(src), src_mask)def decode(self, memory, src_mask, tgt, tgt_mask):return self.decoder(self.tgt_embed(tgt), memory, src_mask, tgt_mask)

上述代碼呈現(xiàn)了一個(gè)標(biāo)準(zhǔn)的Encoder-Decoder框架。在實(shí)際應(yīng)用中,編碼器和解碼器可以有多種組合,比如(RNN, RNN)、(CNN,RNN)等等,這就是傳統(tǒng)的seq2seq框架。后來(lái)引入了attention機(jī)制,上述框架也被稱(chēng)為”分心模型“。為什么說(shuō)他”分心“呢?因?yàn)閷?duì)于解碼器來(lái)說(shuō),他在生成每一個(gè)單詞的時(shí)候,中間向量的每一個(gè)元素對(duì)當(dāng)前生成詞的貢獻(xiàn)都是一樣的。Attention的思想則是對(duì)于當(dāng)前生成的單詞,中間向量z的每個(gè)元素對(duì)其貢獻(xiàn)的重要程度不同,跟其強(qiáng)相關(guān)的賦予更大的權(quán)重,無(wú)關(guān)的則給一個(gè)很小的權(quán)重。

class Generator(nn.Module):'''定義標(biāo)準(zhǔn)的線性+softmax生成步驟這是在8. Embeddings和Softmax中'''def __init__(self, d_model, vocab):super(Generator, self).__init__()self.proj = nn.Linear(d_model, vocab)def forward(self, x):return F.log_softmax(self.proj(x), dim=1)

再通俗一點(diǎn)的圖,可能你在其他博客里看到的圖,如下所示,Transformer由六個(gè)編碼器和六個(gè)解碼器組成。

??

動(dòng)態(tài)流程圖

舉個(gè)例子介紹下如何使用這個(gè)Transformer Seq2Seq做翻譯

  • 首先,Transformer對(duì)原語(yǔ)言的句子進(jìn)行編碼,得到memory。
  • 第一次解碼時(shí)輸入只有一個(gè)<SOS>標(biāo)志,表示句子的開(kāi)始。
  • 解碼器通過(guò)這個(gè)唯一的輸入得到的唯一的輸出,用于預(yù)測(cè)句子的第一個(gè)詞。

編碼器通過(guò)處理輸入序列開(kāi)啟工作。頂端編碼器的輸出之后會(huì)變轉(zhuǎn)化為一個(gè)包含向量K(鍵向量)和V(值向量)的注意力向量集 ,這是并行化操作。這些向量將被每個(gè)解碼器用于自身的“編碼-解碼注意力層”,而這些層可以幫助解碼器關(guān)注輸入序列哪些位置合適:

在完成編碼階段后,則開(kāi)始解碼階段。解碼階段的每個(gè)步驟都會(huì)輸出一個(gè)輸出序列(在這個(gè)例子里,是英語(yǔ)翻譯的句子)的元素。

接下來(lái)的步驟重復(fù)了這個(gè)過(guò)程,直到到達(dá)一個(gè)特殊的終止符號(hào),它表示transformer的解碼器已經(jīng)完成了它的輸出。每個(gè)步驟的輸出在下一個(gè)時(shí)間步被提供給底端解碼器,并且就像編碼器之前做的那樣,這些解碼器會(huì)輸出它們的解碼結(jié)果 。

第二次解碼,將第一次的輸出Append到輸入中,輸入就變成了<SOS>和句子的第一個(gè)詞(ground truth或上一步的預(yù)測(cè)),解碼生成的第二個(gè)輸出用于預(yù)測(cè)句子的第二個(gè)詞。以此類(lèi)推(過(guò)程與Seq2Seq非常類(lèi)似)

二 Encoder

Encoder由N=6個(gè)相同的layer組成,layer指的就是上圖左側(cè)的單元,最左邊有個(gè)“Nx”,這里是x6個(gè)。

每個(gè)Layer由兩個(gè)sub-layer組成:

  • 第一部分是一個(gè)multi-head self-attention mechanism
  • 第二部分是一個(gè)position-wise feed-forward network,是一個(gè)全連接層

其中每個(gè)sub-layer都加了residual connection和normalisation,因此可以將sub-layer的輸出表示為:

def clones(module, N):"Produce N identical layers."return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])class LayerNorm(nn.Module):def __init__(self, features, eps=1e-6):super(LayerNorm, self).__init__()self.a_2 = nn.Parameter(torch.ones(features))self.b_2 = nn.Parameter(torch.zeros(features))self.eps = epsdef forward(self, x):mean = x.mean(-1, keepdim=True)std = x.std(-1, keepdim=True)return self.a_2 * (x - mean) / (std + self.eps) + self.b_2class Encoder(nn.Module):"Core encoder is a stack of N layers"def __init__(self, layer, N):super(Encoder, self).__init__()self.layers = clones(layer, N)self.norm = LayerNorm(layer.size)def forward(self, x, mask):"Pass the input (and mask) through each layer in turn."for layer in self.layers:x = layer(x, mask)return self.norm(x)

以上便是Encoder的核心實(shí)現(xiàn)。它由N個(gè)encoderLayer組成。輸入一次通過(guò)每個(gè)encoderLayer,然后經(jīng)過(guò)一個(gè)歸一化層。下面來(lái)看下EncoderLayer和LayerNorm是什么樣子。

我們?cè)诿績(jī)蓚€(gè)子層之間都使用了殘差連接(Residual Connection) 和歸一化

2.1 Encoder Layer和殘差網(wǎng)絡(luò)

class SublayerConnection(nn.Module):"""A residual connection followed by a layer norm.Note for code simplicity the norm is first as opposed to last."""def __init__(self, size, dropout):super(SublayerConnection, self).__init__()self.norm = LayerNorm(size)self.dropout = nn.Dropout(dropout)def forward(self, x, sublayer):"Apply residual connection to any sublayer with the same size."return x + self.dropout(sublayer(self.norm(x)))

每層都有兩個(gè)子層組成。第一個(gè)子層實(shí)現(xiàn)了“多頭”的 Self-attention,第二個(gè)子層則是一個(gè)簡(jiǎn)單的Position-wise的全連接前饋網(wǎng)絡(luò)。

class EncoderLayer(nn.Module):"Encoder is made up of self-attn and feed forward (defined below)"def __init__(self, size, self_attn, feed_forward, dropout):super(EncoderLayer, self).__init__()self.self_attn = self_attnself.feed_forward = feed_forwardself.sublayer = clones(SublayerConnection(size, dropout), 2)self.size = sizedef forward(self, x, mask):"Follow Figure 1 (left) for connections."x = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, mask))return self.sublayer[1](x, self.feed_forward)

這里的代碼初看上去有點(diǎn)繞,不過(guò)沒(méi)關(guān)系。我們先看什么是殘差網(wǎng)絡(luò)(即代碼中的SublayerConnection)。其實(shí)非常簡(jiǎn)單,就是在正常的前向傳播基礎(chǔ)上開(kāi)一個(gè)綠色通道,這個(gè)通道里x可以無(wú)損通過(guò)。這樣做的好處不言而喻,避免了梯度消失(求導(dǎo)時(shí)多了一個(gè)常數(shù)項(xiàng))。最終的輸出結(jié)果就等于綠色通道里的x加上sublayer層的前向傳播結(jié)果。注意,這里輸入進(jìn)來(lái)的時(shí)候做了個(gè)norm歸一化,關(guān)于norm我們后面再說(shuō)。

Residual Connection

殘差連接其實(shí)很簡(jiǎn)單!給你看一張示意圖你就明白了:

假設(shè)網(wǎng)絡(luò)中某個(gè)層對(duì)輸入x作用后的輸出是F(x),那么增加residual connection之后,就變成了:F(x) + x,這個(gè)+x操作就是一個(gè)shortcut。那么殘差結(jié)構(gòu)有什么好處呢?顯而易見(jiàn):因?yàn)樵黾恿艘豁?xiàng)x,那么該層網(wǎng)絡(luò)對(duì)x求偏導(dǎo)的時(shí)候,多了一個(gè)常數(shù)項(xiàng)1!所以在反向傳播過(guò)程中,梯度連乘,也不會(huì)造成梯度消失

所以,代碼實(shí)現(xiàn)residual connection很非常簡(jiǎn)單:

def residual(sublayer_fn, x):return sublayer_fn(x)+x

文章開(kāi)始的transformer架構(gòu)圖中的Add & Norm中的Add也就是指的這個(gè)shortcut

理解了殘差網(wǎng)絡(luò),EncoderLayer的代碼就很好看懂了。sublayer有兩個(gè),一個(gè)是多頭self-attention層,另一個(gè)是前饋網(wǎng)絡(luò)(feed_forward)。輸入x先進(jìn)入多頭self-attention,用一個(gè)殘差網(wǎng)絡(luò)加成,接著通過(guò)前饋網(wǎng)絡(luò), 再用一個(gè)殘差網(wǎng)絡(luò)加成。

讓我們從輸入x開(kāi)始,再?gòu)念^理一遍這個(gè)過(guò)程:

  • 輸入x
  • x做一個(gè)層歸一化: x1 = norm(x)
  • 進(jìn)入多頭self-attention: x2 = self_attn(x1)
  • 殘差加成:x3 = x + x2
  • 再做個(gè)層歸一化:x4 = norm(x3)
  • 經(jīng)過(guò)前饋網(wǎng)絡(luò): x5 = feed_forward(x4)
  • 殘差加成: x6 = x3 + x5
  • 輸出x6

以上就是一個(gè)Encoder組件所做的全部工作了。里面有兩點(diǎn)暫未說(shuō)明,一個(gè)是多頭attention, 另一個(gè)是層歸一化。

2.2??Self Attention

這里使用的是點(diǎn)乘attention,而不是加性(additive)attention。但是再提一點(diǎn),在encoder和decoder的自注意力中,attention層的輸入分為self_attn(x, x, x, mask)和self_attn(t, t, t, mask), 這里的x和t分別為source和target輸入。后面會(huì)看到,從encoder到decoder層的注意力輸入時(shí)attn(t, m, m), 這里的m是Encoder的輸出。

def attention(query, key, value, mask=None, dropout=None):#因子化的點(diǎn)乘Attention-矩陣形式#Query: 查詢 (batch_size, heads, max_seq_len, d_k)#Key: 鍵 (batch_size, heads, max_seq_len_d_k)#Value: 值 (batch_size, heads, max_seq_len, d_v)#d_v = d_k#Q=K=Vd_k = query.size(-1)# (batch_size, heads, max_seq_len, d_k) * (batch_size, heads, d_k, max_seq_len)# = (batch_size, heads, max_seq_len, max_seq_len)# 為了方便說(shuō)明,只看矩陣的后兩維 (max_seq_len, max_seq_len), 即# How are you# How [[0.8, 0.2, 0.3]# are [0.2, 0.9, 0.6]# you [0.3, 0.6, 0.8]]# 矩陣中每個(gè)元素的含義是,他對(duì)其他單詞的貢獻(xiàn)(分?jǐn)?shù))# 例如,如果我們想得到所有單詞對(duì)單詞“How”的打分,取矩陣第一列[0.8, 0.2, 0.3], 然后做softmaxscores = torch.matmul(query, key.transpose(-2, -1)) \/ math.sqrt(d_k)# 對(duì)于padding部分,賦予一個(gè)極大的負(fù)數(shù),softmax后該項(xiàng)的分?jǐn)?shù)就接近0了,表示貢獻(xiàn)很小if mask is not None:scores = scores.masked_fill(mask == 0, -1e9)p_attn = F.softmax(scores, dim = -1)if dropout is not None:p_attn = dropout(p_attn)# 接著與Value做矩陣乘法 和V做點(diǎn)積:# (batch_size, heads, max_seq_len, max_seq_len) * (batch_size, heads, max_seq_len, d_k)# = (batch_size, heads, max_seq_len, d_k)context = torch.matmul(p_attn, value)return context, p_attn class MultiHeadedAttention(nn.Module):def __init__(self, h, d_model, dropout=0.1):"Take in model size and number of heads."super(MultiHeadedAttention, self).__init__()assert d_model % h == 0, "heads is not a multiple of the number of the in_features"# We assume d_v always equals d_kself.d_k = d_model // hself.h = hself.linears = clones(nn.Linear(d_model, d_model), 4)self.attn = Noneself.dropout = nn.Dropout(p=dropout)def forward(self, query, key, value, mask=None):#這里的query, key, value與attention函數(shù)中的含義有所不同,這里指的是原始的輸入.#對(duì)于Encoder的自注意力來(lái)說(shuō),輸入query=key=value=x#對(duì)于Decoder的自注意力來(lái)說(shuō),輸入query=key=value=t#對(duì)于Encoder和Decoder之間的注意力來(lái)說(shuō), 輸入query=t, key=value=m#其中m為Encoder的輸出,即給定target,通過(guò)key計(jì)算出m中每個(gè)輸出對(duì)當(dāng)前target的分?jǐn)?shù),在乘上mif mask is not None:# Same mask applied to all h heads.mask = mask.unsqueeze(1)nbatches = query.size(0)# 1) Do all the linear projections in batch from d_model => h x d_kquery, key, value = \[l(x).view(nbatches, -1, self.h, self.d_k).transpose(1, 2)for l, x in zip(self.linears, (query, key, value))]# 2) Apply attention on all the projected vectors in batch.## x: (batch_size, heads, max_seq_len, d_k)x, self.attn = attention(query, key, value, mask=mask,dropout=self.dropout)# 3) "Concat" using a view and apply a final linear.## x: (batch_size, max_seq_len, d_k*h)x = x.transpose(1, 2).contiguous() \.view(nbatches, -1, self.h * self.d_k)## output: (batch_size, max_seq_len, d_model)return self.linears[-1](x) def clones(module, N):"Produce N identical layers."return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])

2.3 Add & Norm

在Transformer中,每一個(gè)子層(self-attetion,Feed Forward Neural Network)之后都會(huì)接一個(gè)殘缺模塊,并且有一個(gè)Layer normalization。

一個(gè)殘差網(wǎng)絡(luò),將一層的輸入與其標(biāo)準(zhǔn)化后的輸出進(jìn)行相加即可。Transformer中每一個(gè)Self Attention層與FFN層后面都會(huì)連一個(gè)Add & Norm層。

LayerNormalization 層歸一化

Normalization有很多種,但是它們都有一個(gè)共同的目的,那就是把輸入轉(zhuǎn)化成均值為0方差為1的數(shù)據(jù)。我們?cè)诎褦?shù)據(jù)送入激活函數(shù)之前進(jìn)行normalization(歸一化),因?yàn)槲覀儾幌M斎霐?shù)據(jù)落在激活函數(shù)的飽和區(qū)。

BN的主要思想就是:在每一層的每一批數(shù)據(jù)上進(jìn)行歸一化。我們可能會(huì)對(duì)輸入數(shù)據(jù)進(jìn)行歸一化,但是經(jīng)過(guò)該網(wǎng)絡(luò)層的作用后,我們的數(shù)據(jù)已經(jīng)不再是歸一化的了。隨著這種情況的發(fā)展,數(shù)據(jù)的偏差越來(lái)越大,我的反向傳播需要考慮到這些大的偏差,這就迫使我們只能使用較小的學(xué)習(xí)率來(lái)防止梯度消失或者梯度爆炸。BN的具體做法就是對(duì)每一小批數(shù)據(jù),在批這個(gè)方向上做歸一化。

Layer normalization 它也是歸一化數(shù)據(jù)的一種方式,不過(guò)LN 是在每一個(gè)樣本上計(jì)算均值和方差,而不是BN那種在批方向計(jì)算均值和方差!公式如下:

class LayerNorm(nn.Module):"""實(shí)現(xiàn)LayerNorm。其實(shí)PyTorch已經(jīng)實(shí)現(xiàn)啦,見(jiàn)nn.LayerNorm。"""def __init__(self, features, eps=1e-6):"""Args:features: 就是模型的維度。論文默認(rèn)512eps: 一個(gè)很小的數(shù),防止數(shù)值計(jì)算的除0錯(cuò)誤"""super(LayerNorm, self).__init__()self.gamma = nn.Parameter(torch.ones(features))self.beta = nn.Parameter(torch.zeros(features))self.eps = epsdef forward(self, x):"""Args:x: 輸入序列張量,形狀為[B, L, D]"""# 在X的最后一個(gè)維度求均值,最后一個(gè)維度就是模型的維度mean = x.mean(-1, keepdim=True)# 在X的最后一個(gè)維度求方差,最后一個(gè)維度就是模型的維度std = x.std(-1, keepdim=True)return self.gamma * (x - mean) / (std + self.eps) + self.beta

2.4 前饋網(wǎng)絡(luò) Feed Forward Neural Network

我們需要一種方式,把 8 個(gè)矩陣降為 1 個(gè),首先,我們把 8 個(gè)矩陣連在一起,這樣會(huì)得到一個(gè)大的矩陣,再隨機(jī)初始化一個(gè)矩陣和這個(gè)組合好的矩陣相乘,最后得到一個(gè)最終的矩陣。

Encoder中和Decoder中經(jīng)過(guò)Attention之后輸出的n個(gè)向量(這里n是詞的個(gè)數(shù))都分別的輸入到一個(gè)全連接層中,完成一個(gè)逐個(gè)位置的前饋網(wǎng)絡(luò)。

每個(gè)encoderLayer中,多頭attention后會(huì)接一個(gè)前饋網(wǎng)絡(luò)。這個(gè)前饋網(wǎng)絡(luò)其實(shí)是兩個(gè)全連接層,進(jìn)行了如下操作:

論文提到,這個(gè)公式還可以用兩個(gè)核大小為1的一維卷積來(lái)解釋,卷積的輸入輸出都是dmodel=512dmodel=512 dmodel?=512,中間層的維度是dff=2048

class PositionwiseFeedForward(nn.Module):'''Implements FFN equation.d_model=512d_ff=2048'''def __init__(self, d_model, d_ff, dropout=0.1):super(PositionwiseFeedForward, self).__init__()self.w_1 = nn.Linear(d_model, d_ff)# self.w_1 = nn.Conv1d(in_features=d_model, out_features=d_ff, kenerl_size=1)self.w_2 = nn.Linear(d_ff, d_model)# self.w_2 = nn.Conv1d(in_features=d_ff, out_features=d_model, kenerl_size=1)self.dropout = nn.Dropout(dropout)def forward(self, x):return self.w_2(self.dropout(F.relu(self.w_1(x))))

這兩層的作用等價(jià)于兩個(gè) kenerl_size=1的一維卷積操作。

2.5 詞向量

這里就是普通的不能再普通的詞向量,將詞語(yǔ)變成d_model維的向量。Word embedding應(yīng)該是老生常談了,它實(shí)際上就是一個(gè)二維浮點(diǎn)矩陣,里面的權(quán)重是可訓(xùn)練參數(shù),我們只需要把這個(gè)矩陣構(gòu)建出來(lái)就完成了word embedding的工作。

class Embeddings(nn.Module):def __init__(self, d_model, vocab):super(Embeddings, self).__init__()self.lut = nn.Embedding(vocab, d_model)self.d_model = d_modeldef forward(self, x):return self.lut(x) * math.sqrt(self.d_model)

上面vocab_size就是詞典的大小,embedding_size就是詞嵌入的維度大小,論文里面就是等于dmodel=512,所以word embedding矩陣就是一個(gè)vocab_size*embedding_size的二維張量

Positional Encoding 位置編碼

由于Transformer沒(méi)有用到CNN和RNN,因此,句子單詞之間的位置信息就沒(méi)有利用到。顯然,這些信息對(duì)于翻譯來(lái)說(shuō)是非常有用的,同樣一句話,每個(gè)單詞的意思能夠準(zhǔn)確的翻譯出來(lái),但如果順序不對(duì),表達(dá)出來(lái)的意思就截然不同了。舉個(gè)栗子感受一下,原句:”A man went through the Big Buddhist Temple“, 翻譯成:”人過(guò)大佛寺“和”寺佛大過(guò)人“,意思就完全不同了。

那么如何表達(dá)一個(gè)序列的位置信息呢?為了解決這個(gè)問(wèn)題,Transformer提出了Positional Encoding的方案,就是給每個(gè)輸入的詞向量疊加一個(gè)固定的向量來(lái)表示它的位置。

文中使用的Positional Encoding如下:

對(duì)于某一個(gè)單詞來(lái)說(shuō),他的位置信息主要有兩個(gè)方面:一是絕對(duì)位置,二是相對(duì)位置。絕對(duì)位置決定了單詞在一個(gè)序列中的第幾個(gè)位置,相對(duì)位置決定了序列的流向。作者利用了正弦函數(shù)和余弦函數(shù)來(lái)進(jìn)行位置編碼:

其中pos是指當(dāng)前詞在句子中的位置,i是指向量中每個(gè)值的index,可以看出,在偶數(shù)位置,使用正弦編碼,在奇數(shù)位置,使用余弦編碼

最后把這個(gè)Positional Encoding與embedding的值相加,作為輸入送到下一層。

其中pos是詞在句子中的位置,i是詞向量中第i位,即將每個(gè)詞的詞向量為一行進(jìn)行疊加,然后針對(duì)每一列都疊加上一個(gè)相位不同或波長(zhǎng)逐漸增大的波,以此來(lái)唯一區(qū)分位置。

其中pos是單詞處于句子的第幾個(gè)位置。我們來(lái)考察一下第一個(gè)公式,看是否每個(gè)位置都能得到一個(gè)唯一的值作為編碼。為簡(jiǎn)單起見(jiàn),不妨令i=0,那么:

我們反過(guò)來(lái)想,假如存在位置j和k的編碼值相同,那么就有:

i,j 為非負(fù)整數(shù)且i不等于j, 以上兩式需要同時(shí)滿足,可等價(jià)為:

i,j為非負(fù)整數(shù)且i不等于j且k為整數(shù)

同時(shí)成立,這就意味著:

這顯然是不可能的,因?yàn)樽筮吺莻€(gè)無(wú)理數(shù)(無(wú)限不循環(huán)小數(shù)),而右邊是個(gè)有理數(shù)。通過(guò)反證法就證明了在這種表示下,每個(gè)位置確實(shí)有唯一的編碼。

上面的討論并未考慮i的作用。i決定了頻率的大小,不同的i可以看成是不同的頻率空間中的編碼,是相互正交的,通過(guò)改變i的值,就能得到多維度的編碼,類(lèi)似于詞向量的維度。這里2i<=512(d_model), 一共512維。想象一下,當(dāng)2i大于d_model時(shí)會(huì)出現(xiàn)什么情況,這時(shí)sin函數(shù)的周期會(huì)變得非常大,函數(shù)值會(huì)非常接近于0,這顯然不是我們希望看到的,因?yàn)檫@樣和詞向量就不在一個(gè)量級(jí)了,位置編碼的作用被削弱了。另外,值得注意的是,位置編碼是不參與訓(xùn)練的,而詞向量是參與訓(xùn)練的。作者通過(guò)實(shí)驗(yàn)發(fā)現(xiàn),位置編碼參與訓(xùn)練與否對(duì)最終的結(jié)果并無(wú)影響。

class PositionalEncoding(nn.Module):"Implement the PE function."def __init__(self, d_model, dropout, max_len=5000):"""初始化。Args:d_model: 一個(gè)標(biāo)量。模型的維度,論文默認(rèn)是512max_seq_len: 一個(gè)標(biāo)量。文本序列的最大長(zhǎng)度"""super(PositionalEncoding, self).__init__()self.dropout = nn.Dropout(p=dropout)# Compute the positional encodings once in log space.pe = torch.zeros(max_len, d_model)position = torch.arange(0, max_len).unsqueeze(1)div_term = torch.exp(torch.arange(0, d_model, 2) *-(math.log(10000.0) / d_model))pe[:, 0::2] = torch.sin(position * div_term)pe[:, 1::2] = torch.cos(position * div_term)pe = pe.unsqueeze(0)self.register_buffer('pe', pe)def forward(self, x):x = x + Variable(self.pe[:, :x.size(1)],requires_grad=False)return self.dropout(x)

之所以對(duì)奇偶位置分別編碼,是因?yàn)榫幋a前一個(gè)位置是可以由另一個(gè)位置線性表示的(公差為1的等差數(shù)列),在編碼之后也希望能保留這種線性。我們以第1個(gè)位置和第k+1個(gè)位置為例,還是令i=0:

至此,我們就把Encoder部分的細(xì)節(jié)介紹完了,下面來(lái)看下Decoder部分

三 Decoder

Decoder和Encoder的結(jié)構(gòu)差不多,但是多了一個(gè)attention的sub-layer,這里先明確一下decoder的輸入輸出和解碼過(guò)程:

  • 輸出:對(duì)應(yīng)i位置的輸出詞的概率分布
  • 輸入:encoder的輸出 & 對(duì)應(yīng)i-1位置decoder的輸出。所以中間的attention不是self-attention,它的K,V來(lái)自encoder,Q來(lái)自上一位置decoder的輸出
  • 解碼:這里要特別注意一下,編碼可以并行計(jì)算,一次性全部encoding出來(lái),但解碼不是一次把所有序列解出來(lái)的,而是像rnn一樣一個(gè)一個(gè)解出來(lái)的,因?yàn)橐蒙弦粋€(gè)位置的輸入當(dāng)作attention的query

明確了解碼過(guò)程之后最上面的圖就很好懂了,這里主要的不同就是新加的另外要說(shuō)一下新加的attention多加了一個(gè)mask,因?yàn)橛?xùn)練時(shí)的output都是ground truth,這樣可以確保預(yù)測(cè)第i個(gè)位置時(shí)不會(huì)接觸到未來(lái)的信息。

每一個(gè)層包括以下3個(gè)部分:

  • 第一個(gè)部分是multi-head self-attention mechanism
  • 第二部分是multi-head context-attention mechanism
  • 第三部分是一個(gè)position-wise feed-forward network

還是和encoder類(lèi)似,上面三個(gè)部分的每一個(gè)部分,都有一個(gè)殘差連接,后接一個(gè)Layer Normalization

但是,decoder出現(xiàn)了一個(gè)新的東西multi-head context-attention mechanism。這個(gè)東西其實(shí)也不復(fù)雜,理解了multi-head self-attention你就可以理解multi-head context-attention

通過(guò)觀察上面的結(jié)構(gòu)圖我們還可以發(fā)現(xiàn)Decoder與Encoder的另外一個(gè)不同,就是每個(gè)Decoder單元的輸入層,要先經(jīng)過(guò)一個(gè)Masked Attention層。那么Masked的與普通版本的Attention有什么區(qū)別呢?

3.1 Masked Mutil-head Attention

mask 表示掩碼,它對(duì)某些值進(jìn)行掩蓋,使其在參數(shù)更新時(shí)不產(chǎn)生效果

Encoder因?yàn)橐幋a整個(gè)句子,所以每個(gè)詞都需要考慮上下文的關(guān)系。所以每個(gè)詞在計(jì)算的過(guò)程中都是可以看到句子中所有的詞的。但是Decoder與Seq2Seq中的解碼器類(lèi)似,每個(gè)詞都只能看到前面詞的狀態(tài),所以是一個(gè)單向的Self-Attention結(jié)構(gòu)。

Masked Attention的實(shí)現(xiàn)也非常簡(jiǎn)單,只要在普通的Self Attention的Softmax步驟之前,與(&)上一個(gè)下三角矩陣M就好了

需要說(shuō)明的是,我們的Transformer模型里面涉及兩種mask。分別是padding mask和sequence mask。其中后者我們已經(jīng)在decoder的self-attention里面見(jiàn)過(guò)啦!其中,padding mask在所有的scaled dot-product attention里面都需要用到,而sequence mask只有在decoder的self-attention里面用到。

所以,我們之前ScaledDotProductAttention的forward方法里面的參數(shù)attn_mask在不同的地方會(huì)有不同的含義。

  • padding mask

    什么是padding mask呢?回想一下,我們的每個(gè)批次輸入序列長(zhǎng)度是不一樣的!也就是說(shuō),我們要對(duì)輸入序列進(jìn)行對(duì)齊!具體來(lái)說(shuō),就是給在較短的序列后面填充0。但是如果輸入的序列太長(zhǎng),則是截取左邊的內(nèi)容,把多余的直接舍棄。因?yàn)檫@些填充的位置,其實(shí)是沒(méi)什么意義的,所以我們的attention機(jī)制不應(yīng)該把注意力放在這些位置上,所以我們需要進(jìn)行一些處理。

    具體的做法是,把這些位置的值加上一個(gè)非常大的負(fù)數(shù)(可以是負(fù)無(wú)窮),這樣的話,經(jīng)過(guò)softmax,這些位置的概率就會(huì)接近0!

    而我們的padding mask實(shí)際上是一個(gè)張量,每個(gè)值都是一個(gè)Boolen,值為False的地方就是我們要進(jìn)行處理的地方。

    下面是實(shí)現(xiàn):

    # 參考實(shí)現(xiàn)代碼 def padding_mask(seq_k, seq_q):# seq_k和seq_q的形狀都是[B,L]len_q = seq_q.size(1)# `PAD` is 0pad_mask = seq_k.eq(0)pad_mask = pad_mask.unsqueeze(1).expand(-1, len_q, -1) # shape [B, L_q, L_k]return pad_mask
  • Sequence mask

    文章前面也提到,sequence mask是為了使得decoder不能看見(jiàn)未來(lái)的信息。也就是對(duì)于一個(gè)序列,在time_step為t的時(shí)刻,我們的解碼輸出應(yīng)該只能依賴于t時(shí)刻之前的輸出,而不能依賴t之后的輸出。因此我們需要想一個(gè)辦法,把t之后的信息給隱藏起來(lái)。

    那么具體怎么做呢?也很簡(jiǎn)單:產(chǎn)生一個(gè)上三角矩陣,上三角的值全為1,下三角的值權(quán)威0,對(duì)角線也是0。把這個(gè)矩陣作用在每一個(gè)序列上,就可以達(dá)到我們的目的啦。

    具體的代碼實(shí)現(xiàn)如下:

    #參考實(shí)現(xiàn)代碼 def sequence_mask(seq):batch_size, seq_len = seq.size()mask = torch.triu(torch.ones((seq_len, seq_len), dtype=torch.uint8),diagonal=1)mask = mask.unsqueeze(0).expand(batch_size, -1, -1) # [B, L, L]return mask
  • 對(duì)于 decoder 的 self-attention,里面使用到的 scaled dot-product attention,同時(shí)需要padding mask 和 sequence mask 作為 attn_mask,具體實(shí)現(xiàn)就是兩個(gè)mask相加作為attn_mask。其他情況,attn_mask 一律等于 padding mask。

    注意下attention當(dāng)中的mask。我們之前提到,在三個(gè)地方用到了attention。在Encoder的自注意力機(jī)制中,mask是用來(lái)過(guò)濾padding部分的作用,對(duì)于source中的每一個(gè)詞來(lái)講,其他的詞對(duì)他都是可見(jiàn)的,都可以做出貢獻(xiàn)的。但是在Decoder中,mask的作用就有所不同了。這可能又要從Encoder-Decoder框架說(shuō)起。在這個(gè)框架下,解碼器實(shí)際上可看成一個(gè)神經(jīng)網(wǎng)絡(luò)語(yǔ)言模型,預(yù)測(cè)的時(shí)候,target中的每一個(gè)單詞是逐個(gè)生成的,當(dāng)前詞的生成依賴兩方面:

    • 一是Encoder的輸出.
    • 二是target的前面的單詞.

    例如,在生成第一個(gè)單詞是,不僅依賴于Encoder的輸出,還依賴于起始標(biāo)志[CLS];生成第二個(gè)單詞是,不僅依賴Encoder的輸出,還依賴起始標(biāo)志和第一個(gè)單詞……依此類(lèi)推。這其實(shí)是說(shuō),在翻譯當(dāng)前詞的時(shí)候,是看不到后面的要翻譯的詞。由上可以看出,這里的mask是動(dòng)態(tài)的。

    def subsequent_mask(size):"Mask out subsequent positions."# size: 序列長(zhǎng)度attn_shape = (1, size, size)# 生成一個(gè)上三角矩陣subsequent_mask = np.triu(np.ones(attn_shape), k=1).astype('uint8')return torch.from_numpy(subsequent_mask) == 0

    下面詳細(xì)介紹下subsequent_mask是如何起作用的。函數(shù)的參數(shù)size指的是target句子的長(zhǎng)度。以”[CLS] That is it“這個(gè)長(zhǎng)度為4的target輸入為例,這個(gè)函數(shù)的輸出是什么呢?

    print(subsequent_mask(size=4))tensor([[[1, 0, 0, 0],[1, 1, 0, 0],[1, 1, 1, 0],[1, 1, 1, 1]]], dtype=torch.uint8)

    可以看到,輸出為一個(gè)下三角矩陣,維度為(1,4,4)。現(xiàn)在我們?cè)賮?lái)看下attention函數(shù),mask起作用的地方是在Query和Key點(diǎn)乘后,結(jié)果矩陣的維度為(batch_size, heads, max_seq_len, max_seq_len)。為方便起見(jiàn),我們只看一條數(shù)據(jù),即batch_size=1。進(jìn)入多頭attention時(shí),注意到對(duì)mask做了一步操作:

    mask = mask.unsqueeze(1) mask: tensor([[[[1, 0, 0, 0],[1, 1, 0, 0],[1, 1, 1, 0],[1, 1, 1, 1]]]], dtype=torch.uint8)

    這時(shí)mask的維度變成了(1,1,4,4).

    target:CLS That is itCLS [[[[0.8, 0.2, 0.3, 0.9]That [0.2, 0.9, 0.6, 0.4]is [0.3, 0.6, 0.8, 0.7]it [1.2, 0.6, 2.1, 3.2]]]]mask:[[[[1, 0, 0, 0],[1, 1, 0, 0],[1, 1, 1, 0],[1, 1, 1, 1]]]]

    寫(xiě)成了上面的樣子,mask的作用就很顯然了。例如,對(duì)于”CLS“來(lái)說(shuō),預(yù)測(cè)它下一個(gè)詞時(shí),只有”CLS“參與了attention,其他的詞(相對(duì)于CLS為未來(lái)的詞)都被mask_fill掉了,不起作用。后面的情況依此類(lèi)推。

    細(xì)心的小伙伴可能發(fā)現(xiàn)了,這里的解釋并沒(méi)有考慮padding部分。事實(shí)上,就算加了padding部分(為0),也不影響上述過(guò)程,有興趣的話可以在上面it后面加上個(gè)0,下面的矩陣加一列[0 0 0 0 ], 就可以一目了然。

    class Decoder(nn.Module):"Generic N layer decoder with masking."def __init__(self, layer, N):super(Decoder, self).__init__()self.layers = clones(layer, N)self.norm = LayerNorm(layer.size)def forward(self, x, memory, src_mask, tgt_mask):for layer in self.layers:x = layer(x, memory, src_mask, tgt_mask)return self.norm(x)

    每個(gè)組件長(zhǎng)什么樣子呢?首先輸入經(jīng)過(guò)詞向量和位置編碼,進(jìn)入target的自注意力層,這里和Encoder一樣,也是用了殘差和層歸一化。然后呢,這個(gè)輸出再和Encoder的輸出做一次context attention,相當(dāng)于把上面的那層重復(fù)了一次,唯一不同的是,這次的attention有點(diǎn)不一樣的,不再是自注意力,所有的技術(shù)細(xì)節(jié)都可以參照Encoder部分,這里不再?gòu)?fù)述。

    class DecoderLayer(nn.Module):"Decoder is made of self-attn, src-attn, and feed forward (defined below)"def __init__(self, size, self_attn, src_attn, feed_forward, dropout):super(DecoderLayer, self).__init__()self.size = sizeself.self_attn = self_attnself.src_attn = src_attnself.feed_forward = feed_forwardself.sublayer = clones(SublayerConnection(size, dropout), 3)def forward(self, x, memory, src_mask, tgt_mask):m = memoryx = self.sublayer[0](x, lambda x: self.self_attn(x, x, x, tgt_mask))x = self.sublayer[1](x, lambda x: self.src_attn(x, m, m, src_mask))return self.sublayer[2](x, self.feed_forward)

    3.2 線性層和softmax

    這是整個(gè)模型的最后一步了。從Decoder拿到的輸出是維度為(batch_size, max_seq_len, d_model)的浮點(diǎn)型張量,我們希望得到最終每個(gè)單詞預(yù)測(cè)的結(jié)果,首先用一個(gè)線性層將d_model映射到vocab的維度,得到每個(gè)單詞的可能性,然后送入softmax,找到最可能的單詞。

    線性層的參數(shù)個(gè)數(shù)為d_mode ?? vocab_size, 一般來(lái)說(shuō),vocab_size會(huì)比較大,拿20000為例,那么只這層的參數(shù)就有512?20000512?20000個(gè),約為10的8次方,非常驚人。而在詞向量那一層,同樣也是這個(gè)數(shù)值,所以,一種比較好的做法是將這兩個(gè)全連接層的參數(shù)共享,會(huì)節(jié)省不少內(nèi)存,而且效果也不會(huì)差。

    class Generator(nn.Module):"Define standard linear + softmax generation step."def __init__(self, d_model, vocab):super(Generator, self).__init__()self.proj = nn.Linear(d_model, vocab)def forward(self, x):return F.log_softmax(self.proj(x), dim=-1)

    3.3 完整模型代碼

    def transformer_model(src_vocab, tgt_vocab, N=6, d_model=512, d_ff=2048, h=8, dropout=0.1):"Helper: Construct a model from hyperparameters."c = copy.deepcopyattn = MultiHeadedAttention(h, d_model)ff = PositionwiseFeedForward(d_model, d_ff, dropout)position = PositionalEncoding(d_model, dropout)model = EncoderDecoder(Encoder(EncoderLayer(d_model, c(attn), c(ff), dropout), N),Decoder(DecoderLayer(d_model, c(attn), c(attn), c(ff), dropout), N),nn.Sequential(Embeddings(d_model, src_vocab), c(position)),nn.Sequential(Embeddings(d_model, tgt_vocab), c(position)),Generator(d_model, tgt_vocab))# This was important from their code. # Initialize parameters with Glorot / fan_avg.for p in model.parameters():if p.dim() > 1:nn.init.xavier_uniform(p)return modelmodel = transformer_model(10, 10, 2)

    詳細(xì)例子解釋: Attention Is All You Need(注意力模型)

    GitHub鏈接:https://github.com/harvardnlp/annotated-transformer

    代碼解讀:Transformer解析與tensorflow代碼解讀

    GitHub - Kyubyong/transformer: A TensorFlow Implementation of the Transformer: Attention Is All You Need



    ?

    總結(jié)

    以上是生活随笔為你收集整理的[深度学习] 自然语言处理---Transformer实现(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    超碰人人超 | 亚洲日韩欧美一区二区在线 | 9在线观看免费高清完整 | 久操免费视频 | 成人免费视频免费观看 | 日韩综合色 | 99久久精品国产免费看不卡 | 天天操天天射天天 | 婷婷天天色 | 999国产精品视频 | 国产69精品久久app免费版 | wwxxxx日本 | 免费观看一级视频 | 国产精品99久久久久久宅男 | 精品国产理论片 | 久草视频中文在线 | 手机色在线| 久久久久久网址 | 中文日韩在线 | 91在线精品视频 | 亚洲视频 视频在线 | 国产呻吟在线 | 最新99热| 在线国产一区二区 | 国产高清av免费在线观看 | 国产一区二区三精品久久久无广告 | 成人一区在线观看 | 一区二区三区高清不卡 | 久久久久久福利 | 国产精品99久久免费观看 | 99精品视频免费观看视频 | 成人免费xyz网站 | 久久久久久草 | 午夜精品一区二区三区免费 | 亚洲高清在线观看视频 | 久久999久久| 福利一区在线 | www.色五月.com | 国产在线不卡一区 | 欧美日bb | 久久99国产综合精品免费 | 亚洲婷婷免费 | 成人网444ppp | 国产精品久久久久婷婷 | 色婷婷精品大在线视频 | 久久神马影院 | 久草精品在线观看 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 国产首页 | 国产三级国产精品国产专区50 | 免费黄色小网站 | 欧美日韩视频精品 | 久久不射网站 | 日韩欧美综合视频 | 国产成人精品免费在线观看 | 久草视频在线资源 | 91在线免费观看国产 | 黄色a视频 | 久久 一区 | 成人一区二区三区在线 | 天天射天天拍 | 欧美日韩在线观看一区二区 | 日本黄色a级大片 | www.干| 成人欧美一区二区三区在线观看 | 国产中文字幕国产 | 国产成人精品久久久 | 婷婷日日 | 亚洲高清色综合 | 欧美成人黄色片 | 超碰97中文 | 欧美国产亚洲精品久久久8v | 国产成人精品三级 | 丁香婷婷综合网 | 中文字幕在线免费97 | 成年人视频免费在线 | 欧美性黄网官网 | 91av九色| 天天色天天搞 | 最近2019中文免费高清视频观看www99 | 国产xxxxx在线观看 | 黄色精品网站 | 久久综合色影院 | 五月天天av| 国内精品免费 | 久久精品网址 | 免费在线观看成年人视频 | 久久久麻豆精品一区二区 | 精品一区久久 | 久草视频在线资源站 | 狠狠色丁香久久婷婷综合丁香 | 日韩一区在线播放 | 91九色porny在线 | 中文字幕在线播放第一页 | 超级碰碰碰免费视频 | www.天天操| 黄色大全视频 | 亚洲精品欧洲精品 | 91精品国产成人 | 4438全国亚洲精品在线观看视频 | 四虎www com| 久久精品这里热有精品 | 日韩 在线| 国产午夜一区二区 | 精品一区二区免费在线观看 | 欧美精品一区二区三区一线天视频 | 毛片1000部免费看 | 欧美高清视频不卡网 | 99在线国产 | 亚洲精品视频在线播放 | 国产精品一区二区久久久 | 亚洲a资源 | 99日精品| 日韩在线视频网址 | 日韩一区精品 | 精品亚洲免费视频 | 97av免费视频 | 91在线国内视频 | 国产不卡在线 | 美女在线国产 | 国产精品人成电影在线观看 | 91视频免费观看 | 免费av高清 | 韩日精品中文字幕 | 国产精品午夜在线观看 | 免费 在线 中文 日本 | 91成人免费看片 | 精品国产乱码久久久久久浪潮 | 99精品免费久久久久久久久 | 麻豆果冻剧传媒在线播放 | 国产精品一二 | 亚洲精品久久久久中文字幕二区 | 国产亚洲精品久久久久久久久久 | 五月天婷婷视频 | www五月婷婷 | 开心激情网五月天 | 中文字幕免费 | 国产精品18久久久久久首页狼 | 日韩欧美一区二区三区视频 | 天天色天天射综合网 | 欧美一区二区在线免费看 | 6080yy精品一区二区三区 | 亚洲专区视频在线观看 | 国产精品一区二区av | 五月婷久久 | 美国av片在线观看 | www免费黄色 | 日韩激情影院 | 丁香花在线视频观看免费 | 日韩免费看的电影 | 久久综合婷婷国产二区高清 | 天天干天天综合 | 国模一二三区 | 欧美aⅴ在线观看 | 中文字幕不卡在线88 | 免费在线观看不卡av | 色视频网页 | 成人动漫一区二区 | 午夜精品中文字幕 | 成年人免费看av | 在线黄网站 | av三级av| 色小说在线 | 五月天天在线 | 亚洲年轻女教师毛茸茸 | 综合网天天色 | 精品免费在线视频 | 五月婷婷综合在线 | 中国美女一级看片 | 狠狠狠色狠狠色综合 | 久久久久久久网 | 亚洲特级片 | 国产精品99久久久久 | 日韩精品一区二区在线 | 四虎天堂 | 久久系列 | av青草| 激情久久综合 | 免费国产一区二区 | 人人爽人人搞 | 亚洲一区二区精品在线 | 91麻豆福利| 黄色免费大片 | 五月天堂色 | 亚洲精品mv在线观看 | 伊人五月天av | 91视频免费看 | 在线色资源 | 欧美大片在线观看一区 | a午夜在线 | av免费观看高清 | 成人午夜电影在线播放 | 久99久中文字幕在线 | 国产精品涩涩屋www在线观看 | 国产91av视频在线观看 | 日韩av高清在线观看 | 免费日韩一区二区 | 西西444www | 成人av电影免费在线观看 | 亚洲视屏 | 免费看国产一级片 | 久久久精品在线观看 | 欧美日韩午夜爽爽 | 国产理论影院 | 久久高清免费 | 亚洲三级网 | av中文在线播放 | 免费观看av | 国产在线p | 亚洲成人资源在线观看 | 中文字幕在线成人 | 精品亚洲免费 | 中文字幕超清在线免费 | 免费日韩 精品中文字幕视频在线 | 91视频首页 | 超碰人人在线 | 午夜美女av | 久久免费电影网 | 国产在线a免费观看 | 不卡视频国产 | 午夜国产福利在线观看 | 久久久久高清毛片一级 | 欧美小视频在线观看 | 日本狠狠色 | 国产午夜三级一二三区 | 天天干天天干天天 | 日韩欧美在线播放 | 国产精品久一 | 十八岁以下禁止观看的1000个网站 | 国产精品一区二区三区99 | 一区二区三区日韩在线观看 | 精品久久久久久久久中文字幕 | 国产精品福利小视频 | 天天草网站 | 亚洲综合视频在线 | 国产尤物在线视频 | 精品在线播放视频 | 久久精品1区 | 久久伊人八月婷婷综合激情 | 久操97| 超碰97国产精品人人cao | 最近免费中文字幕大全高清10 | 国产精品igao视频网入口 | 97超视频免费观看 | 亚洲免费av片 | 亚洲视屏在线播放 | 日韩在线视频免费观看 | 日韩电影在线视频 | 韩国精品一区二区三区六区色诱 | 日韩91av| 美女国产免费 | 91九色视频 | 国产成人精品亚洲日本在线观看 | 欧美激情另类文学 | 91在线精品视频 | 夜夜干夜夜 | 狠狠干狠狠久久 | 天天搞天天干天天色 | 国产中文字幕视频在线观看 | 深夜成人av | 一区二区三区国 | 国产中文伊人 | 欧美极品一区二区三区 | www.亚洲精品视频 | 日韩一级成人av | 久久国产精品二国产精品中国洋人 | a特级毛片| 国产在线精品一区二区不卡了 | 一区二区三区在线观看 | 亚洲欧洲成人精品av97 | 午夜精品三区 | 蜜臀久久99精品久久久无需会员 | 免费看一级特黄a大片 | 蜜臀91丨九色丨蝌蚪老版 | 久久视频免费在线观看 | 69xxxx欧美| 国产精品综合在线观看 | 亚洲精品综合一二三区在线观看 | 在线看日韩 | 制服丝袜欧美 | 国产黄在线免费观看 | 国产福利在线免费观看 | 五月婷婷在线综合 | 又大又硬又黄又爽视频在线观看 | 日本中文字幕网 | 日韩av三区 | 久久综合久久综合这里只有精品 | 久久免费视频8 | 国产涩涩在线观看 | 日韩中文字幕免费在线观看 | 在线观看视频亚洲 | 人人爽夜夜爽 | 亚洲欧洲国产日韩精品 | 一区二区视频免费在线观看 | 午夜av免费 | 国产亚洲精品综合一区91 | 日产乱码一二三区别在线 | 天天干天天看 | 天天干天天弄 | 97狠狠干 | 国产精品剧情 | 色综合久久久 | 久草视频免费在线播放 | 国产色一区 | 国产不卡视频 | 视频在线观看亚洲 | 午夜视频二区 | 日韩在线观看中文 | 国产精品久久久久永久免费 | 国内精品亚洲 | 免费视频你懂的 | 国产精品久久久久一区二区国产 | 天天干天天操天天爱 | 久久精品国产一区二区三区 | 97高清视频 | 黄色在线观看免费 | 精品国产91亚洲一区二区三区www | 国产精品va在线观看入 | 免费国产黄线在线观看视频 | 亚洲高清av | 9在线观看免费高清完整版 玖玖爱免费视频 | 欧美日韩精品免费观看视频 | 久久新视频 | 国产69精品久久久久99尤 | 色婷婷亚洲 | 91传媒在线看 | 中文字幕网站视频在线 | 九九视频网站 | 久久综合色一综合色88 | av一区二区三区在线 | 亚洲成人资源在线 | 精品久久久免费 | 中文字幕久久网 | 国产精品美女999 | 久久久高清 | av在线免费网站 | 在线黄色免费 | 成人在线播放视频 | 亚洲黄色免费在线看 | a黄色片| 在线亚洲日本 | 国产黄色视 | 超碰av在线播放 | 一区二区视频电影在线观看 | 91av在线国产 | 久久久久久久影院 | 中文字幕二区三区 | 91人人人| 99热日本 | 婷婷色网址 | 亚洲午夜精品久久久 | 在线免费黄色av | 在线观看aaa| 久久99精品国产99久久 | 五月婷婷中文字幕 | 亚洲自拍偷拍色图 | 中文亚洲欧美日韩 | 伊人久操 | 在线看v片成人 | 97网站| 精品免费在线视频 | 亚洲日本va中文字幕 | 日本一区二区免费在线观看 | 国产精品你懂的在线观看 | 天天碰天天操 | 99精品久久久久 | 中文字幕日韩国产 | 日韩毛片精品 | 91视频88av| 九九在线高清精品视频 | 欧美欧美 | 99久久精品国产一区 | 午夜视频在线观看一区二区 | 免费看污片 | 欧美污在线观看 | 人人爱天天操 | 在线观看视频黄 | 久久99九九99精品 | 在线97| 在线观看福利网站 | 日韩免费在线观看 | 免费在线观看中文字幕 | 久久精品99国产精品 | 国产精品久久久久久久久久久久久久 | 国产免费黄色 | 在线直播av| 最新不卡av| 国产不卡高清 | 91高清免费 | 久色婷婷 | 九月婷婷色 | 日韩国产精品一区 | 亚洲日本一区二区在线 | 九九视频在线观看视频6 | 日韩性xxxx| 久久艹国产视频 | 9色在线视频 | 免费看一级 | 99免费在线观看 | aa级黄色大片 | 日韩在线色视频 | 亚洲码国产日韩欧美高潮在线播放 | 人人舔人人| 精品国产视频在线 | 999久久久免费视频 午夜国产在线观看 | 成人免费av电影 | 国产精品免费大片视频 | 国产精品一区二区久久精品 | 天天射天天 | 91亚色在线观看 | 亚洲视频999 | 国产伦精品一区二区三区高清 | 玖玖在线资源 | 婷婷六月色 | 在线免费亚洲 | www.久久成人 | 国产成人99久久亚洲综合精品 | 黄色视屏av | 成人一级视频在线观看 | 日韩亚洲在线 | 在线观看中文字幕视频 | 日韩欧美视频在线播放 | www黄色大片 | 久草精品在线播放 | 亚洲 欧美 91 | aaa毛片视频| 精品国产乱码久久 | 久久久久国产一区二区三区四区 | 精品久久精品久久 | 安徽妇搡bbbb搡bbbb | 午夜av网站 | 成人毛片一区二区三区 | 国产日本亚洲 | 免费91麻豆精品国产自产在线观看 | 在线91av| 成人全视频免费观看在线看 | 亚洲精品小视频 | 日韩三级在线 | 日韩在线视频免费播放 | 91中文在线视频 | 四虎影视成人永久免费观看视频 | 国产精品观看视频 | 日日爱网址 | 国产精品一区欧美 | 久久久久二区 | 亚洲精品久久激情国产片 | 一区二区视频在线播放 | 三级黄色大片在线观看 | 中文字幕一区二区三区四区 | 亚洲 中文 欧美 日韩vr 在线 | 亚洲精品国偷自产在线91正片 | 91精品久久久久久久久 | 成人a大片 | 婷婷色狠狠 | 亚洲精品视频二区 | 99热官网| 精品成人在线 | 91插插视频 | 国产91免费看 | 香蕉久久久久久久 | 国产色婷婷精品综合在线手机播放 | 99精品一区二区三区 | 九九九热精品 | 99久久婷婷国产综合精品 | 欧美精品中文字幕亚洲专区 | 伊人久久五月天 | 96av在线视频 | 国产亚洲视频在线观看 | 激情五月婷婷丁香 | 亚洲伊人第一页 | 国内精品久久久久影院优 | 黄免费网站 | 在线黄色av | 中文国产在线观看 | 日韩专区在线播放 | 超碰电影在线观看 | 国产香蕉久久精品综合网 | 色综合国产 | 亚洲天天在线日亚洲洲精 | 97自拍超碰 | 色姑娘综合天天 | www.色婷婷.com| 国产亚洲va综合人人澡精品 | 日本电影久久 | 黄色软件在线观看免费 | 狠狠色婷婷丁香六月 | 成年人在线视频观看 | 国产第一页在线播放 | 五月天激情综合 | 日本精a在线观看 | 青青草国产成人99久久 | 色无五月 | 日韩av播放在线 | 日日操日日操 | 日本xxxx裸体xxxx17 | 亚洲精品一区二区精华 | 亚洲视频综合在线 | 国产亚洲在线视频 | 黄色毛片电影 | 国产精品久久久久久久久婷婷 | 91在线porny国产在线看 | 米奇四色影视 | 在线91色 | 久久久久国产一区二区三区 | 国产99一区视频免费 | 日日夜夜中文字幕 | 欧美一区,二区 | 亚洲一区二区三区91 | 麻花天美星空视频 | 不卡av在线免费观看 | 国产自产在线视频 | 亚洲aⅴ在线 | 三级黄色欧美 | 在线91视频 | 国产精品一区二区中文字幕 | 久久试看| 精品久久久亚洲 | 亚洲欧美成人网 | 日韩一区二区三区高清免费看看 | www.天天干 | 亚洲精品一区二区三区高潮 | 草免费视频 | 精品99在线 | 亚洲精品乱码白浆高清久久久久久 | 2019中文最近的2019中文在线 | 狠狠躁18三区二区一区ai明星 | 开心色停停 | 中文字幕在线观看一区二区三区 | 97精品国产97久久久久久 | 蜜臀av.com| 成人久久久久久久久久 | 国产淫片免费看 | 日色在线视频 | 99视频一区二区 | 456成人精品影院 | www.日日日.com | 日韩av手机在线看 | 中文字幕在线视频一区二区三区 | 中文字幕在线观看免费高清电影 | 久久高清| 福利久久 | 精品久久久久久久久久久久久久久久久久 | 狠狠躁天天躁 | 欧美在线日韩在线 | 成人一级在线 | 午夜精品久久久久久久久久 | 精品在线观 | 在线免费黄网站 | 91亚洲精品久久久久图片蜜桃 | 久久国产三级 | 婷婷中文字幕综合 | 最新91在线视频 | av成人在线网站 | 波多野结衣久久精品 | 黄色av大片 | 中文字幕久久精品一区 | 日韩女同av | 欧美一区二区精品在线 | 欧美在线aaa | 91久久奴性调教 | 日韩三级一区 | 99精品视频在线免费观看 | 日韩电影在线视频 | 色就色,综合激情 | 欧洲一区精品 | 色婷丁香 | 色婷婷综合久色 | 91天天操| 91视频免费网站 | www日韩欧美 | 国产 亚洲 欧美 在线 | 国产一区二区三区视频在线 | 亚洲aⅴ一区二区三区 | 美女在线黄 | 97精品国产手机 | 在线看v片 | 国产精品99久久久久久宅男 | 久久99久久99精品中文字幕 | 中文字幕一区二区三区视频 | 日韩欧美视频一区二区三区 | 亚洲精品视频免费在线观看 | 九九视频热 | 狠狠网 | 欧洲一区二区三区精品 | 色亚洲网 | 久久免费视频这里只有精品 | 日本精品中文字幕在线观看 | 在线观看亚洲视频 | 国产福利不卡视频 | 国产高清在线 | 国产伦精品一区二区三区照片91 | 午夜国产影院 | 射射射av | www.91成人 | 国产一级性生活视频 | 91九色在线观看视频 | 免费又黄又爽视频 | 精品国产视频在线 | 夜夜骑日日操 | 久久精品一二三区 | 91在线你懂的 | 91色蜜桃| 国产最顶级的黄色片在线免费观看 | 粉嫩一区二区三区粉嫩91 | 日韩欧美大片免费观看 | 色欧美成人精品a∨在线观看 | 日韩欧美一区二区在线观看 | 99精品国产一区二区 | 999热视频 | 国产麻豆成人传媒免费观看 | 欧美日韩国产二区三区 | 99久久精品国产一区 | 大型av综合网站 | 成人av中文字幕 | avlulu久久精品 | 九九精品视频在线 | 久草视频在线播放 | 免费av网站在线 | 一二三区在线 | 99精彩视频在线观看免费 | 免费在线成人av电影 | h动漫中文字幕 | 日韩二区在线观看 | 久9在线 | 999视频在线观看 | 亚洲综合在线一区二区三区 | 乱男乱女www7788 | 97视频免费观看 | 中文字幕免费高清 | 国产精品一区二区视频 | 果冻av在线 | 在线91精品 | 久久国产影视 | 成年人在线看视频 | 精品中文字幕在线 | www.91成人| 日韩中文字幕免费视频 | 欧美少妇影院 | 久久官网| 免费黄色av. | 日日综合网| 999热视频 | 久久午夜精品视频 | 亚洲一片黄 | 亚洲国产字幕 | 日本在线精品视频 | 亚洲精品久久久久999中文字幕 | 日韩网站中文字幕 | 免费黄a | 国产69精品久久久久久 | 天天操天天射天天爽 | 日本久久视频 | 久久久久久久久久久福利 | 激情婷婷av | 米奇狠狠狠888 | 激情五月色播五月 | 91亚洲网| 国产一区二区在线视频观看 | 免费av在| 日韩视频中文字幕在线观看 | 国产v视频 | 国产免费久久精品 | 亚洲人人av | 国产涩涩在线观看 | 亚洲精品乱码久久久久久写真 | 懂色av懂色av粉嫩av分享吧 | 视频一区二区免费 | 国产亚洲aⅴaaaaaa毛片 | 国内精品毛片 | 91九色最新地址 | 波多野结依在线观看 | 亚洲黄色av网址 | 久久99国产精品久久99 | 国产精品久久久久三级 | 日韩欧美高清视频在线观看 | 午夜精品视频在线 | 国产一性一爱一乱一交 | 久久99中文字幕 | 久久在线精品 | 视频一区在线播放 | av高清在线观看 | 综合婷婷丁香 | 91精品国产91久久久久福利 | 亚洲天天做| 在线国产一区二区三区 | 97色国产 | 亚洲欧美成aⅴ人在线观看 四虎在线观看 | 国产精品1000 | 91精品在线播放 | 婷婷精品在线视频 | 国产精品igao视频网入口 | 久久tv视频 | 免费一级毛毛片 | 日日干天天操 | 国产一区视频在线观看免费 | 日韩三级精品 | 国产精品久久久久久久妇 | 六月丁香在线观看 | 国产精品久久久久影院日本 | 午夜资源站| 亚洲精品在线观看中文字幕 | 激情视频一区二区三区 | 91黄站| 国产一线二线三线在线观看 | 草久在线观看视频 | 久青草影院| 六月丁香伊人 | 国产成人免费观看久久久 | 在线观看国产区 | 97小视频| 欧美日韩视频在线观看免费 | 亚洲国产人午在线一二区 | 亚洲永久av| 六月天综合网 | 日韩午夜剧场 | 国产探花在线看 | 亚洲四虎影院 | 最近中文字幕免费大全 | 欧美日韩久久不卡 | 成人免费精品 | 最近中文字幕mv免费高清在线 | 成人毛片在线视频 | 天天操天天干天天摸 | 久久伊人婷婷 | 免费观看91视频大全 | 久久影院中文字幕 | 日韩av在线一区二区 | 久久视频精品在线观看 | 国产精品一区久久久久 | 国产97色| 久久激情视频 久久 | 97av超碰| 91成品人影院 | 精品av在线播放 | 免费a视频 | 99久久精品国产一区二区成人 | 国产黄网站在线观看 | 久久五月婷婷丁香社区 | 不卡视频国产 | 一本一道久久a久久精品蜜桃 | 91 在线视频 | 日日婷婷夜日日天干 | 人人澡人人添人人爽一区二区 | 久久伦理电影 | 日韩区视频 | 黄色毛片视频免费 | 在线免费观看国产视频 | 伊人久久五月天 | 国产字幕在线观看 | 黄污网站在线观看 | 国产亚洲精品综合一区91 | 在线观看成人国产 | 国产精品免费久久久 | 欧美性久久久久久 | 国产精品久久久久久一区二区 | 中文字幕丝袜一区二区 | 成人免费视频播放 | 国产色综合 | 九九在线精品视频 | 六月丁香综合网 | 中文字幕在线免费看 | 欧美伦理一区二区 | 国产精品刺激对白麻豆99 | 在线影院 国内精品 | 国产亚洲精品无 | 国产精品系列在线观看 | 一级大片在线观看 | 亚洲经典视频在线观看 | 欧美久久久久久久久久久久久 | 一级电影免费在线观看 | 麻豆成人小视频 | 久久在线| 精品国产精品国产偷麻豆 | 91香蕉视频 mp4 | 免费在线色电影 | 久久久久电影 | 久久电影国产免费久久电影 | av成人免费在线观看 | 日韩成年视频 | 国产亚洲欧美在线视频 | 国产在线 一区二区三区 | 免费在线观看日韩视频 | 日韩黄色大片在线观看 | 国产小视频在线免费观看视频 | 中文字幕在线乱 | 一区二区三区在线观看免费视频 | bayu135国产精品视频 | 日韩高清二区 | 婷婷久久综合九色综合 | 成人小电影在线看 | 麻豆91精品视频 | av网站手机在线观看 | 亚洲精品色婷婷 | 国产精品你懂的在线观看 | 亚洲三级毛片 | 最近高清中文字幕 | 国产亚洲精品中文字幕 | 国产99在线播放 | 激情网色 | 97视频人人 | 亚洲电影久久久 | 国产在线超碰 | 中文字幕888 | 国产91免费在线观看 | 超碰公开在线观看 | 日韩艹| 天天夜夜亚洲 | 青青河边草观看完整版高清 | 久久黄色片子 | 嫩模bbw搡bbbb搡bbbb | a成人v在线 | 操操爽| 免费成人在线观看视频 | 看av免费网站| 久久综合给合久久狠狠色 | 人人爽人人爽人人爽学生一级 | 国产99久久久久 | 免费在线观看不卡av | 久草干 | 四川妇女搡bbbb搡bbbb搡 | 久久久久影视 | 成人在线超碰 | 99这里都是精品 | 99国产精品一区二区 | 不卡中文字幕av | 欧美精品亚洲精品日韩精品 | 97操操操| 国产精品乱码高清在线看 | 欧美激情精品久久久久久免费 | 欧美污网站| 国产精品爽爽爽 | 欧美一级淫片videoshd | 91精品人成在线观看 | 97福利社 | 96亚洲精品久久久蜜桃 | 欧美日韩高清一区二区 | 欧洲成人免费 | 欧美一级特黄高清视频 | 天天拍夜夜拍 | 国产精品视频观看 | 在线看av的网址 | 国产精品欧美久久久久天天影视 | 亚洲美女精品区人人人人 | 亚洲最大免费成人网 | av黄色一级片 | 中文字幕一区二区三区乱码在线 | 免费在线观看av片 | 永久免费的啪啪网站免费观看浪潮 | 欧美性爽爽 | 亚洲成人资源在线 | 美州a亚洲一视本频v色道 | 免费网站色 | 欧美最爽乱淫视频播放 | 国产色女人 | 亚洲第一区精品 | 成人免费视频免费观看 | 国产韩国精品一区二区三区 | 永久免费视频国产 | 91麻豆精品国产91久久久久久 | 永久免费在线 | 久久久精品免费观看 | 2020天天干天天操 | 欧美日韩在线免费观看视频 | 日韩欧美电影在线观看 | 日韩在线观看av | 日韩免费成人 | 国产精品视频全国免费观看 | 日本中文一级片 | 69国产成人综合久久精品欧美 | 国产 字幕 制服 中文 在线 | 久久99精品视频 | 一区二区三区精品在线视频 | 青草视频在线看 | 国产精品美女在线 | 九九久久久久久久久激情 | 成人网中文字幕 | 一级免费看 | 久久久国际精品 | 有没有在线观看av | 在线观看日韩精品视频 | 高清久久久久久 | 国产精品99久久久久的智能播放 | 婷婷丁香色综合狠狠色 | 日韩欧美在线观看一区 | 欧美日韩精品在线免费观看 | 欧美影院久久 | 国产一区二区视频在线 | 最新真实国产在线视频 | 激情视频久久 | 91精品国产自产老师啪 | 91麻豆看国产在线紧急地址 | 久久免费视频在线观看 | 亚洲欧洲国产日韩精品 | 伊人视频| 久久成人免费 | 少妇精品久久久一区二区免费 | 国产精品久久久久久高潮 | 日韩av成人在线观看 | 欧美性生活久久 | 国产高清日韩欧美 | 伊人电影在线观看 | 免费网址你懂的 | 在线免费观看黄色av | 国内综合精品午夜久久资源 | 天天射网| 狠狠综合网 | 亚洲区视频在线观看 | 欧美最新大片在线看 | 在线最新av | 久久综合婷婷综合 | 91成人网在线观看 | 日韩电影久久久 | 99久久精品久久久久久清纯 | 欧美精品亚洲精品日韩精品 | 91九色视频在线观看 | 在线观看日韩免费视频 | 中文字幕在线观看1 | 97成人资源站 | 夜夜操狠狠操 | 久久九九精品 | 激情导航 | 国产免费一区二区三区网站免费 | 欧美日韩中文字幕综合视频 | 91视频电影 | 青青河边草免费视频 | 综合网在线视频 | 日韩精品中文字幕在线播放 | 国产护士在线 | 欧美一区二区三区在线 | 成人黄色电影在线观看 | 青草草在线视频 | 久久久久久久久久久黄色 | 亚洲情感电影大片 | 欧美在线99 | 成人免费共享视频 | 日韩高清毛片 | 欧美大片mv免费 | 日韩在线观看一区二区三区 | 亚洲精品国产精品99久久 | 国产xxxx做受性欧美88 | 亚洲国产99| 91中文视频| 成人va视频 | 国产精品原创av片国产免费 | 国产成人福利在线观看 | 怡红院av久久久久久久 | 国产一区二区在线免费播放 | 美女网站一区 | 婷婷丁香五 | 91人人澡人人爽 | 国产精品国产三级国产 | av免费电影在线 | 国产成人三级在线观看 | 亚洲狠狠操 | se婷婷| 99久久精品一区二区成人 | 97精品伊人 | 日韩中文字幕免费在线观看 | 97伊人网 | 天天干天天干天天干天天干天天干天天干 | 美女网站免费福利视频 | 国产一级做a爱片久久毛片a | 99视频99| 超碰97久久 | 久久久黄视频 | 手机在线中文字幕 | 国产精品午夜在线 | 国产精品你懂的在线观看 | 激情欧美网 | 久久久久国产精品视频 | 欧美日韩三级 | 欧美日韩二三区 | 综合色亚洲 | 亚洲成人黄色在线观看 | 久久国产精品小视频 | 麻豆成人精品 | 福利一区二区三区四区 | 欧美污污网站 | www91在线| 九九免费在线看完整版 | 九九九热| 国产在线播放一区二区 | 菠萝菠萝蜜在线播放 | 国产无遮挡又黄又爽在线观看 | 日韩理论电影网 | 中文字幕乱码电影 | 精品国产美女在线 | 欧美极度另类性三渗透 | 免费av片在线 | 亚洲国产视频直播 | 中文字幕网站 | 三三级黄色片之日韩 | 国产精品大全 | 天堂网一区 | 成人av在线亚洲 | 91尤物在线播放 | 又黄又爽又无遮挡的视频 | 欧美日韩国产在线精品 |