久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > pytorch >内容正文

pytorch

【深度学习】搞懂 Vision Transformer 原理和代码,看这篇技术综述就够了

發(fā)布時間:2025/3/12 pytorch 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【深度学习】搞懂 Vision Transformer 原理和代码,看这篇技术综述就够了 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

??作者丨科技猛獸

編輯丨極市平臺

導讀

?

本文對Vision Transformer的原理和代碼進行了非常全面詳細的解讀,一切從Self-attention開始、Transformer的實現(xiàn)和代碼以及Transformer+Detection:引入視覺領域的首創(chuàng)DETR。>>加入極市CV技術交流群,走在計算機視覺的最前沿

Transformer 是 Google 的團隊在 2017 年提出的一種 NLP 經典模型,現(xiàn)在比較火熱的 Bert 也是基于 Transformer。Transformer 模型使用了 Self-Attention 機制,不采用RNN順序結構,使得模型可以并行化訓練,而且能夠擁有全局信息。本文將對Vision Transformer的原理和代碼進行非常全面的解讀??紤]到每篇文章字數(shù)的限制,每一篇文章將按照目錄的編排包含三個小節(jié),而且這個系列會隨著Vision Transformer的發(fā)展而長期更新。

目錄

(每篇文章對應一個Section,目錄持續(xù)更新。)

  • Section 1

1 一切從Self-attention開始
1.1 處理Sequence數(shù)據(jù)的模型
1.2 Self-attention
1.3 Multi-head Self-attention
1.4 Positional Encoding

2 Transformer的實現(xiàn)和代碼解讀 (NIPS2017)
(來自Google Research, Brain Team)
2.1 Transformer原理分析
2.2 Transformer代碼解讀

3 Transformer+Detection:引入視覺領域的首創(chuàng)DETR (ECCV2020)
(來自Facebook AI)
3.1 DETR原理分析
3.2 DETR代碼解讀

  • Section 2

4 Transformer+Detection:Deformable DETR:可變形的Transformer (ICLR2021)
(來自商湯代季峰老師組)
4.1 Deformable DETR原理分析
4.2 Deformable DETR代碼解讀

5 Transformer+Classification:用于分類任務的Transformer (ICLR2021)
(來自Google Research, Brain Team)
5.1 ViT原理分析
5.2 ViT代碼解讀

6 Transformer+Image Processing:IPT:用于底層視覺任務的Transformer
(來自北京華為諾亞方舟實驗室)
6.1 IPT原理分析

  • Section 3

7 Transformer+Segmentation:SETR:基于Transformer 的語義分割
(來自復旦大學,騰訊優(yōu)圖等)
7.1 SETR原理分析

8 Transformer+GAN:VQGAN:實現(xiàn)高分辨率的圖像生成
(來自德國海德堡大學)
8.1 VQGAN原理分析
8.2 VQGAN代碼解讀

9 Transformer+Distillation:DeiT:高效圖像Transformer
(來自Facebook AI)
9.1 DeiT原理分析

1 一切從Self-attention開始

  • 1.1 處理Sequence數(shù)據(jù)的模型:

Transformer是一個Sequence to Sequence model,特別之處在于它大量用到了self-attention。

要處理一個Sequence,最常想到的就是使用RNN,它的輸入是一串vector sequence,輸出是另一串vector sequence,如下圖1左所示。

如果假設是一個single directional的RNN,那當輸出?時,默認?都已經看過了。如果假設是一個bi-directional的RNN,那當輸出?任意時,默認?都已經看過了。RNN非常擅長于處理input是一個sequence的狀況。

那RNN有什么樣的問題呢?它的問題就在于:RNN很不容易并行化 (hard to parallel)。

為什么說RNN很不容易并行化呢?假設在single directional的RNN的情形下,你今天要算出?,就必須要先看?再看?再看?再看?,所以這個過程很難平行處理。

所以今天就有人提出把CNN拿來取代RNN,如下圖1右所示。其中,橘色的三角形表示一個filter,每次掃過3個向量?,掃過一輪以后,就輸出了一排結果,使用橘色的小圓點表示。

這是第一個橘色的filter的過程,還有其他的filter,比如圖2中的黃色的filter,它經歷著與橘色的filter相似的過程,又輸出一排結果,使用黃色的小圓點表示。

圖1:處理Sequence數(shù)據(jù)的模型圖2:處理Sequence數(shù)據(jù)的模型

所以,用CNN,你確實也可以做到跟RNN的輸入輸出類似的關系,也可以做到輸入是一個sequence,輸出是另外一個sequence。

但是,表面上CNN和RNN可以做到相同的輸入和輸出,但是CNN只能考慮非常有限的內容。比如在我們右側的圖中CNN的filter只考慮了3個vector,不像RNN可以考慮之前的所有vector。但是CNN也不是沒有辦法考慮很長時間的dependency的,你只需要堆疊filter,多堆疊幾層,上層的filter就可以考慮比較多的資訊,比如,第二層的filter (藍色的三角形)看了6個vector,所以,只要疊很多層,就能夠看很長時間的資訊。

而CNN的一個好處是:它是可以并行化的 (can parallel),不需要等待紅色的filter算完,再算黃色的filter。但是必須要疊很多層filter,才可以看到長時的資訊。所以今天有一個想法:self-attention,如下圖3所示,目的是使用self-attention layer取代RNN所做的事情。

圖3:You can try to replace any thing that has been done by RNNwith self attention

所以重點是:我們有一種新的layer,叫self-attention,它的輸入和輸出和RNN是一模一樣的,輸入一個sequence,輸出一個sequence,它的每一個輸出?都看過了整個的輸入sequence,這一點與bi-directional RNN相同。但是神奇的地方是:它的每一個輸出?可以并行化計算。

  • 1.2 Self-attention:

那么self-attention具體是怎么做的呢?

圖4:self-attention具體是怎么做的?

首先假設我們的input是圖4的?,是一個sequence,每一個input (vector)先乘上一個矩陣?得到embedding,即向量?。接著這個embedding進入self-attention層,每一個向量?分別乘上3個不同的transformation matrix?,以向量?為例,分別得到3個不同的向量?。

圖5:self-attention具體是怎么做的?

接下來使用每個query?去對每個key?做attention,attention就是匹配這2個向量有多接近,比如我現(xiàn)在要對?和?做attention,我就可以把這2個向量做scaled inner product,得到?。接下來你再拿?和?做attention,得到?,你再拿?和?做attention,得到?,你再拿?和?做attention,得到?。那這個scaled inner product具體是怎么計算的呢?

式中,?是?跟?的維度。因為?的數(shù)值會隨著dimension的增大而增大,所以要除以?的值,相當于歸一化的效果。

接下來要做的事如圖6所示,把計算得到的所有?值取?操作。

圖6:self-attention具體是怎么做的?

取完?操作以后,我們得到了?,我們用它和所有的?值進行相乘。具體來講,把?乘上?,把?乘上?,把?乘上?,把?乘上?,把結果通通加起來得到?,所以,今天在產生?的過程中用了整個sequence的資訊 (Considering the whole sequence)。如果要考慮local的information,則只需要學習出相應的?,?就不再帶有那個對應分支的信息了;如果要考慮global的information,則只需要學習出相應的?,?就帶有全部的對應分支的信息了。

圖7:self-attention具體是怎么做的?

同樣的方法,也可以計算出?,如下圖8所示,?就是拿query?去對其他的?做attention,得到?,再與value值?相乘取weighted sum得到的。

圖8:self-attention具體是怎么做的?

經過了以上一連串計算,self-attention layer做的事情跟RNN是一樣的,只是它可以并行的得到layer輸出的結果,如圖9所示。現(xiàn)在我們要用矩陣表示上述的計算過程。

圖9:self-attention的效果

首先輸入的embedding是?,然后用?乘以transformation matrix?得到?,它的每一列代表著一個vector?。同理,用?乘以transformation matrix?得到?,它的每一列代表著一個vector?。用?乘以transformation matrix?得到?,它的每一列代表著一個vector?。

圖10:self-attention的矩陣計算過程

接下來是?與?的attention過程,我們可以把vector?橫過來變成行向量,與列向量?做內積,這里省略了?。這樣,?就成為了?的矩陣,它由4個行向量拼成的矩陣和4個列向量拼成的矩陣做內積得到,如圖11所示。

在得到?以后,如上文所述,要得到?, 就要使用?分別與?相乘再求和得到,所以?要再左乘?矩陣。

圖11:self-attention的矩陣計算過程

到這里你會發(fā)現(xiàn)這個過程可以被表示為,如圖12所示:輸入矩陣?分別乘上3個不同的矩陣?得到3個中間矩陣?。它們的維度是相同的。把?轉置之后與?相乘得到Attention矩陣?,代表每一個位置兩兩之間的attention。再將它取?操作得到?,最后將它乘以?矩陣得到輸出vector?。

圖12:self-attention就是一堆矩陣乘法,可以實現(xiàn)GPU加速
  • 1.3 Multi-head Self-attention:

還有一種multi-head的self-attention,以2個head的情況為例:由?生成的?進一步乘以2個轉移矩陣變?yōu)?和?,同理由?生成的?進一步乘以2個轉移矩陣變?yōu)?和?,由?生成的?進一步乘以2個轉移矩陣變?yōu)?和?。接下來?再與?做attention,得到weighted sum的權重?,再與?做weighted sum得到最終的?。同理得到??,F(xiàn)在我們有了?和?,可以把它們concat起來,再通過一個transformation matrix調整維度,使之與剛才的?維度一致(這步如圖13所示)。

圖13:multi-head self-attention圖13:調整b的維度

從下圖14可以看到 Multi-Head Attention 包含多個 Self-Attention 層,首先將輸入?分別傳遞到 2個不同的 Self-Attention 中,計算得到 2 個輸出結果。得到2個輸出矩陣之后,Multi-Head Attention 將它們拼接在一起 (Concat),然后傳入一個Linear層,得到 Multi-Head Attention 最終的輸出???梢钥吹?Multi-Head Attention 輸出的矩陣?與其輸入的矩陣?的維度是一樣的。

圖14:multi-head self-attention

這里有一組Multi-head Self-attention的解果,其中綠色部分是一組query和key,紅色部分是另外一組query和key,可以發(fā)現(xiàn)綠色部分其實更關注global的信息,而紅色部分其實更關注local的信息。

圖15:Multi-head Self-attention的不同head分別關注了global和local的訊息
  • 1.4 Positional Encoding:

以上是multi-head self-attention的原理,但是還有一個問題是:現(xiàn)在的self-attention中沒有位置的信息,一個單詞向量的“近在咫尺”位置的單詞向量和“遠在天涯”位置的單詞向量效果是一樣的,沒有表示位置的信息(No position information in self attention)。所以你輸入"A打了B"或者"B打了A"的效果其實是一樣的,因為并沒有考慮位置的信息。所以在self-attention原來的paper中,作者為了解決這個問題所做的事情是如下圖16所示:

圖16:self-attention中的位置編碼

具體的做法是:給每一個位置規(guī)定一個表示位置信息的向量?,讓它與?加在一起之后作為新的?參與后面的運算過程,但是這個向量?是由人工設定的,而不是神經網絡學習出來的。每一個位置都有一個不同的?。

那到這里一個自然而然的問題是:為什么是?與?相加?為什么不是concatenate?加起來以后,原來表示位置的資訊不就混到?里面去了嗎?不就很難被找到了嗎?

這里提供一種解答這個問題的思路:

如圖15所示,我們先給每一個位置的?append一個one-hot編碼的向量?,得到一個新的輸入向量?,這個向量作為新的輸入,乘以一個transformation matrix?。那么:

所以,與?相加就等同于把原來的輸入?concat一個表示位置的獨熱編碼?,再做transformation。

這個與位置編碼乘起來的矩陣?是手工設計的,如圖17所示。

圖17:與位置編碼乘起來的轉移矩陣WP

Transformer 中除了單詞的 Embedding,還需要使用位置 Embedding 表示單詞出現(xiàn)在句子中的位置。因為 Transformer 不采用 RNN 的結構,而是使用全局信息,不能利用單詞的順序信息,而這部分信息對于 NLP 來說非常重要。所以 Transformer 中使用位置 Embedding 保存單詞在序列中的相對或絕對位置。

位置 Embedding 用 PE表示,PE 的維度與單詞 Embedding 是一樣的。PE 可以通過訓練得到,也可以使用某種公式計算得到。在 Transformer 中采用了后者,計算公式如下:

式中,?表示token在sequence中的位置,例如第一個token "我" 的?。

,或者準確意義上是?和?表示了Positional Encoding的維度,的取值范圍是:?。所以當?為1時,對應的Positional Encoding可以寫成:

式中,?。底數(shù)是10000。為什么要使用10000呢,這個就類似于玄學了,原論文中完全沒有提啊,這里不得不說說論文的readability的問題,即便是很多高引的文章,最基本的內容都討論不清楚,所以才出現(xiàn)像上面提問里的討論,說實話這些論文還遠遠沒有做到easy to follow。這里我給出一個假想:是一個比較接近1的數(shù)(1.018),如果用100000,則是1.023。這里只是猜想一下,其實大家應該完全可以使用另一個底數(shù)。

這個式子的好處是:

  • 每個位置有一個唯一的positional encoding。

  • 使?能夠適應比訓練集里面所有句子更長的句子,假設訓練集里面最長的句子是有 20 個單詞,突然來了一個長度為 21 的句子,則使用公式計算的方法可以計算出第 21 位的 Embedding。

  • 可以讓模型容易地計算出相對位置,對于固定長度的間距?,任意位置的?都可以被?的線性函數(shù)表示,因為三角函數(shù)特性:

接下來我們看看self-attention在sequence2sequence model里面是怎么使用的,我們可以把Encoder-Decoder中的RNN用self-attention取代掉。

圖18:Seq2seq with Attention

2 Transformer的實現(xiàn)和代碼解讀

  • 2.1 Transformer原理分析:

圖19:Transformer

Encoder:

這個圖19講的是一個seq2seq的model,左側為 Encoder block,右側為 Decoder block。紅色圈中的部分為Multi-Head Attention,是由多個Self-Attention組成的,可以看到 Encoder block 包含一個 Multi-Head Attention,而 Decoder block 包含兩個 Multi-Head Attention (其中有一個用到 Masked)。Multi-Head Attention 上方還包括一個 Add & Norm 層,Add 表示殘差連接 (Residual Connection) 用于防止網絡退化,Norm 表示 Layer Normalization,用于對每一層的激活值進行歸一化。比如說在Encoder Input處的輸入是機器學習,在Decoder Input處的輸入是<BOS>,輸出是machine。再下一個時刻在Decoder Input處的輸入是machine,輸出是learning。不斷重復知道輸出是句點(.)代表翻譯結束。

接下來我們看看這個Encoder和Decoder里面分別都做了什么事情,先看左半部分的Encoder:首先輸入?通過一個Input Embedding的轉移矩陣?變?yōu)榱艘粋€張量,即上文所述的?,再加上一個表示位置的Positional Encoding?,得到一個張量,去往后面的操作。

它進入了這個綠色的block,這個綠色的block會重復?次。這個綠色的block里面有什么呢?它的第1層是一個上文講的multi-head的attention。你現(xiàn)在一個sequence,經過一個multi-head的attention,你會得到另外一個sequence?。

下一個Layer是Add & Norm,這個意思是說:把multi-head的attention的layer的輸入?和輸出?進行相加以后,再做Layer Normalization,至于Layer Normalization和我們熟悉的Batch Normalization的區(qū)別是什么,請參考圖20和21。

圖20:不同Normalization方法的對比

其中,Batch Normalization和Layer Normalization的對比可以概括為圖20,Batch Normalization強行讓一個batch的數(shù)據(jù)的某個channel的?,而Layer Normalization讓一個數(shù)據(jù)的所有channel的?。

圖21:Batch Normalization和Layer Normalization的對比

接著是一個Feed Forward的前饋網絡和一個Add & Norm Layer。

所以,這一個綠色的block的前2個Layer操作的表達式為:

這一個綠色的block的后2個Layer操作的表達式為:

所以Transformer的Encoder的整體操作為:

Decoder:

現(xiàn)在來看Decoder的部分,輸入包括2部分,下方是前一個time step的輸出的embedding,即上文所述的?,再加上一個表示位置的Positional Encoding?,得到一個張量,去往后面的操作。它進入了這個綠色的block,這個綠色的block會重復?次。這個綠色的block里面有什么呢?

首先是Masked Multi-Head Self-attention,masked的意思是使attention只會attend on已經產生的sequence,這個很合理,因為還沒有產生出來的東西不存在,就無法做attention。

輸出是: 對應?位置的輸出詞的概率分布。

輸入是:?的輸出對應?位置decoder的輸出。所以中間的attention不是self-attention,它的Key和Value來自encoder,Query來自上一位置?的輸出。

解碼:這里要特別注意一下,編碼可以并行計算,一次性全部Encoding出來,但解碼不是一次把所有序列解出來的,而是像?一樣一個一個解出來的,因為要用上一個位置的輸入當作attention的query。

明確了解碼過程之后最上面的圖就很好懂了,這里主要的不同就是新加的另外要說一下新加的attention多加了一個mask,因為訓練時的output都是Ground Truth,這樣可以確保預測第?個位置時不會接觸到未來的信息。

  • 包含兩個 Multi-Head Attention 層。

  • 第一個 Multi-Head Attention 層采用了 Masked 操作。

  • 第二個 Multi-Head Attention 層的Key,Value矩陣使用 Encoder 的編碼信息矩陣?進行計算,而Query使用上一個 Decoder block 的輸出計算。

  • 最后有一個 Softmax 層計算下一個翻譯單詞的概率。

下面詳細介紹下Masked Multi-Head Self-attention的具體操作,Masked在Scale操作之后,softmax操作之前。

圖22:Masked在Scale操作之后,softmax操作之前

因為在翻譯的過程中是順序翻譯的,即翻譯完第?個單詞,才可以翻譯第?個單詞。通過 Masked 操作可以防止第?個單詞知道第?個單詞之后的信息。下面以 "我有一只貓" 翻譯成 "I have a cat" 為例,了解一下 Masked 操作。在 Decoder 的時候,是需要根據(jù)之前的翻譯,求解當前最有可能的翻譯,如下圖所示。首先根據(jù)輸入 "<Begin>" 預測出第一個單詞為 "I",然后根據(jù)輸入 "<Begin> I" 預測下一個單詞 "have"。

Decoder 可以在訓練的過程中使用 Teacher Forcing 并且并行化訓練,即將正確的單詞序列 (<Begin> I have a cat) 和對應輸出 (I have a cat <end>) 傳遞到 Decoder。那么在預測第?個輸出時,就要將第? 之后的單詞掩蓋住,注意 Mask 操作是在 Self-Attention 的 Softmax 之前使用的,下面用 0 1 2 3 4 5 分別表示 "<Begin> I have a cat <end>"。

圖23:Decoder過程

注意這里transformer模型訓練和測試的方法不同:

測試時:

  • 輸入<Begin>,解碼器輸出 I 。

  • 輸入前面已經解碼的<Begin>和 I,解碼器輸出have。

  • 輸入已經解碼的<Begin>,I, have, a, cat,解碼器輸出解碼結束標志位<end>,每次解碼都會利用前面已經解碼輸出的所有單詞嵌入信息。

  • Transformer測試時的解碼過程:

    訓練時:

    不采用上述類似RNN的方法 一個一個目標單詞嵌入向量順序輸入訓練,想采用類似編碼器中的矩陣并行算法,一步就把所有目標單詞預測出來。要實現(xiàn)這個功能就可以參考編碼器的操作,把目標單詞嵌入向量組成矩陣一次輸入即可。即:并行化訓練。

    但是在解碼have時候,不能利用到后面單詞a和cat的目標單詞嵌入向量信息,否則這就是作弊(測試時候不可能能未卜先知)。為此引入mask。具體是:在解碼器中,self-attention層只被允許處理輸出序列中更靠前的那些位置,在softmax步驟前,它會把后面的位置給隱去。

    Masked Multi-Head Self-attention的具體操作 如圖24所示。

    Step1: 輸入矩陣包含 "<Begin> I have a cat" (0, 1, 2, 3, 4) 五個單詞的表示向量,Mask是一個 5×5 的矩陣。在Mask可以發(fā)現(xiàn)單詞 0 只能使用單詞 0 的信息,而單詞 1 可以使用單詞 0, 1 的信息,即只能使用之前的信息。輸入矩陣?經過transformation matrix變?yōu)?個矩陣:Query,Key?和Value?。

    Step2:?得到 Attention矩陣?,此時先不急于做softmax的操作,而是先于一個?矩陣相乘,使得attention矩陣的有些位置 歸0,得到Masked Attention矩陣?。?矩陣是個下三角矩陣,為什么這樣設計?是因為想在計算?矩陣的某一行時,只考慮它前面token的作用。即:在計算?的第一行時,刻意地把?矩陣第一行的后面幾個元素屏蔽掉,只考慮?。在產生have這個單詞時,只考慮 I,不考慮之后的have a cat,即只會attend on已經產生的sequence,這個很合理,因為還沒有產生出來的東西不存在,就無法做attention。

    Step3: Masked Attention矩陣進行 Softmax,每一行的和都為 1。但是單詞 0 在單詞 1, 2, 3, 4 上的 attention score 都為 0。得到的結果再與?矩陣相乘得到最終的self-attention層的輸出結果?。

    Step4:?只是某一個head的結果,將多個head的結果concat在一起之后再最后進行Linear Transformation得到最終的Masked Multi-Head Self-attention的輸出結果?。

    圖24:Masked Multi-Head Self-attention的具體操作

    第1個Masked Multi-Head Self-attention的?均來自Output Embedding。

    第2個Multi-Head Self-attention的?來自第1個Self-attention layer的輸出,?來自Encoder的輸出。

    為什么這么設計? 這里提供一種個人的理解:

    來自Transformer Encoder的輸出,所以可以看做句子(Sequence)/圖片(image)內容信息(content,比如句意是:"我有一只貓",圖片內容是:"有幾輛車,幾個人等等")。

    表達了一種訴求:希望得到什么,可以看做引導信息(guide)

    通過Multi-Head Self-attention結合在一起的過程就相當于是把我們需要的內容信息指導表達出來。

    Decoder的最后是Softmax 預測輸出單詞。因為 Mask 的存在,使得單詞 0 的輸出?只包含單詞 0 的信息。Softmax 根據(jù)輸出矩陣的每一行預測下一個單詞,如下圖25所示。

    圖25:Softmax 根據(jù)輸出矩陣的每一行預測下一個單詞

    如下圖26所示為Transformer的整體結構。

    圖26:Transformer的整體結構
    • 2.2 Transformer代碼解讀:

    代碼來自:

    https://github.com/jadore801120/attention-is-all-you-need-pytorch

    ScaledDotProductAttention:
    實現(xiàn)的是圖22的操作,先令?,再對結果按位乘以?矩陣,再做?操作,最后的結果與?相乘,得到self-attention的輸出。

    class ScaledDotProductAttention(nn.Module): ''' Scaled Dot-Product Attention '''def __init__(self, temperature, attn_dropout=0.1): super().__init__() self.temperature = temperature self.dropout = nn.Dropout(attn_dropout)def forward(self, q, k, v, mask=None):attn = torch.matmul(q / self.temperature, k.transpose(2, 3))if mask is not None: attn = attn.masked_fill(mask == 0, -1e9)attn = self.dropout(F.softmax(attn, dim=-1)) output = torch.matmul(attn, v)return output, attn

    位置編碼 PositionalEncoding:
    實現(xiàn)的是式(5)的位置編碼。

    class PositionalEncoding(nn.Module):def __init__(self, d_hid, n_position=200): super(PositionalEncoding, self).__init__()# Not a parameter self.register_buffer('pos_table', self._get_sinusoid_encoding_table(n_position, d_hid))def _get_sinusoid_encoding_table(self, n_position, d_hid): ''' Sinusoid position encoding table ''' # TODO: make it with torch instead of numpydef get_position_angle_vec(position): return [position / np.power(10000, 2 * (hid_j // 2) / d_hid) for hid_j in range(d_hid)]sinusoid_table = np.array([get_position_angle_vec(pos_i) for pos_i in range(n_position)]) sinusoid_table[:, 0::2] = np.sin(sinusoid_table[:, 0::2]) # dim 2i sinusoid_table[:, 1::2] = np.cos(sinusoid_table[:, 1::2]) # dim 2i+1return torch.FloatTensor(sinusoid_table).unsqueeze(0)#(1,N,d)def forward(self, x): # x(B,N,d) return x + self.pos_table[:, :x.size(1)].clone().detach()

    MultiHeadAttention:
    實現(xiàn)圖13,14的多頭self-attention。

    class MultiHeadAttention(nn.Module): ''' Multi-Head Attention module '''def __init__(self, n_head, d_model, d_k, d_v, dropout=0.1): super().__init__()self.n_head = n_head self.d_k = d_k self.d_v = d_vself.w_qs = nn.Linear(d_model, n_head * d_k, bias=False) self.w_ks = nn.Linear(d_model, n_head * d_k, bias=False) self.w_vs = nn.Linear(d_model, n_head * d_v, bias=False) self.fc = nn.Linear(n_head * d_v, d_model, bias=False)self.attention = ScaledDotProductAttention(temperature=d_k ** 0.5)self.dropout = nn.Dropout(dropout) self.layer_norm = nn.LayerNorm(d_model, eps=1e-6)def forward(self, q, k, v, mask=None):d_k, d_v, n_head = self.d_k, self.d_v, self.n_head sz_b, len_q, len_k, len_v = q.size(0), q.size(1), k.size(1), v.size(1)residual = q# Pass through the pre-attention projection: b x lq x (n*dv) # Separate different heads: b x lq x n x dv q = self.w_qs(q).view(sz_b, len_q, n_head, d_k) k = self.w_ks(k).view(sz_b, len_k, n_head, d_k) v = self.w_vs(v).view(sz_b, len_v, n_head, d_v)# Transpose for attention dot product: b x n x lq x dv q, k, v = q.transpose(1, 2), k.transpose(1, 2), v.transpose(1, 2)if mask is not None: mask = mask.unsqueeze(1) # For head axis broadcasting.q, attn = self.attention(q, k, v, mask=mask)#q (sz_b,n_head,N=len_q,d_k) #k (sz_b,n_head,N=len_k,d_k) #v (sz_b,n_head,N=len_v,d_v)# Transpose to move the head dimension back: b x lq x n x dv # Combine the last two dimensions to concatenate all the heads together: b x lq x (n*dv) q = q.transpose(1, 2).contiguous().view(sz_b, len_q, -1)#q (sz_b,len_q,n_head,N * d_k) q = self.dropout(self.fc(q)) q += residualq = self.layer_norm(q)return q, attn

    前向傳播Feed Forward Network:

    class PositionwiseFeedForward(nn.Module): ''' A two-feed-forward-layer module '''def __init__(self, d_in, d_hid, dropout=0.1): super().__init__() self.w_1 = nn.Linear(d_in, d_hid) # position-wise self.w_2 = nn.Linear(d_hid, d_in) # position-wise self.layer_norm = nn.LayerNorm(d_in, eps=1e-6) self.dropout = nn.Dropout(dropout)def forward(self, x):residual = xx = self.w_2(F.relu(self.w_1(x))) x = self.dropout(x) x += residualx = self.layer_norm(x)return x

    EncoderLayer:
    實現(xiàn)圖26中的一個EncoderLayer,具體的結構如圖19所示。

    class EncoderLayer(nn.Module): ''' Compose with two layers '''def __init__(self, d_model, d_inner, n_head, d_k, d_v, dropout=0.1): super(EncoderLayer, self).__init__() self.slf_attn = MultiHeadAttention(n_head, d_model, d_k, d_v, dropout=dropout) self.pos_ffn = PositionwiseFeedForward(d_model, d_inner, dropout=dropout)def forward(self, enc_input, slf_attn_mask=None): enc_output, enc_slf_attn = self.slf_attn( enc_input, enc_input, enc_input, mask=slf_attn_mask) enc_output = self.pos_ffn(enc_output) return enc_output, enc_slf_attn

    DecoderLayer:
    實現(xiàn)圖26中的一個DecoderLayer,具體的結構如圖19所示。

    class DecoderLayer(nn.Module): ''' Compose with three layers '''def __init__(self, d_model, d_inner, n_head, d_k, d_v, dropout=0.1): super(DecoderLayer, self).__init__() self.slf_attn = MultiHeadAttention(n_head, d_model, d_k, d_v, dropout=dropout) self.enc_attn = MultiHeadAttention(n_head, d_model, d_k, d_v, dropout=dropout) self.pos_ffn = PositionwiseFeedForward(d_model, d_inner, dropout=dropout)def forward( self, dec_input, enc_output, slf_attn_mask=None, dec_enc_attn_mask=None): dec_output, dec_slf_attn = self.slf_attn( dec_input, dec_input, dec_input, mask=slf_attn_mask) dec_output, dec_enc_attn = self.enc_attn( dec_output, enc_output, enc_output, mask=dec_enc_attn_mask) dec_output = self.pos_ffn(dec_output) return dec_output, dec_slf_attn, dec_enc_attn

    Encoder:
    實現(xiàn)圖26,19左側的Encoder:

    class Encoder(nn.Module): ''' A encoder model with self attention mechanism. '''def __init__( self, n_src_vocab, d_word_vec, n_layers, n_head, d_k, d_v, d_model, d_inner, pad_idx, dropout=0.1, n_position=200):super().__init__()self.src_word_emb = nn.Embedding(n_src_vocab, d_word_vec, padding_idx=pad_idx) self.position_enc = PositionalEncoding(d_word_vec, n_position=n_position) self.dropout = nn.Dropout(p=dropout) self.layer_stack = nn.ModuleList([ EncoderLayer(d_model, d_inner, n_head, d_k, d_v, dropout=dropout) for _ in range(n_layers)]) self.layer_norm = nn.LayerNorm(d_model, eps=1e-6)def forward(self, src_seq, src_mask, return_attns=False):enc_slf_attn_list = []# -- Forwardenc_output = self.dropout(self.position_enc(self.src_word_emb(src_seq))) enc_output = self.layer_norm(enc_output)for enc_layer in self.layer_stack: enc_output, enc_slf_attn = enc_layer(enc_output, slf_attn_mask=src_mask) enc_slf_attn_list += [enc_slf_attn] if return_attns else []if return_attns: return enc_output, enc_slf_attn_list return enc_output,

    Decoder:
    實現(xiàn)圖26,19右側的Decoder:

    class Decoder(nn.Module): ''' A decoder model with self attention mechanism. '''def forward(self, trg_seq, trg_mask, enc_output, src_mask, return_attns=False):dec_slf_attn_list, dec_enc_attn_list = [], []# -- Forward dec_output = self.dropout(self.position_enc(self.trg_word_emb(trg_seq))) dec_output = self.layer_norm(dec_output)for dec_layer in self.layer_stack: dec_output, dec_slf_attn, dec_enc_attn = dec_layer( dec_output, enc_output, slf_attn_mask=trg_mask, dec_enc_attn_mask=src_mask) dec_slf_attn_list += [dec_slf_attn] if return_attns else [] dec_enc_attn_list += [dec_enc_attn] if return_attns else []if return_attns: return dec_output, dec_slf_attn_list, dec_enc_attn_list return dec_output,

    整體結構:
    實現(xiàn)圖26,19整體的Transformer:

    class Transformer(nn.Module): ''' A sequence to sequence model with attention mechanism. '''def __init__( self, n_src_vocab, n_trg_vocab, src_pad_idx, trg_pad_idx, d_word_vec=512, d_model=512, d_inner=2048, n_layers=6, n_head=8, d_k=64, d_v=64, dropout=0.1, n_position=200, trg_emb_prj_weight_sharing=True, emb_src_trg_weight_sharing=True):super().__init__()self.src_pad_idx, self.trg_pad_idx = src_pad_idx, trg_pad_idxself.encoder = Encoder( n_src_vocab=n_src_vocab, n_position=n_position, d_word_vec=d_word_vec, d_model=d_model, d_inner=d_inner, n_layers=n_layers, n_head=n_head, d_k=d_k, d_v=d_v, pad_idx=src_pad_idx, dropout=dropout)self.decoder = Decoder( n_trg_vocab=n_trg_vocab, n_position=n_position, d_word_vec=d_word_vec, d_model=d_model, d_inner=d_inner, n_layers=n_layers, n_head=n_head, d_k=d_k, d_v=d_v, pad_idx=trg_pad_idx, dropout=dropout)self.trg_word_prj = nn.Linear(d_model, n_trg_vocab, bias=False)for p in self.parameters(): if p.dim() > 1: nn.init.xavier_uniform_(p) assert d_model == d_word_vec, \ 'To facilitate the residual connections, \ the dimensions of all module outputs shall be the same.'self.x_logit_scale = 1. if trg_emb_prj_weight_sharing: # Share the weight between target word embedding & last dense layer self.trg_word_prj.weight = self.decoder.trg_word_emb.weight self.x_logit_scale = (d_model ** -0.5)if emb_src_trg_weight_sharing: self.encoder.src_word_emb.weight = self.decoder.trg_word_emb.weightdef forward(self, src_seq, trg_seq):src_mask = get_pad_mask(src_seq, self.src_pad_idx) trg_mask = get_pad_mask(trg_seq, self.trg_pad_idx) & get_subsequent_mask(trg_seq)enc_output, *_ = self.encoder(src_seq, src_mask) dec_output, *_ = self.decoder(trg_seq, trg_mask, enc_output, src_mask) seq_logit = self.trg_word_prj(dec_output) * self.x_logit_scalereturn seq_logit.view(-1, seq_logit.size(2))

    產生Mask:

    def get_pad_mask(seq, pad_idx): return (seq != pad_idx).unsqueeze(-2)def get_subsequent_mask(seq): ''' For masking out the subsequent info. ''' sz_b, len_s = seq.size() subsequent_mask = (1 - torch.triu( torch.ones((1, len_s, len_s), device=seq.device), diagonal=1)).bool() return subsequent_mask

    src_mask = get_pad_mask(src_seq, self.src_pad_idx)
    用于產生Encoder的Mask,它是一列Bool值,負責把標點mask掉。
    trg_mask = get_pad_mask(trg_seq, self.trg_pad_idx) & get_subsequent_mask(trg_seq)
    用于產生Decoder的Mask。它是一個矩陣,如圖24中的Mask所示,功能已在上文介紹。

    3 Transformer+Detection:引入視覺領域的首創(chuàng)DETR

    論文名稱:End-to-End Object Detection with Transformers

    論文地址:

    https://arxiv.org/abs/2005.12872arxiv.org

    • 3.1 DETR原理分析:

    網絡架構部分解讀

    本文的任務是Object detection,用到的工具是Transformers,特點是End-to-end。

    目標檢測的任務是要去預測一系列的Bounding Box的坐標以及Label, 現(xiàn)代大多數(shù)檢測器通過定義一些proposal,anchor或者windows,把問題構建成為一個分類和回歸問題來間接地完成這個任務。文章所做的工作,就是將transformers運用到了object detection領域,取代了現(xiàn)在的模型需要手工設計的工作,并且取得了不錯的結果。在object detection上DETR準確率和運行時間上和Faster RCNN相當;將模型 generalize 到 panoptic segmentation 任務上,DETR表現(xiàn)甚至還超過了其他的baseline。DETR第一個使用End to End的方式解決檢測問題,解決的方法是把檢測問題視作是一個set prediction problem,如下圖27所示。

    圖27:DETR結合CNN和Transformer的結構,并行實現(xiàn)預測

    網絡的主要組成是CNN和Transformer,Transformer借助第1節(jié)講到的self-attention機制,可以顯式地對一個序列中的所有elements兩兩之間的interactions進行建模,使得這類transformer的結構非常適合帶約束的set prediction的問題。DETR的特點是:一次預測,端到端訓練,set loss function和二分匹配。

    文章的主要有兩個關鍵的部分。

    第一個是用transformer的encoder-decoder架構一次性生成?個box prediction。其中?是一個事先設定的、比遠遠大于image中object個數(shù)的一個整數(shù)。

    第二個是設計了bipartite matching loss,基于預測的boxex和ground truth boxes的二分圖匹配計算loss的大小,從而使得預測的box的位置和類別更接近于ground truth。

    DETR整體結構可以分為四個部分:backbone,encoder,decoder和FFN,如下圖28所示,以下分別解釋這四個部分:

    圖28:DETR整體結構

    1 首先看backbone: CNN backbone處理?維的圖像,把它轉換為維的feature map(一般來說?或),backbone只做這一件事。

    2 再看encoder: encoder的輸入是維的feature map,接下來依次進行以下過程:

    • 通道數(shù)壓縮: 先用?convolution處理,將channels數(shù)量從?壓縮到?,即得到維的新feature map。

    • 轉化為序列化數(shù)據(jù): 將空間的維度(高和寬)壓縮為一個維度,即把上一步得到的維的feature map通過reshape成維的feature map。

    • 位置編碼: 在得到了維的feature map之后,正式輸入encoder之前,需要進行 Positional Encoding 。這一步在第2節(jié)講解transformer的時候已經提到過,因為在self-attention中需要有表示位置的信息,否則你的sequence = "A打了B" 還是sequence = "B打了A"的效果是一樣的。但是transformer encoder這個結構本身卻無法體現(xiàn)出位置信息。也就是說,我們需要對這個?維的feature map做positional encoding。

    進行完位置編碼以后根據(jù)paper中的圖片會有個相加的過程,如下圖問號處所示。很多讀者有疑問的地方是:論文圖示中相加的2個張量,一個是input embedding,另一個是位置編碼維度看上去不一致,是怎么相加的?后面會解答。

    圖:怎么相加的?

    原版Transformer和Vision Transformer (第4節(jié)講述)的Positional Encoding的表達式為:

    式中,?就是這個?維的feature map的第一維,?。表示token在sequence中的位置,sequence的長度是?,例如第一個token 的?。

    ,或者準確意義上是?和?表示了Positional Encoding的維度,的取值范圍是:?。所以當?為1時,對應的Positional Encoding可以寫成:

    式中,?。

    第一點不同的是,原版Transformer只考慮?方向的位置編碼,但是DETR考慮了?方向的位置編碼,因為圖像特征是2-D特征。采用的依然是?模式,但是需要考慮?兩個方向。不是類似vision transoformer做法簡單的將其拉伸為?,然后從?進行長度為256的位置編碼,而是考慮了?方向同時編碼,每個方向各編碼128維向量,這種編碼方式更符合圖像特點。

    Positional Encoding的輸出張量是:?,其中?代表位置編碼的長度,?代表張量的位置。意思是說,這個特征圖上的任意一個點?有個位置編碼,這個編碼的長度是256,其中,前128維代表?的位置編碼,后128維代表?的位置編碼。

    假設你想計算任意一個位置?的Positional Encoding,把?代入(11)式的?式和?式可以計算得到128維的向量,它代表?的位置編碼,再把?代入(11)式的?式和?式可以計算得到128維的向量,它代表?的位置編碼,把這2個128維的向量拼接起來,就得到了一個256維的向量,它代表?的位置編碼。

    計算所有位置的編碼,就得到了?的張量,代表這個batch的位置編碼。編碼矩陣的維度是?,也把它序列化成維度為?維的張量。

    準備與維的feature map相加以后輸入Encoder。

    值得注意的是,網上許多解讀文章沒有搞清楚 "轉化為序列化數(shù)據(jù)"這一步和 "位置編碼"的順序關系,以及變量的shape到底是怎樣變化的,這里我用一個圖表達,終結這個問題。

    圖29:變量的shape的變化,變量一律使用方塊表達。

    所以,了解了DETR的位置編碼之后,你應該明白了其實input embedding和位置編碼維度其實是一樣的,只是論文圖示為了突出二位編碼所以畫的不一樣罷了,如下圖所示:

    圖:input embedding與positional embedding的shape是一致的

    另一點不同的是,原版Transformer 只在Encoder之前使用了Positional Encoding,而且是在輸入上進行Positional Encoding,再把輸入經過transformation matrix變?yōu)镼uery,Key和Value這幾個張量。但是DETR在Encoder的每一個Multi-head Self-attention之前都使用了Positional Encoding,且只對Query和Key使用了Positional Encoding,即:只把維度為維的位置編碼與維度為維的Query和Key相加,而不與Value相加。

    如圖30所示為DETR的Transformer的詳細結構,讀者可以對比下原版Transformer的結構,如圖19所示,為了閱讀的方便我把圖19又貼在下面了。

    可以發(fā)現(xiàn),除了Positional Encoding設置的不一樣外,Encoder其他的結構是一致的。每個Encoder Layer包含一個multi-head self-attention 的module和一個前饋網絡Feed Forward Network。

    Encoder最終輸出的是?維的編碼矩陣Embedding,按照原版Transformer的做法,把這個東西給Decoder。

    總結下和原始transformer編碼器不同的地方:

    • 輸入編碼器的位置編碼需要考慮2-D空間位置。

    • 位置編碼向量需要加入到每個Encoder Layer中。

    • 在編碼器內部位置編碼Positional Encoding僅僅作用于Query和Key,即只與Query和Key相加,Value不做任何處理。

    圖30:Transformer詳細結構。為了方便理解,我把每個變量的維度標在了圖上。圖19:Transformer整體結構

    3 再看decoder:

    DETR的Decoder和原版Transformer的decoder是不太一樣的,如下圖30和19所示。

    先回憶下原版Transformer,看下圖19的decoder的最后一個框:output probability,代表我們一次只產生一個單詞的softmax,根據(jù)這個softmax得到這個單詞的預測結果。這個過程我們表達為:predicts the output sequence one element at a time。

    不同的是,DETR的Transformer Decoder是一次性處理全部的object queries,即一次性輸出全部的predictions;而不像原始的Transformer是auto-regressive的,從左到右一個詞一個詞地輸出。這個過程我們表達為:decodes the N objects in parallel at each decoder layer。

    DETR的Decoder主要有兩個輸入:

  • Transformer Encoder輸出的Embedding與 position encoding 之和。

  • Object queries。

  • 其中,Embedding就是上文提到的?的編碼矩陣。這里著重講一下Object queries。

    Object queries是一個維度為?維的張量,數(shù)值類型是nn.Embedding,說明這個張量是可以學習的,即:我們的Object queries是可學習的。Object queries矩陣內部通過學習建模了100個物體之間的全局關系,例如房間里面的桌子旁邊(A類)一般是放椅子(B類),而不會是放一頭大象(C類),那么在推理時候就可以利用該全局注意力更好的進行解碼預測輸出。

    Decoder的輸入一開始也初始化成維度為?維的全部元素都為0的張量,和Object queries加在一起之后充當?shù)?個multi-head self-attention的Query和Key。第一個multi-head self-attention的Value為Decoder的輸入,也就是全0的張量。

    到了每個Decoder的第2個multi-head self-attention,它的Key和Value來自Encoder的輸出張量,維度為?,其中Key值還進行位置編碼。Query值一部分來自第1個Add and Norm的輸出,維度為?的張量,另一部分來自Object queries,充當可學習的位置編碼。所以,第2個multi-head self-attention的Key和Value的維度為?,而Query的維度為。

    每個Decoder的輸出維度為?,送入后面的前饋網絡,具體的變量維度的變化見圖30。

    到這里你會發(fā)現(xiàn):Object queries充當?shù)钠鋵嵤俏恢镁幋a的作用,只不過它是可以學習的位置編碼,所以,我們對Encoder和Decoder的每個self-attention的Query和Key的位置編碼做個歸納,如圖31所示,Value沒有位置編碼:

    圖31:Transformer的位置編碼來自哪里?

    損失函數(shù)部分解讀

    得到了Decoder的輸出以后,如前文所述,應該是輸出維度為?的張量。接下來要送入2個前饋網絡FFN得到class和Bounding Box。它們會得到?個預測目標,包含類別和Bounding Box,當然這個100肯定是大于圖中的目標總數(shù)的。如果不夠100,則采用背景填充,計算loss時候回歸分支分支僅僅計算有物體位置,背景集合忽略。所以,DETR輸出張量的維度為輸出的張量的維度是?和?。對應COCO數(shù)據(jù)集來說,?,?指的是每個預測目標歸一化的?。歸一化就是除以圖片寬高進行歸一化。

    到這里我們了解了DETR的網絡架構,我們發(fā)現(xiàn),它輸出的張量的維度是 分類分支:回歸分支:?,其中,前者是指100個預測框的類型,后者是指100個預測框的Bounding Box,但是讀者可能會有疑問:預測框和真值是怎么一一對應的?換句話說:你怎么知道第47個預測框對應圖片里的狗,第88個預測框對應圖片里的車?等等。

    我們下面就來聊聊這個問題。

    相比Faster R-CNN等做法,DETR最大特點是將目標檢測問題轉化為無序集合預測問題(set prediction)。論文中特意指出Faster R-CNN這種設置一大堆anchor,然后基于anchor進行分類和回歸其實屬于代理做法即不是最直接做法,目標檢測任務就是輸出無序集合,而Faster R-CNN等算法通過各種操作,并結合復雜后處理最終才得到無序集合屬于繞路了,而DETR就比較純粹了?,F(xiàn)在核心問題來了:輸出的?個檢測結果是無序的,如何和?計算loss?這就需要用到經典的雙邊匹配算法了,也就是常說的匈牙利算法,該算法廣泛應用于最優(yōu)分配問題。

    一幅圖片,我們把第?個物體的真值表達為?,其中,?表示它的?,?表示它的?。我們定義?為網絡輸出的?個預測值。

    假設我們已經了解了什么是匈牙利算法(先假裝了解了),對于第?個?,?為匈牙利算法得到的與?對應的prediction的索引。我舉個栗子,比如?,意思就是:與第3個真值對應的預測值是第18個。

    那我能根據(jù)?匈牙利算法,找到?與每個真值對應的預測值是哪個,那究竟是如何找到呢?

    我們看看這個表達式是甚么意思,對于某一個真值?,假設我們已經找到這個真值對應的預測值?,這里的?是所有可能的排列,代表從真值索引到預測值索引的所有的映射,然后用?最小化?和?的距離。這個?具體是:

    意思是:假設當前從真值索引到預測值索引的所有的映射為?,對于圖片中的每個真值?,先找到對應的預測值?,再看看分類網絡的結果?,取反作為?的第1部分。再計算回歸網絡的結果?與真值的?的差異,即?,作為?的第2部分。

    所以,可以使得?最小的排列?就是我們要找的排列,即:對于圖片中的每個真值?來講,?就是這個真值所對應的預測值的索引。

    請讀者細品這個 尋找匹配的過程 ,這就是匈牙利算法的過程。是不是與Anchor或Proposal有異曲同工的地方,只是此時我們找的是一對一匹配。

    接下來就是使用上一步得到的排列?,計算匈牙利損失:

    式中的?具體為:

    最常用的?對于大小?會有不同的標度,即使它們的相對誤差是相似的。為了緩解這個問題,作者使用了?和廣義IoU損耗?的線性組合,它是比例不變的。

    Hungarian意思就是匈牙利,也就是前面的?,上述意思是需要計算?個?和?個輸預測出集合兩兩之間的廣義距離,距離越近表示越可能是最優(yōu)匹配關系,也就是兩者最密切。廣義距離的計算考慮了分類分支和回歸分支。

    最后,再概括一下DETR的End-to-End的原理,前面那么多段話就是為了講明白這個事情,如果你對前面的論述還存在疑問的話,把下面一直到Experiments之前的這段話看懂就能解決你的困惑。

    DETR是怎么訓練的?

    訓練集里面的任何一張圖片,假設第1張圖片,我們通過模型產生100個預測框?,假設這張圖片有只3個?,它們分別是?。

    問題是:我怎么知道這100個預測框哪個是對應?,哪個是對應?,哪個是對應??

    我們建立一個?的矩陣,矩陣里面的元素就是?式的計算結果,舉個例子:比如左上角的?號元素的含義是:第1個預測框對應?的情況下的?值。我們用scipy.optimize 這個庫中的 linear_sum_assignment 函數(shù)找到最優(yōu)的匹配,這個過程我們稱之為:"匈牙利算法 (Hungarian Algorithm)"

    假設linear_sum_assignment 做完以后的結果是:第?個預測框對應?,第?個預測框對應?,第?個預測框對應?。

    現(xiàn)在把第?個預測框挑出來,按照?式計算Loss,得到這個圖片的Loss。

    把所有的圖片按照這個模式去訓練模型。

    訓練完以后怎么用?

    訓練完以后,你的模型學習到了一種能力,即:模型產生的100個預測框,它知道某個預測框該對應什么?,比如,模型學習到:第1個?對應?,第2個?對應?,第3個?對應?,第4個?對應?,第5個?對應?,第6-100個?對應?,等等。

    以上只是我舉的一個例子,意思是說:模型知道了自己的100個預測框每個該做什么事情,即:每個框該預測什么樣的?。

    為什么訓練完以后,模型學習到了一種能力,即:模型產生的100個預測框,它知道某個預測框該對應什么??

    還記得前面說的Object queries嗎?它是一個維度為?維的張量,初始時元素全為?。實現(xiàn)方式是nn.Embedding(num_queries, hidden_dim),這里num_queries=100,hidden_dim=256,它是可訓練的。這里的?指的是batch size,我們考慮單張圖片,所以假設Object queries是一個維度為?維的張量。我們訓練完模型以后,這個張量已經訓練完了,那此時的Object queries究竟代表什么?

    我們把此時的Object queries看成100個格子,每個格子是個256維的向量。訓練完以后,這100個格子里面注入了不同?的位置信息和類別信息。比如第1個格子里面的這個256維的向量代表著?這種?的位置信息,這種信息是通過訓練,考慮了所有圖片的某個位置附近的?編碼特征,屬于和位置有關的全局?統(tǒng)計信息。

    測試時,假設圖片中有?三種物體,該圖片會輸入到編碼器中進行特征編碼,假設特征沒有丟失,Decoder的KeyValue就是編碼器輸出的編碼向量(如圖30所示),而Query就是Object queries,就是我們的100個格子。

    Query可以視作代表不同?的信息,而Key和Value可以視作代表圖像的全局信息。

    現(xiàn)在通過注意力模塊將QueryKey計算,然后加權Value得到解碼器輸出。對于第1個格子的Query會和Key中的所有向量進行計算,目的是查找某個位置附近有沒有?,如果有那么該特征就會加權輸出,對于第3個格子的Query會和Key中的所有向量進行計算,目的是查找某個位置附近有沒有?,很遺憾,這個沒有,所以輸出的信息里面沒有?。

    整個過程計算完成后就可以把編碼向量中的?的編碼嵌入信息提取出來,然后后面接?進行分類和回歸就比較容易,因為特征已經對齊了。

    發(fā)現(xiàn)了嗎?Object queries在訓練過程中對于?個格子會壓縮入對應的和位置和類別相關的統(tǒng)計信息,在測試階段就可以利用該Query去和某個圖像的編碼特征Key,Value計算,若圖片中剛好有Query想找的特征,比如?,則這個特征就能提取出來,最后通過2個?進行分類和回歸。所以前面才會說Object queries作用非常類似Faster R-CNN中的anchor,這個anchor是可學習的,由于維度比較高,故可以表征的東西豐富,當然維度越高,訓練時長就會越長。

    這就是DETR的End-to-End的原理,可以簡單歸結為上面的幾段話,你讀懂了上面的話,也就明白了DETR以及End-to-End的Detection模型原理。

    Experiments:

    1. 性能對比:

    圖32:DETR與Fast R-CNN的性能對比

    2. 編碼器層數(shù)對比實驗:

    圖33:編碼器數(shù)目與模型性能

    可以發(fā)現(xiàn),編碼器層數(shù)越多越好,最后就選擇6。

    下圖34為最后一個Encoder Layer的attention可視化,Encoder已經分離了instances,簡化了Decoder的對象提取和定位。

    圖34:最后一個Encoder Layer的attention可視化

    3. 解碼器層數(shù)對比實驗:

    圖35:每個Decoder Layer后的AP和AP 50性能。

    可以發(fā)現(xiàn),性能隨著解碼器層數(shù)的增加而提升,DETR本不需要NMS,但是作者也進行了,上圖中的NMS操作是指DETR的每個解碼層都可以輸入無序集合,那么將所有解碼器無序集合全部保留,然后進行NMS得到最終輸出,可以發(fā)現(xiàn)性能稍微有提升,特別是AP50。這可以通過以下事實來解釋:Transformer的單個Decoder Layer不能計算輸出元素之間的任何互相關,因此它易于對同一對象進行多次預測。在第2個和隨后的Decoder Layer中,self-attention允許模型抑制重復預測。所以NMS帶來的改善隨著Decoder Layer的增加而減少。在最后幾層,作者觀察到AP的一個小損失,因為NMS錯誤地刪除了真實的positive prediction。

    圖36:Decoder Layer的attention可視化

    類似于可視化編碼器注意力,作者在圖36中可視化解碼器注意力,用不同的顏色給每個預測對象的注意力圖著色。觀察到,解碼器的attention相當局部,這意味著它主要關注對象的四肢,如頭部或腿部。我們假設,在編碼器通過全局關注分離實例之后,解碼器只需要關注極端來提取類和對象邊界。

    • 3.2 DETR代碼解讀:

    https://github.com/facebookresearch/detr

    分析都注釋在了代碼中。

    二維位置編碼:
    DETR的二維位置編碼:
    首先構造位置矩陣x_embed和y_embed,這里用到了python函數(shù)cumsum,作用是對一個矩陣的元素進行累加,那么累加以后最后一個元素就是所有累加元素的和,省去了求和的步驟,直接用這個和做歸一化,對應x_embed[:, :, -1:]和y_embed[:, -1:, :]。
    這里我想著重強調下代碼中一些變量的shape,方便讀者掌握作者編程的思路:
    值得注意的是,tensor_list的類型是NestedTensor,內部自動附加了mask,用于表示動態(tài)shape,是pytorch中tensor新特性https://github.com/pytorch/nestedtensor。全是false。
    x:(b,c,H,W)
    mask:(b,H,W),全是False。
    not_mask:(b,H,W),全是True。
    首先出現(xiàn)的y_embed:(b,H,W),具體是1,1,1,1,......,2,2,2,2,......3,3,3,3,......
    首先出現(xiàn)的x_embed:(b,H,W),具體是1,2,3,4,......,1,2,3,4,......1,2,3,4,......
    self.num_pos_feats = 128
    首先出現(xiàn)的dim_t = [0,1,2,3,.....,127]
    pos_x:(b,H,W,128)
    pos_y:(b,H,W,128)
    flatten后面的數(shù)字指的是:flatten()方法應從哪個軸開始展開操作。
    torch.stack((pos_x[:, :, :, 0::2].sin(), pos_x[:, :, :, 1::2].cos()), dim=4).flatten(3)
    pos_y = torch.stack((pos_y[:, :, :, 0::2].sin(), pos_y[:, :, :, 1::2].cos()), dim=4)
    這一步執(zhí)行完以后變成(b,H,W,2,64)通過flatten()方法從第3個軸開始展平,變?yōu)?#xff1a;(b,H,W,128)
    torch.cat((pos_y, pos_x), dim=3)之后變?yōu)?b,H,W,256),再最后permute為(b,256,H,W)。
    PositionEmbeddingSine類繼承nn.Module類。

    class PositionEmbeddingSine(nn.Module):def __init__(self, num_pos_feats=64, temperature=10000, normalize=False, scale=None): super().__init__() self.num_pos_feats = num_pos_feats self.temperature = temperature self.normalize = normalize if scale is not None and normalize is False: raise ValueError("normalize should be True if scale is passed") if scale is None: scale = 2 * math.pi self.scale = scaledef forward(self, tensor_list: NestedTensor):#輸入是b,c,h,w#tensor_list的類型是NestedTensor,內部自動附加了mask,#用于表示動態(tài)shape,是pytorch中tensor新特性https://github.com/pytorch/nestedtensor x = tensor_list.tensors# 附加的mask,shape是b,h,w 全是false mask = tensor_list.mask assert mask is not None not_mask = ~mask# 因為圖像是2d的,所以位置編碼也分為x,y方向# 1 1 1 1 .. 2 2 2 2... 3 3 3... y_embed = not_mask.cumsum(1, dtype=torch.float32)# 1 2 3 4 ... 1 2 3 4... x_embed = not_mask.cumsum(2, dtype=torch.float32) if self.normalize: eps = 1e-6 y_embed = y_embed / (y_embed[:, -1:, :] + eps) * self.scale x_embed = x_embed / (x_embed[:, :, -1:] + eps) * self.scale # num_pos_feats = 128# 0~127 self.num_pos_feats=128,因為前面輸入向量是256,編碼是一半sin,一半cos dim_t = torch.arange(self.num_pos_feats, dtype=torch.float32, device=x.device) dim_t = self.temperature ** (2 * (dim_t // 2) / self.num_pos_feats) # 輸出shape=b,h,w,128 pos_x = x_embed[:, :, :, None] / dim_t pos_y = y_embed[:, :, :, None] / dim_t pos_x = torch.stack((pos_x[:, :, :, 0::2].sin(), pos_x[:, :, :, 1::2].cos()), dim=4).flatten(3) pos_y = torch.stack((pos_y[:, :, :, 0::2].sin(), pos_y[:, :, :, 1::2].cos()), dim=4).flatten(3) pos = torch.cat((pos_y, pos_x), dim=3).permute(0, 3, 1, 2)# 每個特征圖的xy位置都編碼成256的向量,其中前128是y方向編碼,而128是x方向編碼 return pos# b,n=256,h,w

    作者定義了一種數(shù)據(jù)結構:NestedTensor,里面打包存了兩個變量:x 和mask。

    NestedTensor:
    里面打包存了兩個變量:x 和mask。
    to()函數(shù):把變量移到GPU中。

    Backbone:

    class BackboneBase(nn.Module):def __init__(self, backbone: nn.Module, train_backbone: bool, num_channels: int, return_interm_layers: bool): super().__init__() for name, parameter in backbone.named_parameters(): if not train_backbone or 'layer2' not in name and 'layer3' not in name and 'layer4' not in name: parameter.requires_grad_(False) if return_interm_layers: return_layers = {"layer1": "0", "layer2": "1", "layer3": "2", "layer4": "3"} else: return_layers = {'layer4': "0"} #作用的模型:定義BackboneBase時傳入的nn.Moduleclass的backbone,返回的layer:來自bool變量return_interm_layers self.body = IntermediateLayerGetter(backbone, return_layers=return_layers) self.num_channels = num_channelsdef forward(self, tensor_list: NestedTensor):#BackboneBase的輸入是一個NestedTensor#xs中間層的輸出, xs = self.body(tensor_list.tensors) out: Dict[str, NestedTensor] = {} for name, x in xs.items(): m = tensor_list.mask assert m is not None#F.interpolate上下采樣,調整mask的size#to(torch.bool) 把mask轉化為Bool型變量 mask = F.interpolate(m[None].float(), size=x.shape[-2:]).to(torch.bool)[0] out[name] = NestedTensor(x, mask) return outclass Backbone(BackboneBase): """ResNet backbone with frozen BatchNorm.""" def __init__(self, name: str, train_backbone: bool, return_interm_layers: bool, dilation: bool):#根據(jù)name選擇backbone, num_channels, return_interm_layers等,傳入BackboneBase初始化 backbone = getattr(torchvision.models, name)( replace_stride_with_dilation=[False, False, dilation], pretrained=is_main_process(), norm_layer=FrozenBatchNorm2d) num_channels = 512 if name in ('resnet18', 'resnet34') else 2048 super().__init__(backbone, train_backbone, num_channels, return_interm_layers)

    把Backbone和之前的PositionEmbeddingSine連在一起:
    Backbone完以后輸出(b,c,h,w),再經過PositionEmbeddingSine輸出(b,H,W,256)。

    class Joiner(nn.Sequential): def __init__(self, backbone, position_embedding): super().__init__(backbone, position_embedding)def forward(self, tensor_list: NestedTensor): xs = self[0](tensor_list) out: List[NestedTensor] = [] pos = [] for name, x in xs.items(): out.append(x) # position encoding pos.append(self[1](x).to(x.tensors.dtype))return out, posdef build_backbone(args):#position_embedding是個nn.module position_embedding = build_position_encoding(args) train_backbone = args.lr_backbone > 0 return_interm_layers = args.masks#backbone是個nn.module backbone = Backbone(args.backbone, train_backbone, return_interm_layers, args.dilation)#nn.Sequential在一起 model = Joiner(backbone, position_embedding) model.num_channels = backbone.num_channels return model

    Transformer的一個Encoder Layer:

    class TransformerEncoderLayer(nn.Module):def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1, activation="relu", normalize_before=False): super().__init__() self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout) # Implementation of Feedforward model self.linear1 = nn.Linear(d_model, dim_feedforward) self.dropout = nn.Dropout(dropout) self.linear2 = nn.Linear(dim_feedforward, d_model)self.norm1 = nn.LayerNorm(d_model) self.norm2 = nn.LayerNorm(d_model) self.dropout1 = nn.Dropout(dropout) self.dropout2 = nn.Dropout(dropout)self.activation = _get_activation_fn(activation) self.normalize_before = normalize_beforedef with_pos_embed(self, tensor, pos: Optional[Tensor]): return tensor if pos is None else tensor + posdef forward_post(self, src, src_mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None, pos: Optional[Tensor] = None): # 和標準做法有點不一樣,src加上位置編碼得到q和k,但是v依然還是src, # 也就是v和qk不一樣 q = k = self.with_pos_embed(src, pos) src2 = self.self_attn(q, k, value=src, attn_mask=src_mask, key_padding_mask=src_key_padding_mask)[0]#Add and Norm src = src + self.dropout1(src2) src = self.norm1(src)#FFN src2 = self.linear2(self.dropout(self.activation(self.linear1(src))))#Add and Norm src = src + self.dropout2(src2) src = self.norm2(src) return srcdef forward_pre(self, src, src_mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None, pos: Optional[Tensor] = None): src2 = self.norm1(src) q = k = self.with_pos_embed(src2, pos) src2 = self.self_attn(q, k, value=src2, attn_mask=src_mask, key_padding_mask=src_key_padding_mask)[0] src = src + self.dropout1(src2) src2 = self.norm2(src) src2 = self.linear2(self.dropout(self.activation(self.linear1(src2)))) src = src + self.dropout2(src2) return srcdef forward(self, src, src_mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None, pos: Optional[Tensor] = None): if self.normalize_before: return self.forward_pre(src, src_mask, src_key_padding_mask, pos) return self.forward_post(src, src_mask, src_key_padding_mask, pos)

    有了一個Encoder Layer的定義,再看Transformer的整個Encoder:

    class TransformerEncoder(nn.Module): def __init__(self, encoder_layer, num_layers, norm=None): super().__init__() # 編碼器copy6份 self.layers = _get_clones(encoder_layer, num_layers) self.num_layers = num_layers self.norm = normdef forward(self, src, mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None, pos: Optional[Tensor] = None): # 內部包括6個編碼器,順序運行 # src是圖像特征輸入,shape=hxw,b,256 output = src for layer in self.layers: # 每個編碼器都需要加入pos位置編碼 # 第一個編碼器輸入來自圖像特征,后面的編碼器輸入來自前一個編碼器輸出 output = layer(output, src_mask=mask, src_key_padding_mask=src_key_padding_mask, pos=pos) return output

    Object Queries:可學習的位置編碼:
    注釋中已經注明了變量的shape的變化過程,最終輸出的是與Positional Encoding維度相同的位置編碼,維度是(b,H,W,256),只是現(xiàn)在這個位置編碼是可學習的了。

    class PositionEmbeddingLearned(nn.Module): """ Absolute pos embedding, learned. """ def __init__(self, num_pos_feats=256): super().__init__()]#這里使用了nn.Embedding,這是一個矩陣類,里面初始化了一個隨機矩陣,矩陣的長是字典的大小,寬是用來表示字典中每個元素的屬性向量,# 向量的維度根據(jù)你想要表示的元素的復雜度而定。類實例化之后可以根據(jù)字典中元素的下標來查找元素對應的向量。輸入下標0,輸出就是embeds矩陣中第0行。 self.row_embed = nn.Embedding(50, num_pos_feats) self.col_embed = nn.Embedding(50, num_pos_feats) self.reset_parameters()def reset_parameters(self): nn.init.uniform_(self.row_embed.weight) nn.init.uniform_(self.col_embed.weight) #輸入依舊是NestedTensor def forward(self, tensor_list: NestedTensor): x = tensor_list.tensors h, w = x.shape[-2:] i = torch.arange(w, device=x.device) j = torch.arange(h, device=x.device) #x_emb:(w, 128)#y_emb:(h, 128) x_emb = self.col_embed(i) y_emb = self.row_embed(j) pos = torch.cat([ x_emb.unsqueeze(0).repeat(h, 1, 1),#(1,w,128) → (h,w,128) y_emb.unsqueeze(1).repeat(1, w, 1),#(h,1,128) → (h,w,128) ], dim=-1).permute(2, 0, 1).unsqueeze(0).repeat(x.shape[0], 1, 1, 1)#(h,w,256) → (256,h,w) → (1,256,h,w) → (b,256,h,w) return posdef build_position_encoding(args): N_steps = args.hidden_dim // 2 if args.position_embedding in ('v2', 'sine'): # TODO find a better way of exposing other arguments position_embedding = PositionEmbeddingSine(N_steps, normalize=True) elif args.position_embedding in ('v3', 'learned'): position_embedding = PositionEmbeddingLearned(N_steps) else: raise ValueError(f"not supported {args.position_embedding}")return position_embedding

    Transformer的一個Decoder Layer:
    注意變量的命名:
    object queries(query_pos)
    Encoder的位置編碼(pos)
    Encoder的輸出(memory)

    def forward_post(self, tgt, memory, tgt_mask: Optional[Tensor] = None, memory_mask: Optional[Tensor] = None, tgt_key_padding_mask: Optional[Tensor] = None, memory_key_padding_mask: Optional[Tensor] = None, pos: Optional[Tensor] = None, query_pos: Optional[Tensor] = None): #query,key的輸入是object queries(query_pos) + Decoder的輸入(tgt),shape都是(100,b,256)#value的輸入是Decoder的輸入(tgt),shape = (100,b,256) q = k = self.with_pos_embed(tgt, query_pos) #Multi-head self-attention tgt2 = self.self_attn(q, k, value=tgt, attn_mask=tgt_mask, key_padding_mask=tgt_key_padding_mask)[0]#Add and Norm tgt = tgt + self.dropout1(tgt2) tgt = self.norm1(tgt) #query的輸入是上一個attention的輸出(tgt) + object queries(query_pos)#key的輸入是Encoder的位置編碼(pos) + Encoder的輸出(memory)#value的輸入是Encoder的輸出(memory) tgt2 = self.multihead_attn(query=self.with_pos_embed(tgt, query_pos), key=self.with_pos_embed(memory, pos), value=memory, attn_mask=memory_mask, key_padding_mask=memory_key_padding_mask)[0] #Add and Norm tgt = tgt + self.dropout2(tgt2) tgt = self.norm2(tgt) #FFN tgt2 = self.linear2(self.dropout(self.activation(self.linear1(tgt)))) tgt = tgt + self.dropout3(tgt2) tgt = self.norm3(tgt) return tgtdef forward_pre(self, tgt, memory, tgt_mask: Optional[Tensor] = None, memory_mask: Optional[Tensor] = None, tgt_key_padding_mask: Optional[Tensor] = None, memory_key_padding_mask: Optional[Tensor] = None, pos: Optional[Tensor] = None, query_pos: Optional[Tensor] = None): tgt2 = self.norm1(tgt) q = k = self.with_pos_embed(tgt2, query_pos) tgt2 = self.self_attn(q, k, value=tgt2, attn_mask=tgt_mask, key_padding_mask=tgt_key_padding_mask)[0] tgt = tgt + self.dropout1(tgt2) tgt2 = self.norm2(tgt) tgt2 = self.multihead_attn(query=self.with_pos_embed(tgt2, query_pos), key=self.with_pos_embed(memory, pos), value=memory, attn_mask=memory_mask, key_padding_mask=memory_key_padding_mask)[0] tgt = tgt + self.dropout2(tgt2) tgt2 = self.norm3(tgt) tgt2 = self.linear2(self.dropout(self.activation(self.linear1(tgt2)))) tgt = tgt + self.dropout3(tgt2) return tgtdef forward(self, tgt, memory, tgt_mask: Optional[Tensor] = None, memory_mask: Optional[Tensor] = None, tgt_key_padding_mask: Optional[Tensor] = None, memory_key_padding_mask: Optional[Tensor] = None, pos: Optional[Tensor] = None, query_pos: Optional[Tensor] = None): if self.normalize_before: return self.forward_pre(tgt, memory, tgt_mask, memory_mask, tgt_key_padding_mask, memory_key_padding_mask, pos, query_pos) return self.forward_post(tgt, memory, tgt_mask, memory_mask, tgt_key_padding_mask, memory_key_padding_mask, pos, query_pos)

    有了一個Decoder Layer的定義,再看Transformer的整個Decoder:

    class TransformerDecoder(nn.Module):#值得注意的是:在使用TransformerDecoder時需要傳入的參數(shù)有:# tgt:Decoder的輸入,memory:Encoder的輸出,pos:Encoder的位置編碼的輸出,query_pos:Object Queries,一堆mask def forward(self, tgt, memory, tgt_mask: Optional[Tensor] = None, memory_mask: Optional[Tensor] = None, tgt_key_padding_mask: Optional[Tensor] = None, memory_key_padding_mask: Optional[Tensor] = None, pos: Optional[Tensor] = None, query_pos: Optional[Tensor] = None): output = tgtintermediate = []for layer in self.layers: output = layer(output, memory, tgt_mask=tgt_mask, memory_mask=memory_mask, tgt_key_padding_mask=tgt_key_padding_mask, memory_key_padding_mask=memory_key_padding_mask, pos=pos, query_pos=query_pos) if self.return_intermediate: intermediate.append(self.norm(output))if self.norm is not None: output = self.norm(output) if self.return_intermediate: intermediate.pop() intermediate.append(output)if self.return_intermediate: return torch.stack(intermediate)return output.unsqueeze(0)

    然后是把Encoder和Decoder拼在一起,即總的Transformer結構的實現(xiàn):
    此處考慮到字數(shù)限制,省略了代碼。

    實現(xiàn)了Transformer,還剩后面的FFN:

    class MLP(nn.Module): """ Very simple multi-layer perceptron (also called FFN)""" 代碼略,簡單的Pytorch定義layer。

    匈牙利匹配HungarianMatcher類:
    這個類的目的是計算從targets到predictions的一種最優(yōu)排列。
    predictions比targets的數(shù)量多,但我們要進行1-to-1 matching,所以多的predictions將與?匹配。
    這個函數(shù)整體在構建(13)式,cost_class,cost_bbox,cost_giou,對應的就是(13)式中的幾個損失函數(shù),它們的維度都是(b,100,m)。
    m包含了這個batch內部所有的?。

    # pred_logits:[b,100,92] # pred_boxes:[b,100,4] # targets是個長度為b的list,其中的每個元素是個字典,共包含:labels-長度為(m,)的Tensor,元素是標簽;boxes-長度為(m,4)的Tensor,元素是Bounding Box。 # detr分類輸出,num_queries=100,shape是(b,100,92)bs, num_queries = outputs["pred_logits"].shape[:2]# We flatten to compute the cost matrices in a batchout_prob = outputs["pred_logits"].flatten(0, 1).softmax(-1) # [batch_size * num_queries, num_classes] = [100b, 92]out_bbox = outputs["pred_boxes"].flatten(0, 1) # [batch_size * num_queries, 4] = [100b, 4]# 準備分類target shape=(m,)里面存儲的是類別索引,m包括了整個batch內部的所有gt bbox# Also concat the target labels and boxestgt_ids = torch.cat([v["labels"] for v in targets])# (m,)[3,6,7,9,5,9,3] # 準備bbox target shape=(m,4),已經歸一化了tgt_bbox = torch.cat([v["boxes"] for v in targets])# (m,4)#(100b,92)->(100b, m),對于每個預測結果,把目前gt里面有的所有類別值提取出來,其余值不需要參與匹配 #對應上述公式,類似于nll loss,但是更加簡單# Compute the classification cost. Contrary to the loss, we don't use the NLL,# but approximate it in 1 - proba[target class].# The 1 is a constant that doesn't change the matching, it can be ommitted. #行:取每一行;列:只取tgt_ids對應的m列cost_class = -out_prob[:, tgt_ids]# (100b, m)# Compute the L1 cost between boxes, 計算out_bbox和tgt_bbox兩兩之間的l1距離 (100b, m)cost_bbox = torch.cdist(out_bbox, tgt_bbox, p=1)# (100b, m)# Compute the giou cost betwen boxes, 額外多計算一個giou loss (100b, m)cost_giou = -generalized_box_iou(box_cxcywh_to_xyxy(out_bbox), box_cxcywh_to_xyxy(tgt_bbox))#得到最終的廣義距離(100b, m),距離越小越可能是最優(yōu)匹配# Final cost matrixC = self.cost_bbox * cost_bbox + self.cost_class * cost_class + self.cost_giou * cost_giou #(100b, m)--> (b, 100, m)C = C.view(bs, num_queries, -1).cpu()#計算每個batch內部有多少物體,后續(xù)計算時候按照單張圖片進行匹配,沒必要batch級別匹配,徒增計算sizes = [len(v["boxes"]) for v in targets] #匈牙利最優(yōu)匹配,返回匹配索引 #enumerate(C.split(sizes, -1))]:(b,100,image1,image2,image3,...)indices = [linear_sum_assignment(c[i]) for i, c in enumerate(C.split(sizes, -1))] return [(torch.as_tensor(i, dtype=torch.int64), torch.as_tensor(j, dtype=torch.int64)) for i, j in indices]

    在得到匹配關系后算loss就水到渠成了。loss_labels計算分類損失,loss_boxes計算回歸損失,包含?。

    PS:作者將繼續(xù)更新Section2和Section3,請保持關注~

    參考文獻:

    code:
    https://github.com/jadore801120/attention-is-all-you-need-pytorch
    https://github.com/lucidrains/vit-pytorch
    https://github.com/facebookresearch/detr

    video:
    https://www.bilibili.com/video/av71295187/?spm_id_from=333.788.videocard.8

    blog:
    https://baijiahao.baidu.com/s?id%3D1651219987457222196&wfr=spider%26for=pc
    https://zhuanlan.zhihu.com/p/308301901
    https://blog.csdn.net/your_answer/article/details/79160045

    ◎作者檔案

    作者:科技猛獸

    往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習及深度學習筆記等資料打印機器學習在線手冊深度學習筆記專輯《統(tǒng)計學習方法》的代碼復現(xiàn)專輯 AI基礎下載機器學習的數(shù)學基礎專輯 獲取本站知識星球優(yōu)惠券,復制鏈接直接打開: https://t.zsxq.com/qFiUFMV 本站qq群704220115。加入微信群請掃碼:

    總結

    以上是生活随笔為你收集整理的【深度学习】搞懂 Vision Transformer 原理和代码,看这篇技术综述就够了的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    国产 浪潮av性色四虎 | 天天综合网天天综合色 | 色婷婷av一区二区三区之红樱桃 | 午夜男女很黄的视频 | 亚洲小说春色综合另类 | 成在人线av无码免费 | 六月丁香婷婷色狠狠久久 | 国产综合色产在线精品 | 在线看片无码永久免费视频 | 亚洲s码欧洲m码国产av | www国产亚洲精品久久网站 | 久久综合激激的五月天 | 青草视频在线播放 | 亚洲成av人片在线观看无码不卡 | 国产亚洲精品久久久久久久 | 老子影院午夜伦不卡 | 性开放的女人aaa片 | 熟妇人妻无码xxx视频 | 国产精品国产三级国产专播 | 国产精品高潮呻吟av久久4虎 | 亚洲gv猛男gv无码男同 | 欧美性黑人极品hd | 又粗又大又硬又长又爽 | 18禁黄网站男男禁片免费观看 | 麻豆av传媒蜜桃天美传媒 | 国产激情一区二区三区 | 久久 国产 尿 小便 嘘嘘 | 乱人伦人妻中文字幕无码 | 未满小14洗澡无码视频网站 | 成 人 网 站国产免费观看 | 国产午夜福利100集发布 | 亚洲精品一区三区三区在线观看 | 国产亚洲精品久久久久久 | 久久国产精品_国产精品 | 精品无码国产自产拍在线观看蜜 | 欧美 日韩 人妻 高清 中文 | 久久zyz资源站无码中文动漫 | 亚洲成a人一区二区三区 | 色窝窝无码一区二区三区色欲 | 强辱丰满人妻hd中文字幕 | 狠狠亚洲超碰狼人久久 | 精品无码国产自产拍在线观看蜜 | 午夜福利一区二区三区在线观看 | 日产精品高潮呻吟av久久 | 国产情侣作爱视频免费观看 | 丝袜 中出 制服 人妻 美腿 | 亚洲日韩精品欧美一区二区 | 色噜噜亚洲男人的天堂 | 欧美怡红院免费全部视频 | 亚洲人成人无码网www国产 | 激情国产av做激情国产爱 | 国产午夜手机精彩视频 | 九月婷婷人人澡人人添人人爽 | 捆绑白丝粉色jk震动捧喷白浆 | 中国女人内谢69xxxxxa片 | 老熟妇乱子伦牲交视频 | 亚洲熟女一区二区三区 | 无人区乱码一区二区三区 | 亚洲熟悉妇女xxx妇女av | 国产成人无码一二三区视频 | www国产精品内射老师 | 美女张开腿让人桶 | 97夜夜澡人人双人人人喊 | 无码精品人妻一区二区三区av | 国产精品沙发午睡系列 | 国产综合久久久久鬼色 | 131美女爱做视频 | 国产成人无码av片在线观看不卡 | 丝袜 中出 制服 人妻 美腿 | 久久久久久亚洲精品a片成人 | 狠狠色丁香久久婷婷综合五月 | 国色天香社区在线视频 | 亚洲va中文字幕无码久久不卡 | 国产小呦泬泬99精品 | 欧洲欧美人成视频在线 | 亚洲熟妇色xxxxx欧美老妇y | 97夜夜澡人人爽人人喊中国片 | 亚洲国产欧美国产综合一区 | 国产成人无码专区 | 亚洲啪av永久无码精品放毛片 | 亚洲自偷自偷在线制服 | 97资源共享在线视频 | 免费无码午夜福利片69 | 国产精品久久久久无码av色戒 | 国产亚洲人成a在线v网站 | 熟女俱乐部五十路六十路av | 国产精品久久久午夜夜伦鲁鲁 | 正在播放老肥熟妇露脸 | 永久黄网站色视频免费直播 | 人人妻人人澡人人爽欧美一区九九 | 国产成人无码一二三区视频 | 亚洲人成网站色7799 | 无码av最新清无码专区吞精 | 国产亲子乱弄免费视频 | 亚洲一区av无码专区在线观看 | 永久免费观看国产裸体美女 | 99久久久国产精品无码免费 | 亚洲欧美综合区丁香五月小说 | 国产日产欧产精品精品app | 永久免费观看美女裸体的网站 | 四虎国产精品免费久久 | 国产午夜亚洲精品不卡下载 | 性生交大片免费看女人按摩摩 | 久久久国产一区二区三区 | 亚洲一区二区三区国产精华液 | 纯爱无遮挡h肉动漫在线播放 | 亚洲va中文字幕无码久久不卡 | 97资源共享在线视频 | 国产又爽又黄又刺激的视频 | 国产亚洲美女精品久久久2020 | 精品国产一区二区三区四区 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 中文字幕无码免费久久99 | 欧美放荡的少妇 | 久久亚洲中文字幕无码 | 欧美三级a做爰在线观看 | 在线亚洲高清揄拍自拍一品区 | 亚洲自偷自拍另类第1页 | 午夜时刻免费入口 | 55夜色66夜色国产精品视频 | 中国女人内谢69xxxx | 国产av一区二区精品久久凹凸 | 人人妻人人澡人人爽精品欧美 | 一二三四社区在线中文视频 | 亚洲欧美日韩成人高清在线一区 | 偷窥村妇洗澡毛毛多 | 亚洲一区二区三区无码久久 | 亚洲性无码av中文字幕 | 欧美成人高清在线播放 | 久久久久久久人妻无码中文字幕爆 | 少妇性俱乐部纵欲狂欢电影 | 大肉大捧一进一出好爽视频 | 日产国产精品亚洲系列 | 国产乡下妇女做爰 | 久久熟妇人妻午夜寂寞影院 | 人人妻人人澡人人爽欧美一区 | 装睡被陌生人摸出水好爽 | 成人欧美一区二区三区黑人 | 亚洲天堂2017无码 | 午夜精品久久久内射近拍高清 | 欧美激情一区二区三区成人 | 亚洲日韩av一区二区三区中文 | 日本丰满护士爆乳xxxx | 波多野结衣aⅴ在线 | 波多野结衣aⅴ在线 | 亚洲熟女一区二区三区 | 欧美精品免费观看二区 | 亚洲色在线无码国产精品不卡 | 最近的中文字幕在线看视频 | 国产精华av午夜在线观看 | 成人性做爰aaa片免费看不忠 | 国产无遮挡又黄又爽免费视频 | 波多野结衣av一区二区全免费观看 | 欧美日韩精品 | 久久综合狠狠综合久久综合88 | 国产欧美精品一区二区三区 | 在线成人www免费观看视频 | 人妻无码αv中文字幕久久琪琪布 | av在线亚洲欧洲日产一区二区 | 国产精品.xx视频.xxtv | 午夜嘿嘿嘿影院 | 香港三级日本三级妇三级 | 亚洲欧洲中文日韩av乱码 | 成人动漫在线观看 | 午夜男女很黄的视频 | 天天拍夜夜添久久精品 | 99久久久无码国产aaa精品 | 成人一区二区免费视频 | 十八禁视频网站在线观看 | 正在播放老肥熟妇露脸 | 99久久婷婷国产综合精品青草免费 | 成人综合网亚洲伊人 | 免费看少妇作爱视频 | 老熟妇乱子伦牲交视频 | 国产人成高清在线视频99最全资源 | 性史性农村dvd毛片 | 狠狠色丁香久久婷婷综合五月 | 成人性做爰aaa片免费看不忠 | 人妻少妇精品久久 | 久久久久国色av免费观看性色 | 在线 国产 欧美 亚洲 天堂 | 日本大乳高潮视频在线观看 | 国产无遮挡吃胸膜奶免费看 | 丁香花在线影院观看在线播放 | 国产精品第一区揄拍无码 | 亚洲精品国产第一综合99久久 | 国产 浪潮av性色四虎 | 久久亚洲a片com人成 | 亚洲啪av永久无码精品放毛片 | 中文无码成人免费视频在线观看 | 人妻夜夜爽天天爽三区 | 欧美日本免费一区二区三区 | 伊在人天堂亚洲香蕉精品区 | 一个人看的www免费视频在线观看 | 巨爆乳无码视频在线观看 | 久久久精品欧美一区二区免费 | 最近的中文字幕在线看视频 | 国内精品人妻无码久久久影院 | 在线观看免费人成视频 | 欧美激情内射喷水高潮 | 99精品无人区乱码1区2区3区 | 亚洲色偷偷男人的天堂 | 西西人体www44rt大胆高清 | 狠狠亚洲超碰狼人久久 | 亚洲综合久久一区二区 | 精品无码一区二区三区的天堂 | 国产亲子乱弄免费视频 | a片在线免费观看 | 色综合天天综合狠狠爱 | 色欲人妻aaaaaaa无码 | 色综合久久久无码网中文 | 国产综合色产在线精品 | 亚洲成色www久久网站 | 亚洲中文字幕在线无码一区二区 | 日本熟妇人妻xxxxx人hd | 激情内射日本一区二区三区 | 啦啦啦www在线观看免费视频 | 国内精品人妻无码久久久影院 | 久激情内射婷内射蜜桃人妖 | 久久99久久99精品中文字幕 | 性欧美牲交xxxxx视频 | 亚欧洲精品在线视频免费观看 | 中文字幕乱码人妻无码久久 | 日本护士xxxxhd少妇 | 中文无码成人免费视频在线观看 | 欧美人与动性行为视频 | 无码精品国产va在线观看dvd | 国产色精品久久人妻 | 国产精品无码久久av | 色综合久久88色综合天天 | 久久亚洲精品中文字幕无男同 | 中文精品久久久久人妻不卡 | 亚洲综合精品香蕉久久网 | 国精产品一品二品国精品69xx | 大肉大捧一进一出视频出来呀 | 亚洲第一网站男人都懂 | 亚洲国产精品美女久久久久 | 无码人妻久久一区二区三区不卡 | 久久久久se色偷偷亚洲精品av | 国产激情一区二区三区 | 色欲av亚洲一区无码少妇 | 中文字幕av无码一区二区三区电影 | 久久久久久av无码免费看大片 | 99久久久无码国产精品免费 | 激情亚洲一区国产精品 | 日本一卡二卡不卡视频查询 | 熟妇人妻无码xxx视频 | 亚洲乱码中文字幕在线 | 日韩精品久久久肉伦网站 | 男女爱爱好爽视频免费看 | 熟妇人妻无乱码中文字幕 | 久久精品国产日本波多野结衣 | 久久精品国产日本波多野结衣 | 国产超碰人人爽人人做人人添 | 久久久无码中文字幕久... | 欧美35页视频在线观看 | 久久精品国产一区二区三区 | 中国女人内谢69xxxx | 少妇被粗大的猛进出69影院 | 亚洲欧美日韩成人高清在线一区 | 欧美亚洲日韩国产人成在线播放 | 久久综合激激的五月天 | 嫩b人妻精品一区二区三区 | 成人无码视频在线观看网站 | 大胆欧美熟妇xx | 欧美成人免费全部网站 | 丰满人妻精品国产99aⅴ | 四虎影视成人永久免费观看视频 | 亚洲综合无码一区二区三区 | 蜜桃视频韩日免费播放 | 强伦人妻一区二区三区视频18 | 少妇性荡欲午夜性开放视频剧场 | 天堂а√在线地址中文在线 | 久久午夜夜伦鲁鲁片无码免费 | 亚洲日韩中文字幕在线播放 | 成人无码视频免费播放 | 午夜精品久久久久久久 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 国产综合在线观看 | 精品人妻人人做人人爽 | 两性色午夜免费视频 | 亚洲一区二区观看播放 | 欧美放荡的少妇 | 又湿又紧又大又爽a视频国产 | 一本久道久久综合婷婷五月 | 国产激情精品一区二区三区 | 在线欧美精品一区二区三区 | 欧美放荡的少妇 | 亚洲乱码中文字幕在线 | 久久视频在线观看精品 | 精品水蜜桃久久久久久久 | 乌克兰少妇xxxx做受 | 久久国内精品自在自线 | 亚洲国产精品一区二区第一页 | 国产综合在线观看 | 国产一区二区三区精品视频 | 香蕉久久久久久av成人 | 国产精华av午夜在线观看 | 狠狠cao日日穞夜夜穞av | 99久久亚洲精品无码毛片 | 97人妻精品一区二区三区 | 又粗又大又硬又长又爽 | 亚洲欧美精品aaaaaa片 | 四十如虎的丰满熟妇啪啪 | 三上悠亚人妻中文字幕在线 | 大肉大捧一进一出视频出来呀 | 午夜熟女插插xx免费视频 | 成人无码精品一区二区三区 | 亚洲小说图区综合在线 | 国产香蕉97碰碰久久人人 | 97久久国产亚洲精品超碰热 | 国产偷自视频区视频 | 午夜成人1000部免费视频 | 久久 国产 尿 小便 嘘嘘 | 久久国产自偷自偷免费一区调 | 小泽玛莉亚一区二区视频在线 | 性啪啪chinese东北女人 | 亚洲欧美综合区丁香五月小说 | 乱码av麻豆丝袜熟女系列 | 夜夜影院未满十八勿进 | 久久伊人色av天堂九九小黄鸭 | 亚洲色偷偷偷综合网 | 精品久久久久久亚洲精品 | √天堂资源地址中文在线 | 老头边吃奶边弄进去呻吟 | 亚洲精品一区二区三区大桥未久 | 狂野欧美性猛xxxx乱大交 | 亚洲成a人片在线观看无码 | 日韩精品无码一区二区中文字幕 | 亚洲国产av精品一区二区蜜芽 | 俄罗斯老熟妇色xxxx | 欧美老人巨大xxxx做受 | 成年美女黄网站色大免费视频 | 亚洲熟妇色xxxxx欧美老妇 | 久久久久久九九精品久 | 国内老熟妇对白xxxxhd | 对白脏话肉麻粗话av | 亚无码乱人伦一区二区 | 国产精品人人妻人人爽 | 高清无码午夜福利视频 | 亚洲色成人中文字幕网站 | 日本精品久久久久中文字幕 | 国产精品久久久久影院嫩草 | 婷婷六月久久综合丁香 | 国产精品亚洲综合色区韩国 | 久久久亚洲欧洲日产国码αv | 国产亚洲精品久久久久久久久动漫 | 美女黄网站人色视频免费国产 | 一个人免费观看的www视频 | www国产精品内射老师 | 亚洲国产精品一区二区第一页 | 久久午夜无码鲁丝片 | 中国大陆精品视频xxxx | 亚洲国精产品一二二线 | 欧美一区二区三区 | 精品国产一区二区三区四区在线看 | 又粗又大又硬毛片免费看 | 国产69精品久久久久app下载 | 国产乱人无码伦av在线a | 无码av最新清无码专区吞精 | 亚洲aⅴ无码成人网站国产app | 国产电影无码午夜在线播放 | 亚洲国产精品无码一区二区三区 | 色综合久久中文娱乐网 | 欧美自拍另类欧美综合图片区 | 成人无码影片精品久久久 | 东京热男人av天堂 | 精品国精品国产自在久国产87 | 娇妻被黑人粗大高潮白浆 | 无码人妻久久一区二区三区不卡 | 国产精品人妻一区二区三区四 | 亚洲国产精品毛片av不卡在线 | 国产内射老熟女aaaa | 一个人免费观看的www视频 | 精品无码成人片一区二区98 | 麻豆人妻少妇精品无码专区 | 四虎国产精品免费久久 | 夜夜夜高潮夜夜爽夜夜爰爰 | 无码人妻丰满熟妇区五十路百度 | 性生交大片免费看女人按摩摩 | 蜜臀av无码人妻精品 | 久久久婷婷五月亚洲97号色 | 51国偷自产一区二区三区 | 久久精品中文字幕一区 | 国产色视频一区二区三区 | 国产精品18久久久久久麻辣 | 久久精品中文闷骚内射 | 麻花豆传媒剧国产免费mv在线 | 国产色精品久久人妻 | 国产av无码专区亚洲awww | 女人色极品影院 | 少妇被黑人到高潮喷出白浆 | 午夜精品一区二区三区在线观看 | 亚洲综合在线一区二区三区 | 三级4级全黄60分钟 | av人摸人人人澡人人超碰下载 | 亚洲第一无码av无码专区 | 丁香花在线影院观看在线播放 | 久久久久亚洲精品男人的天堂 | 久久久久久亚洲精品a片成人 | 高清无码午夜福利视频 | 亚洲男女内射在线播放 | 色诱久久久久综合网ywww | 久久亚洲精品中文字幕无男同 | 国产亚洲精品久久久久久大师 | аⅴ资源天堂资源库在线 | 一个人看的www免费视频在线观看 | 老熟妇仑乱视频一区二区 | 中文字幕日产无线码一区 | 人妻插b视频一区二区三区 | 99久久久无码国产精品免费 | 又湿又紧又大又爽a视频国产 | 7777奇米四色成人眼影 | 无码免费一区二区三区 | 亚洲国产精品无码久久久久高潮 | 亚洲色成人中文字幕网站 | 男人和女人高潮免费网站 | 国产极品视觉盛宴 | 撕开奶罩揉吮奶头视频 | 四虎永久在线精品免费网址 | 精品少妇爆乳无码av无码专区 | 99久久人妻精品免费二区 | 好爽又高潮了毛片免费下载 | 国产精品第一区揄拍无码 | 亚洲中文字幕成人无码 | 成人欧美一区二区三区黑人免费 | 国产亚洲美女精品久久久2020 | 国产精品18久久久久久麻辣 | 人人妻人人藻人人爽欧美一区 | 最新国产乱人伦偷精品免费网站 | 国产欧美精品一区二区三区 | 国产超碰人人爽人人做人人添 | 国产又粗又硬又大爽黄老大爷视 | 成在人线av无码免观看麻豆 | 一二三四在线观看免费视频 | 久久精品人妻少妇一区二区三区 | 国产精品福利视频导航 | 精品午夜福利在线观看 | 欧美性生交活xxxxxdddd | 青草视频在线播放 | 久久久中文字幕日本无吗 | 国产无遮挡又黄又爽又色 | 强开小婷嫩苞又嫩又紧视频 | 中文字幕无线码免费人妻 | 国产熟妇另类久久久久 | 成人一在线视频日韩国产 | 国产成人人人97超碰超爽8 | 久久综合狠狠综合久久综合88 | 久久久久久av无码免费看大片 | 樱花草在线播放免费中文 | 1000部啪啪未满十八勿入下载 | 国产亚洲美女精品久久久2020 | 国产精品内射视频免费 | 亚洲色欲色欲欲www在线 | 日本一卡二卡不卡视频查询 | 国产精品亚洲五月天高清 | 无码毛片视频一区二区本码 | av在线亚洲欧洲日产一区二区 | 少妇高潮喷潮久久久影院 | 亚洲熟妇色xxxxx欧美老妇y | 亚洲性无码av中文字幕 | 97精品人妻一区二区三区香蕉 | 午夜精品一区二区三区的区别 | 国产精品丝袜黑色高跟鞋 | 成人无码精品一区二区三区 | 日本一区二区三区免费高清 | 国产精品久久久久久亚洲影视内衣 | 丰满人妻翻云覆雨呻吟视频 | 亚洲国产欧美国产综合一区 | 天天摸天天碰天天添 | 蜜桃视频韩日免费播放 | 玩弄少妇高潮ⅹxxxyw | 精品厕所偷拍各类美女tp嘘嘘 | 色情久久久av熟女人妻网站 | 国产片av国语在线观看 | 国产亚洲精品久久久久久久久动漫 | 台湾无码一区二区 | 黑人玩弄人妻中文在线 | 牲交欧美兽交欧美 | 中文久久乱码一区二区 | 日日碰狠狠丁香久燥 | 精品乱子伦一区二区三区 | 国产亚洲精品久久久久久久久动漫 | av小次郎收藏 | 国产成人综合在线女婷五月99播放 | 亚洲欧美中文字幕5发布 | 国产性生大片免费观看性 | 性史性农村dvd毛片 | 亚洲色大成网站www国产 | 亚洲欧美综合区丁香五月小说 | 国产激情无码一区二区app | 精品日本一区二区三区在线观看 | 国产精品久久久久久无码 | 成熟人妻av无码专区 | 夜夜夜高潮夜夜爽夜夜爰爰 | 亚洲人成人无码网www国产 | 噜噜噜亚洲色成人网站 | 国产两女互慰高潮视频在线观看 | 性史性农村dvd毛片 | 麻豆果冻传媒2021精品传媒一区下载 | 色一情一乱一伦 | 131美女爱做视频 | 国产精品免费大片 | 久久精品国产日本波多野结衣 | 丰满妇女强制高潮18xxxx | 少妇邻居内射在线 | 风流少妇按摩来高潮 | 国产熟女一区二区三区四区五区 | 国产亚洲精品久久久闺蜜 | 亚洲精品综合一区二区三区在线 | 装睡被陌生人摸出水好爽 | 日韩精品无码一区二区中文字幕 | 红桃av一区二区三区在线无码av | 丰满少妇高潮惨叫视频 | 国产情侣作爱视频免费观看 | 激情爆乳一区二区三区 | 久久综合狠狠综合久久综合88 | 国产成人无码一二三区视频 | 国产精品无套呻吟在线 | a片免费视频在线观看 | 久久久精品国产sm最大网站 | 又大又紧又粉嫩18p少妇 | 波多野结衣一区二区三区av免费 | 国产亚洲精品久久久久久久 | 精品国产一区二区三区四区 | 精品无码成人片一区二区98 | 亚洲精品综合一区二区三区在线 | 亚洲日韩一区二区三区 | 扒开双腿疯狂进出爽爽爽视频 | 秋霞特色aa大片 | 99久久人妻精品免费一区 | 中国大陆精品视频xxxx | 无码人妻av免费一区二区三区 | 国产一区二区不卡老阿姨 | 亚洲国产高清在线观看视频 | 无码av免费一区二区三区试看 | 少妇无套内谢久久久久 | 亚洲aⅴ无码成人网站国产app | 牛和人交xxxx欧美 | 国产亚洲精品久久久闺蜜 | 精品无码一区二区三区爱欲 | 亚洲男人av香蕉爽爽爽爽 | 久久99精品久久久久婷婷 | 免费无码午夜福利片69 | 美女极度色诱视频国产 | 免费观看又污又黄的网站 | 亚洲欧美日韩综合久久久 | 欧美高清在线精品一区 | 国产明星裸体无码xxxx视频 | 午夜福利电影 | 狂野欧美性猛交免费视频 | 高清国产亚洲精品自在久久 | 98国产精品综合一区二区三区 | 亚洲自偷自拍另类第1页 | 99riav国产精品视频 | 国产精品久久精品三级 | 成人性做爰aaa片免费看 | 又色又爽又黄的美女裸体网站 | 少妇无码一区二区二三区 | 一个人看的www免费视频在线观看 | 六月丁香婷婷色狠狠久久 | 精品国产成人一区二区三区 | 97夜夜澡人人爽人人喊中国片 | 蜜臀aⅴ国产精品久久久国产老师 | 一本久道高清无码视频 | 日韩欧美中文字幕公布 | 亚洲精品午夜国产va久久成人 | 欧美精品免费观看二区 | 1000部啪啪未满十八勿入下载 | 欧美日韩精品 | 成人精品视频一区二区三区尤物 | 国产精品无码mv在线观看 | 色综合久久久久综合一本到桃花网 | 久久亚洲国产成人精品性色 | 成熟人妻av无码专区 | 亚洲精品国产品国语在线观看 | 中文无码伦av中文字幕 | 久久精品国产99久久6动漫 | 欧美三级a做爰在线观看 | 亚洲爆乳无码专区 | 久久久久久国产精品无码下载 | 国产尤物精品视频 | 网友自拍区视频精品 | 国产无遮挡吃胸膜奶免费看 | 亚洲精品久久久久avwww潮水 | 国精产品一区二区三区 | 色五月五月丁香亚洲综合网 | 精品久久综合1区2区3区激情 | 国产两女互慰高潮视频在线观看 | 欧美大屁股xxxxhd黑色 | 国内综合精品午夜久久资源 | 国产精品二区一区二区aⅴ污介绍 | 国产麻豆精品精东影业av网站 | 欧美日韩精品 | 欧美35页视频在线观看 | 精品偷自拍另类在线观看 | 欧美阿v高清资源不卡在线播放 | 中文字幕无码av激情不卡 | 国产精品福利视频导航 | 久久综合久久自在自线精品自 | 久久久精品人妻久久影视 | 色婷婷久久一区二区三区麻豆 | 国产精品理论片在线观看 | 老子影院午夜伦不卡 | 一本色道久久综合狠狠躁 | 国产亚洲tv在线观看 | 亚洲精品国偷拍自产在线观看蜜桃 | 亚洲 高清 成人 动漫 | 六十路熟妇乱子伦 | 精品水蜜桃久久久久久久 | 精品国产一区二区三区四区在线看 | 国产一区二区不卡老阿姨 | 日本护士xxxxhd少妇 | 51国偷自产一区二区三区 | 狂野欧美性猛xxxx乱大交 | 国内精品久久久久久中文字幕 | 国产亚洲人成a在线v网站 | 丰满少妇熟乱xxxxx视频 | 99国产欧美久久久精品 | 亚洲国产精品一区二区美利坚 | 无遮挡啪啪摇乳动态图 | 水蜜桃色314在线观看 | 丰满少妇熟乱xxxxx视频 | av小次郎收藏 | 精品国精品国产自在久国产87 | 狠狠cao日日穞夜夜穞av | 美女毛片一区二区三区四区 | 国产一区二区三区精品视频 | 亚洲a无码综合a国产av中文 | 最近的中文字幕在线看视频 | 国产午夜亚洲精品不卡下载 | 亚洲色无码一区二区三区 | 乱码午夜-极国产极内射 | 国产农村妇女高潮大叫 | 人人妻人人澡人人爽欧美精品 | 国产午夜亚洲精品不卡 | 国产精品资源一区二区 | 亚洲色大成网站www国产 | 久久精品国产一区二区三区肥胖 | 一本加勒比波多野结衣 | 亚洲国产欧美日韩精品一区二区三区 | 国产成人无码一二三区视频 | 国产成人精品三级麻豆 | 国产精品美女久久久 | 国产激情一区二区三区 | 久久国内精品自在自线 | 99久久久无码国产精品免费 | 国产高潮视频在线观看 | 鲁一鲁av2019在线 | 99re在线播放 | 色欲久久久天天天综合网精品 | 日日麻批免费40分钟无码 | 小鲜肉自慰网站xnxx | 国产熟妇高潮叫床视频播放 | 亚拍精品一区二区三区探花 | 领导边摸边吃奶边做爽在线观看 | 精品一区二区三区无码免费视频 | 国产午夜福利100集发布 | 午夜精品久久久久久久久 | 国产精品视频免费播放 | 亚洲综合色区中文字幕 | 国产黄在线观看免费观看不卡 | 日韩亚洲欧美精品综合 | 亚洲色欲色欲天天天www | 亚洲日韩一区二区三区 | 国产人妖乱国产精品人妖 | 久久久久免费精品国产 | 国产精品.xx视频.xxtv | 中文字幕无码日韩欧毛 | 亚洲人成影院在线观看 | 国产av剧情md精品麻豆 | 国产舌乚八伦偷品w中 | 99久久精品日本一区二区免费 | 欧美性生交活xxxxxdddd | 亚洲人成人无码网www国产 | 国产极品美女高潮无套在线观看 | 成人亚洲精品久久久久软件 | 日本丰满熟妇videos | 成人女人看片免费视频放人 | 国产成人精品无码播放 | 国产午夜手机精彩视频 | 人妻中文无码久热丝袜 | 久久精品女人的天堂av | 高潮毛片无遮挡高清免费视频 | 久久亚洲国产成人精品性色 | 女人被男人爽到呻吟的视频 | 国産精品久久久久久久 | 日本一卡2卡3卡四卡精品网站 | 国产精品美女久久久网av | 88国产精品欧美一区二区三区 | 国产精品欧美成人 | 欧美黑人巨大xxxxx | 精品无码一区二区三区爱欲 | 免费男性肉肉影院 | 国产午夜手机精彩视频 | 性色av无码免费一区二区三区 | 曰韩无码二三区中文字幕 | 国产成人无码av片在线观看不卡 | 最近免费中文字幕中文高清百度 | 99久久精品日本一区二区免费 | 亚洲一区二区三区无码久久 | 天天摸天天透天天添 | 性生交片免费无码看人 | 国产成人无码一二三区视频 | 丰满岳乱妇在线观看中字无码 | 久久久久av无码免费网 | 无码吃奶揉捏奶头高潮视频 | 亚洲s码欧洲m码国产av | 国内精品久久久久久中文字幕 | 国产人妻精品一区二区三区 | 亚洲国精产品一二二线 | 黄网在线观看免费网站 | 亚洲经典千人经典日产 | 欧美freesex黑人又粗又大 | 亚洲日本va中文字幕 | 熟妇人妻无乱码中文字幕 | 国产成人精品久久亚洲高清不卡 | 午夜时刻免费入口 | 亚洲人成影院在线无码按摩店 | 四十如虎的丰满熟妇啪啪 | 色婷婷欧美在线播放内射 | 少妇愉情理伦片bd | 18黄暴禁片在线观看 | 97色伦图片97综合影院 | 国产口爆吞精在线视频 | 黑人玩弄人妻中文在线 | 学生妹亚洲一区二区 | 4hu四虎永久在线观看 | 国产精品毛多多水多 | 国产精品爱久久久久久久 | 国产三级精品三级男人的天堂 | 中文毛片无遮挡高清免费 | 精品午夜福利在线观看 | 亚洲va中文字幕无码久久不卡 | 亚洲中文字幕av在天堂 | 青青青手机频在线观看 | 国产黄在线观看免费观看不卡 | 无码毛片视频一区二区本码 | 精品厕所偷拍各类美女tp嘘嘘 | 亚洲色偷偷偷综合网 | 久久天天躁夜夜躁狠狠 | 午夜精品一区二区三区的区别 | 久久午夜夜伦鲁鲁片无码免费 | 亚洲成av人片天堂网无码】 | 国产精品对白交换视频 | 无码人妻精品一区二区三区不卡 | 女人被爽到呻吟gif动态图视看 | 亚洲精品一区二区三区婷婷月 | 亚洲国产精品久久人人爱 | 2020久久超碰国产精品最新 | 日日橹狠狠爱欧美视频 | 亚洲男人av香蕉爽爽爽爽 | 99在线 | 亚洲 | 国产疯狂伦交大片 | 乱人伦人妻中文字幕无码 | 亚洲综合另类小说色区 | 欧美老熟妇乱xxxxx | 国产色精品久久人妻 | 久久久精品欧美一区二区免费 | 88国产精品欧美一区二区三区 | 国产亚洲人成a在线v网站 | 国产精品久久国产三级国 | 亚洲色欲色欲欲www在线 | 人人超人人超碰超国产 | 夜夜高潮次次欢爽av女 | 无码人妻精品一区二区三区不卡 | 亚洲国产欧美在线成人 | 亚洲欧美日韩成人高清在线一区 | 无码人妻丰满熟妇区毛片18 | 1000部夫妻午夜免费 | 精品欧洲av无码一区二区三区 | 亚洲国产精品成人久久蜜臀 | 国产精品久久久久久亚洲毛片 | 暴力强奷在线播放无码 | 无码免费一区二区三区 | 无码人妻丰满熟妇区毛片18 | 日本熟妇大屁股人妻 | 2019午夜福利不卡片在线 | 人人妻人人藻人人爽欧美一区 | 成人无码精品1区2区3区免费看 | 丰满少妇熟乱xxxxx视频 | 久久久久成人精品免费播放动漫 | 中国大陆精品视频xxxx | 樱花草在线社区www | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 黄网在线观看免费网站 | 国产片av国语在线观看 | 国产在线精品一区二区高清不卡 | 高潮喷水的毛片 | 人妻插b视频一区二区三区 | 久久99精品国产.久久久久 | 亚洲小说春色综合另类 | 玩弄人妻少妇500系列视频 | 男女作爱免费网站 | 国产亚洲精品久久久久久 | 久久久久免费看成人影片 | 露脸叫床粗话东北少妇 | 1000部夫妻午夜免费 | 少妇高潮一区二区三区99 | 噜噜噜亚洲色成人网站 | 国产精品久久久久影院嫩草 | 欧美日韩综合一区二区三区 | 免费人成网站视频在线观看 | 日韩人妻少妇一区二区三区 | 久久久久久亚洲精品a片成人 | 亚洲色在线无码国产精品不卡 | 少妇久久久久久人妻无码 | 欧美亚洲国产一区二区三区 | 狠狠噜狠狠狠狠丁香五月 | 亚洲va中文字幕无码久久不卡 | 中文字幕无码av激情不卡 | 欧美性猛交内射兽交老熟妇 | 久久久久免费看成人影片 | 久久精品人人做人人综合 | √天堂中文官网8在线 | 久久久中文久久久无码 | 亚洲人成影院在线无码按摩店 | 久久综合狠狠综合久久综合88 | 亚洲自偷精品视频自拍 | 日韩精品无码一区二区中文字幕 | 亚洲日韩一区二区三区 | 精品国产国产综合精品 | 国产精品亚洲lv粉色 | 国产精品人人妻人人爽 | 亚洲 高清 成人 动漫 | 午夜精品一区二区三区在线观看 | 乱人伦人妻中文字幕无码久久网 | 国产成人综合色在线观看网站 | 99视频精品全部免费免费观看 | 国产无遮挡吃胸膜奶免费看 | 国产精品亚洲а∨无码播放麻豆 | 日韩亚洲欧美精品综合 | 性生交大片免费看l | 大地资源网第二页免费观看 | 无遮挡啪啪摇乳动态图 | 高中生自慰www网站 | 成人试看120秒体验区 | 欧美日韩一区二区三区自拍 | 色一情一乱一伦一区二区三欧美 | 久久99精品久久久久久动态图 | 青草视频在线播放 | 免费无码肉片在线观看 | 国产美女精品一区二区三区 | 久久99精品国产麻豆蜜芽 | 任你躁国产自任一区二区三区 | 一本精品99久久精品77 | 色五月五月丁香亚洲综合网 | 色一情一乱一伦 | 亚洲男人av香蕉爽爽爽爽 | 亚洲中文字幕无码中字 | 久精品国产欧美亚洲色aⅴ大片 | 成人无码影片精品久久久 | 国产日产欧产精品精品app | 亚洲一区二区观看播放 | 久久99精品国产麻豆 | 狂野欧美性猛xxxx乱大交 | 国产区女主播在线观看 | 中文字幕无码日韩专区 | 东北女人啪啪对白 | 国产日产欧产精品精品app | 国产九九九九九九九a片 | 久久久久久九九精品久 | 中文久久乱码一区二区 | 国产三级久久久精品麻豆三级 | 欧美激情内射喷水高潮 | 麻豆国产人妻欲求不满 | 国产亚洲日韩欧美另类第八页 | 亚洲 欧美 激情 小说 另类 | 国产又粗又硬又大爽黄老大爷视 | 波多野结衣乳巨码无在线观看 | 久久亚洲日韩精品一区二区三区 | 好爽又高潮了毛片免费下载 | a片免费视频在线观看 | 一本无码人妻在中文字幕免费 | 99久久精品无码一区二区毛片 | 亚洲经典千人经典日产 | 欧美 日韩 亚洲 在线 | 久久精品99久久香蕉国产色戒 | 波多野42部无码喷潮在线 | 亚洲中文字幕久久无码 | 亚洲精品久久久久avwww潮水 | 性色av无码免费一区二区三区 | 97精品人妻一区二区三区香蕉 | 性啪啪chinese东北女人 | 亚洲第一无码av无码专区 | 国产成人精品视频ⅴa片软件竹菊 | 无码人妻少妇伦在线电影 | 国产va免费精品观看 | 国产97色在线 | 免 | 国产成人精品久久亚洲高清不卡 | 国产成人一区二区三区别 | 国产无遮挡又黄又爽又色 | 亚洲一区二区三区在线观看网站 | 亚洲阿v天堂在线 | 中文字幕乱妇无码av在线 | 亚洲色偷偷男人的天堂 | 对白脏话肉麻粗话av | 人妻aⅴ无码一区二区三区 | 久久精品国产99久久6动漫 | 大地资源中文第3页 | 青青青手机频在线观看 | 香蕉久久久久久av成人 | 国产精品内射视频免费 | 久久久久99精品成人片 | 久久国产精品_国产精品 | 久久久精品人妻久久影视 | 中文字幕av无码一区二区三区电影 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 特大黑人娇小亚洲女 | 青草视频在线播放 | 国产片av国语在线观看 | 亚洲无人区午夜福利码高清完整版 | 人妻天天爽夜夜爽一区二区 | 中文字幕乱码亚洲无线三区 | 午夜肉伦伦影院 | 亚洲va中文字幕无码久久不卡 | 欧洲熟妇色 欧美 | 成人试看120秒体验区 | 中文精品无码中文字幕无码专区 | 亚洲中文字幕乱码av波多ji | av无码不卡在线观看免费 | 免费无码午夜福利片69 | 99久久人妻精品免费一区 | 国产无av码在线观看 | 日韩精品无码一区二区中文字幕 | 亲嘴扒胸摸屁股激烈网站 | 一本久久a久久精品vr综合 | 131美女爱做视频 | 久久久久久久久蜜桃 | 牲交欧美兽交欧美 | 亚洲自偷自偷在线制服 | 欧美freesex黑人又粗又大 | 精品无码一区二区三区的天堂 | 大地资源中文第3页 | 小sao货水好多真紧h无码视频 | 国产成人综合在线女婷五月99播放 | 领导边摸边吃奶边做爽在线观看 | 亚洲成av人综合在线观看 | 国产激情无码一区二区 | 少妇人妻偷人精品无码视频 | 图片区 小说区 区 亚洲五月 | 人妻少妇精品无码专区动漫 | 荫蒂添的好舒服视频囗交 | 国产真人无遮挡作爱免费视频 | av人摸人人人澡人人超碰下载 | 98国产精品综合一区二区三区 | 亚洲国产精品一区二区美利坚 | 久久综合狠狠综合久久综合88 | 精品人人妻人人澡人人爽人人 | 人妻尝试又大又粗久久 | 在线成人www免费观看视频 | 久在线观看福利视频 | 无码人妻精品一区二区三区不卡 | 曰本女人与公拘交酡免费视频 | 亚洲欧美精品aaaaaa片 | 欧美野外疯狂做受xxxx高潮 | 午夜精品一区二区三区的区别 | 亚洲日韩av一区二区三区四区 | 国产凸凹视频一区二区 | 日韩av无码一区二区三区不卡 | 熟女俱乐部五十路六十路av | 久久人人爽人人爽人人片ⅴ | 亚洲欧美日韩成人高清在线一区 | 亚洲va欧美va天堂v国产综合 | 欧美一区二区三区 | 天堂在线观看www | 久久午夜无码鲁丝片 | 一区二区传媒有限公司 | 亚洲春色在线视频 | 美女毛片一区二区三区四区 | 99久久精品无码一区二区毛片 | 人妻与老人中文字幕 | 国产激情一区二区三区 | 国产av人人夜夜澡人人爽麻豆 | 色爱情人网站 | 免费网站看v片在线18禁无码 | 中文字幕中文有码在线 | 亚洲国产精品一区二区美利坚 | 国产在线精品一区二区高清不卡 | 免费无码一区二区三区蜜桃大 | 国产成人精品视频ⅴa片软件竹菊 | 色婷婷av一区二区三区之红樱桃 | 99久久精品国产一区二区蜜芽 | 丰满人妻精品国产99aⅴ | 暴力强奷在线播放无码 | 成人无码精品1区2区3区免费看 | 国产精品久久国产精品99 | 人妻尝试又大又粗久久 | 国产色视频一区二区三区 | 欧美人妻一区二区三区 | 亚洲一区二区三区含羞草 | 久久久精品456亚洲影院 | 亚洲一区二区三区播放 | 午夜无码区在线观看 | 好男人社区资源 | 2019nv天堂香蕉在线观看 | 97久久超碰中文字幕 | 色综合久久88色综合天天 | 亚洲经典千人经典日产 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 未满成年国产在线观看 | 中文字幕精品av一区二区五区 | 少妇太爽了在线观看 | 色五月丁香五月综合五月 | 亚洲色欲久久久综合网东京热 | 99久久99久久免费精品蜜桃 | 国产激情精品一区二区三区 | 亚洲日韩一区二区三区 | 亚洲精品午夜无码电影网 | 国产成人综合在线女婷五月99播放 | 色诱久久久久综合网ywww | 亚洲欧美精品aaaaaa片 | 亚洲欧美国产精品久久 | 国产成人无码区免费内射一片色欲 | 亚洲人成网站色7799 | 国产卡一卡二卡三 | 性色欲网站人妻丰满中文久久不卡 | 亚洲va欧美va天堂v国产综合 | 精品无人国产偷自产在线 | 免费观看的无遮挡av | 亚洲国产一区二区三区在线观看 | 国产亲子乱弄免费视频 | 日本又色又爽又黄的a片18禁 | 免费国产成人高清在线观看网站 | 国产免费观看黄av片 | 国产黄在线观看免费观看不卡 | 亚洲中文字幕成人无码 | 精品乱子伦一区二区三区 | 日本精品人妻无码77777 天堂一区人妻无码 | 久久久久久a亚洲欧洲av冫 | 亚洲中文字幕在线无码一区二区 | 国产成人无码av在线影院 | 自拍偷自拍亚洲精品被多人伦好爽 | 国产一区二区三区四区五区加勒比 | 无码av岛国片在线播放 | 中文亚洲成a人片在线观看 | 精品 日韩 国产 欧美 视频 | 97精品国产97久久久久久免费 | 人人妻人人藻人人爽欧美一区 | 夜夜影院未满十八勿进 | a在线亚洲男人的天堂 | 撕开奶罩揉吮奶头视频 | 男人扒开女人内裤强吻桶进去 | 一本色道婷婷久久欧美 | 国产精品99爱免费视频 | 少妇高潮喷潮久久久影院 | 国产精品久久久一区二区三区 | 日韩成人一区二区三区在线观看 | 精品一区二区不卡无码av | 久久99精品久久久久久动态图 | 人妻少妇被猛烈进入中文字幕 | 久久成人a毛片免费观看网站 | 国产精品第一区揄拍无码 | 国产偷国产偷精品高清尤物 | 国产av一区二区精品久久凹凸 | 欧美性生交活xxxxxdddd | 狠狠亚洲超碰狼人久久 | 欧洲熟妇色 欧美 | 妺妺窝人体色www婷婷 | 中文字幕人成乱码熟女app | 中文字幕乱码亚洲无线三区 | a片免费视频在线观看 | 女人色极品影院 | 美女张开腿让人桶 | 欧美成人免费全部网站 | 亚洲中文无码av永久不收费 | 99久久精品国产一区二区蜜芽 | 久久精品视频在线看15 | 乱码午夜-极国产极内射 | 精品少妇爆乳无码av无码专区 | 国产精品-区区久久久狼 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 日本熟妇浓毛 | 扒开双腿疯狂进出爽爽爽视频 | 男人的天堂2018无码 | 影音先锋中文字幕无码 | 兔费看少妇性l交大片免费 | 国产97在线 | 亚洲 | 色综合久久久久综合一本到桃花网 | 无码人妻出轨黑人中文字幕 | 欧美黑人巨大xxxxx | 丰满少妇弄高潮了www | 欧美性黑人极品hd | 3d动漫精品啪啪一区二区中 | 97精品国产97久久久久久免费 | 午夜福利一区二区三区在线观看 | 亚洲gv猛男gv无码男同 | 日韩欧美中文字幕公布 | 国産精品久久久久久久 | 亚洲中文字幕乱码av波多ji | 欧美一区二区三区视频在线观看 | 99久久久国产精品无码免费 | 国产高潮视频在线观看 | 真人与拘做受免费视频一 | 图片区 小说区 区 亚洲五月 | 鲁鲁鲁爽爽爽在线视频观看 | 国产疯狂伦交大片 | 国产精品无码一区二区三区不卡 | 欧美乱妇无乱码大黄a片 | 中国女人内谢69xxxx | 无码播放一区二区三区 | 午夜精品久久久久久久久 | 一本一道久久综合久久 | 国内揄拍国内精品人妻 | 色婷婷久久一区二区三区麻豆 | 又粗又大又硬又长又爽 | 亚洲精品一区二区三区大桥未久 | 激情亚洲一区国产精品 | 无码任你躁久久久久久久 | 一个人看的视频www在线 | 女人被爽到呻吟gif动态图视看 | 午夜精品久久久久久久 | 国产极品视觉盛宴 | 国产精品爱久久久久久久 | 天天躁日日躁狠狠躁免费麻豆 | 四虎国产精品免费久久 | 亚洲欧美精品aaaaaa片 | 国内精品久久久久久中文字幕 | 无遮挡啪啪摇乳动态图 | 欧美 日韩 亚洲 在线 | 国产亚洲精品久久久ai换 | 久久久国产一区二区三区 | 国产亚洲精品久久久久久久久动漫 | 精品人妻av区 | av人摸人人人澡人人超碰下载 | www国产亚洲精品久久网站 | 国产99久久精品一区二区 | 亚洲精品综合一区二区三区在线 | 日日麻批免费40分钟无码 | 精品 日韩 国产 欧美 视频 | 亚洲国产精品久久人人爱 | 又大又硬又黄的免费视频 | 国产色xx群视频射精 | 亚洲精品中文字幕乱码 | 国产免费观看黄av片 | 四虎国产精品免费久久 | 久久天天躁狠狠躁夜夜免费观看 | 国产高潮视频在线观看 | 国产亚洲美女精品久久久2020 | 午夜精品一区二区三区在线观看 | 亚洲国产精品一区二区第一页 | 久久zyz资源站无码中文动漫 | 亚洲国产成人a精品不卡在线 | 女人色极品影院 | 国产国语老龄妇女a片 | 小sao货水好多真紧h无码视频 | 国产亲子乱弄免费视频 | 99久久99久久免费精品蜜桃 | 大肉大捧一进一出好爽视频 | 国产综合久久久久鬼色 | 国产午夜亚洲精品不卡 | 大屁股大乳丰满人妻 | 人人妻人人澡人人爽人人精品 | 18禁黄网站男男禁片免费观看 | 精品成人av一区二区三区 | 亚洲成av人影院在线观看 | 免费人成在线视频无码 | 野外少妇愉情中文字幕 | 日韩精品无码免费一区二区三区 | 大乳丰满人妻中文字幕日本 | 久久99精品久久久久久动态图 | 日产精品99久久久久久 | 精品久久久中文字幕人妻 | 亚洲国产日韩a在线播放 | 亚洲日韩中文字幕在线播放 | 欧美老熟妇乱xxxxx | 丁香花在线影院观看在线播放 | 亚洲色大成网站www国产 | 未满小14洗澡无码视频网站 | 精品久久久久久亚洲精品 | 中文字幕无码av激情不卡 | 久久亚洲国产成人精品性色 | 亚洲中文字幕无码一久久区 | 日本精品高清一区二区 | 免费网站看v片在线18禁无码 | 午夜精品一区二区三区的区别 | 欧美熟妇另类久久久久久多毛 | 亚洲一区av无码专区在线观看 | 鲁鲁鲁爽爽爽在线视频观看 | 日韩欧美群交p片內射中文 | 九九久久精品国产免费看小说 | 性啪啪chinese东北女人 | 粉嫩少妇内射浓精videos | 色欲综合久久中文字幕网 | 国内精品一区二区三区不卡 | 婷婷五月综合激情中文字幕 | 粗大的内捧猛烈进出视频 | 少妇久久久久久人妻无码 | 天堂一区人妻无码 | 亚洲精品综合一区二区三区在线 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 蜜桃视频韩日免费播放 | 国语精品一区二区三区 | 精品日本一区二区三区在线观看 | 亚洲综合久久一区二区 | 国产97色在线 | 免 | 亚洲中文字幕无码一久久区 | 美女极度色诱视频国产 | 日日摸夜夜摸狠狠摸婷婷 | 久久99国产综合精品 | 成在人线av无码免观看麻豆 | 自拍偷自拍亚洲精品被多人伦好爽 | 亚洲成在人网站无码天堂 | 天天做天天爱天天爽综合网 | 亚洲精品久久久久久久久久久 | 日本护士毛茸茸高潮 | 精品国产一区二区三区四区在线看 | 精品少妇爆乳无码av无码专区 | 国产精品无码一区二区三区不卡 | 乱人伦中文视频在线观看 | 波多野结衣aⅴ在线 | 三级4级全黄60分钟 | 丝袜 中出 制服 人妻 美腿 | 久久99热只有频精品8 | 在线欧美精品一区二区三区 | 国产精品高潮呻吟av久久4虎 | 国产精品无码成人午夜电影 | 夫妻免费无码v看片 | 中文字幕久久久久人妻 | 亚洲国产高清在线观看视频 | 鲁大师影院在线观看 | 中文字幕无码免费久久99 | 久久99精品久久久久久 | 国产免费久久久久久无码 | 人妻插b视频一区二区三区 | 欧美成人午夜精品久久久 | 亚洲啪av永久无码精品放毛片 | 久久久久se色偷偷亚洲精品av | 亚洲综合无码久久精品综合 | 久久久久av无码免费网 | 西西人体www44rt大胆高清 | 国精品人妻无码一区二区三区蜜柚 | 亚洲日本va午夜在线电影 | 亚洲中文字幕在线无码一区二区 | 97精品国产97久久久久久免费 | 中文字幕无码日韩专区 | 国产激情无码一区二区app | 中文字幕av无码一区二区三区电影 | 奇米综合四色77777久久 东京无码熟妇人妻av在线网址 | 久久这里只有精品视频9 | 玩弄人妻少妇500系列视频 | 亚洲欧美日韩成人高清在线一区 | 人人妻人人澡人人爽人人精品浪潮 | 免费无码av一区二区 | 性生交大片免费看l | 中文字幕无码人妻少妇免费 | 性欧美牲交xxxxx视频 | 欧美丰满熟妇xxxx性ppx人交 | а天堂中文在线官网 | 美女毛片一区二区三区四区 | 久久人人爽人人爽人人片ⅴ | 一本久道高清无码视频 | 强开小婷嫩苞又嫩又紧视频 | 亚洲成av人片天堂网无码】 | www国产亚洲精品久久久日本 | 国产无遮挡吃胸膜奶免费看 | 麻豆蜜桃av蜜臀av色欲av | 麻豆国产人妻欲求不满 | 亚洲精品美女久久久久久久 | 久久精品99久久香蕉国产色戒 | 欧美熟妇另类久久久久久不卡 | 内射巨臀欧美在线视频 | 荫蒂添的好舒服视频囗交 | 日本一区二区三区免费播放 | 欧美激情一区二区三区成人 | 熟妇激情内射com | 一区二区三区乱码在线 | 欧洲 | 成在人线av无码免观看麻豆 | 青春草在线视频免费观看 | 激情国产av做激情国产爱 | 亚洲精品美女久久久久久久 | 国产精品无套呻吟在线 | 亚洲第一网站男人都懂 | 国产精品久久久久久无码 | 伊人久久大香线焦av综合影院 | 欧美黑人巨大xxxxx | 噜噜噜亚洲色成人网站 | 丰满人妻翻云覆雨呻吟视频 | 狠狠躁日日躁夜夜躁2020 | 18无码粉嫩小泬无套在线观看 | 亚洲精品成a人在线观看 | 黄网在线观看免费网站 | 久久99精品国产.久久久久 | 欧美日韩人成综合在线播放 | 51国偷自产一区二区三区 | 成人精品视频一区二区三区尤物 | 国产午夜福利100集发布 | 国产两女互慰高潮视频在线观看 | 人妻夜夜爽天天爽三区 | 亚洲国产日韩a在线播放 | 久久无码专区国产精品s | 人人超人人超碰超国产 | 国语精品一区二区三区 | 好爽又高潮了毛片免费下载 | 一本久久a久久精品vr综合 | 午夜成人1000部免费视频 | 精品一二三区久久aaa片 | av香港经典三级级 在线 | 人妻中文无码久热丝袜 | 波多野结衣一区二区三区av免费 | 综合网日日天干夜夜久久 | 国产免费久久久久久无码 | 蜜桃无码一区二区三区 | 中文精品久久久久人妻不卡 | 亚洲欧美国产精品久久 | 女人高潮内射99精品 | 国产熟妇高潮叫床视频播放 | 狂野欧美性猛xxxx乱大交 | 成人亚洲精品久久久久软件 | 午夜福利一区二区三区在线观看 | 久久精品国产一区二区三区 | 福利一区二区三区视频在线观看 | 亚洲啪av永久无码精品放毛片 | 中文字幕av日韩精品一区二区 | 黄网在线观看免费网站 | 国产深夜福利视频在线 | 国产情侣作爱视频免费观看 | 欧美猛少妇色xxxxx | 精品无码国产一区二区三区av | 国产无套粉嫩白浆在线 | 久精品国产欧美亚洲色aⅴ大片 | 国产区女主播在线观看 | 亚洲精品成a人在线观看 | 一区二区传媒有限公司 | 精品人妻av区 | 97精品人妻一区二区三区香蕉 | 无码av岛国片在线播放 | 国产午夜无码精品免费看 | 亚洲精品久久久久中文第一幕 | 亚洲日韩精品欧美一区二区 | 色欲av亚洲一区无码少妇 | 无码播放一区二区三区 | 亚洲色欲久久久综合网东京热 | 婷婷丁香六月激情综合啪 | 国产真人无遮挡作爱免费视频 | 日本成熟视频免费视频 | 99久久精品国产一区二区蜜芽 | 亚洲国产av精品一区二区蜜芽 | 午夜福利一区二区三区在线观看 | 中文字幕日韩精品一区二区三区 | 岛国片人妻三上悠亚 | 午夜无码区在线观看 | 国产成人人人97超碰超爽8 | 色一情一乱一伦一视频免费看 | 给我免费的视频在线观看 | 97精品人妻一区二区三区香蕉 | 成人性做爰aaa片免费看 | 俄罗斯老熟妇色xxxx | 免费观看激色视频网站 | 久久综合九色综合97网 | 熟妇女人妻丰满少妇中文字幕 | 88国产精品欧美一区二区三区 | 四虎影视成人永久免费观看视频 | 少妇人妻av毛片在线看 | 午夜精品一区二区三区在线观看 | 精品久久久无码人妻字幂 | 女人被爽到呻吟gif动态图视看 | 国产成人亚洲综合无码 | 99久久精品日本一区二区免费 | 久久久精品人妻久久影视 | 欧美激情综合亚洲一二区 | 久久熟妇人妻午夜寂寞影院 | 精品少妇爆乳无码av无码专区 | www一区二区www免费 | 澳门永久av免费网站 | 国产乱人伦av在线无码 | av人摸人人人澡人人超碰下载 | 亚无码乱人伦一区二区 | 亚洲精品一区三区三区在线观看 | 无码乱肉视频免费大全合集 | 自拍偷自拍亚洲精品被多人伦好爽 | 国产一精品一av一免费 | 在线a亚洲视频播放在线观看 | 国产av久久久久精东av | 亚洲无人区午夜福利码高清完整版 | 给我免费的视频在线观看 | 中文字幕无码热在线视频 | 久久久久99精品国产片 | 国产精品va在线观看无码 | 人妻少妇精品无码专区动漫 | 国产激情综合五月久久 | 欧美放荡的少妇 | 亚洲人成网站免费播放 | 中文字幕av无码一区二区三区电影 | 亚洲精品中文字幕久久久久 | 少妇人妻偷人精品无码视频 | 久久亚洲a片com人成 | 久久精品女人天堂av免费观看 | 亚洲aⅴ无码成人网站国产app | 99久久99久久免费精品蜜桃 | 久久精品女人的天堂av | 亚洲精品国产第一综合99久久 | 欧美日本免费一区二区三区 | 国产极品视觉盛宴 | 午夜无码区在线观看 | 九九综合va免费看 | 人妻少妇被猛烈进入中文字幕 | 天下第一社区视频www日本 | 久久精品女人的天堂av | 无码国产乱人伦偷精品视频 | 无码国模国产在线观看 | 欧洲vodafone精品性 | 国产亚洲精品久久久久久国模美 | 天干天干啦夜天干天2017 | 乱人伦人妻中文字幕无码久久网 | 成人精品天堂一区二区三区 | 久久99精品久久久久久动态图 | 正在播放东北夫妻内射 | 国产农村妇女高潮大叫 | 天天av天天av天天透 | 亚洲一区二区三区在线观看网站 | 欧美大屁股xxxxhd黑色 | 亚洲国产成人av在线观看 | 国色天香社区在线视频 | 国产人妻人伦精品 | 亚洲熟妇色xxxxx欧美老妇 | 精品久久久无码人妻字幂 | 色婷婷综合激情综在线播放 | 久久无码人妻影院 | 伊人久久大香线蕉午夜 | 国产在线aaa片一区二区99 | aⅴ亚洲 日韩 色 图网站 播放 | 国产精品内射视频免费 | a片免费视频在线观看 | 亚洲成色www久久网站 | 88国产精品欧美一区二区三区 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 在线成人www免费观看视频 | 又色又爽又黄的美女裸体网站 | a片在线免费观看 | 性欧美熟妇videofreesex | 中文字幕 亚洲精品 第1页 | 欧美 丝袜 自拍 制服 另类 | 少妇被黑人到高潮喷出白浆 | 天干天干啦夜天干天2017 | 精品乱码久久久久久久 | 色综合久久中文娱乐网 | 欧美日韩人成综合在线播放 | ass日本丰满熟妇pics | 亚洲国产欧美日韩精品一区二区三区 | 午夜精品一区二区三区的区别 | 色诱久久久久综合网ywww | 国内精品久久久久久中文字幕 | 性色欲情网站iwww九文堂 | 午夜成人1000部免费视频 | 亚洲精品一区二区三区在线观看 | 亚洲 激情 小说 另类 欧美 | 2020久久香蕉国产线看观看 | 亚洲人成网站在线播放942 | 国产乱码精品一品二品 | 人人澡人摸人人添 | 色五月丁香五月综合五月 | 欧洲美熟女乱又伦 | 偷窥日本少妇撒尿chinese | 日产精品99久久久久久 | а√天堂www在线天堂小说 | 粉嫩少妇内射浓精videos | 中文字幕无码日韩欧毛 | 成在人线av无码免观看麻豆 | 人妻体内射精一区二区三四 | 亚洲中文字幕在线无码一区二区 | 高清无码午夜福利视频 | 乱人伦人妻中文字幕无码久久网 | 国产成人精品久久亚洲高清不卡 | 国产熟妇另类久久久久 | 奇米影视7777久久精品人人爽 | 日本丰满护士爆乳xxxx | 精品水蜜桃久久久久久久 | 亚洲国产精品美女久久久久 | 久久综合给合久久狠狠狠97色 | 国产人妻精品一区二区三区 | 欧美人与物videos另类 | 在教室伦流澡到高潮hnp视频 | 欧美成人家庭影院 | 无码精品人妻一区二区三区av | 国产精品内射视频免费 | √天堂中文官网8在线 | 亚洲中文字幕成人无码 | 精品欧洲av无码一区二区三区 | 欧美怡红院免费全部视频 | 亚洲欧美日韩成人高清在线一区 | 三上悠亚人妻中文字幕在线 | 国产尤物精品视频 | 99re在线播放 | 日韩精品无码一区二区中文字幕 | 国产人妻大战黑人第1集 | 午夜丰满少妇性开放视频 | 国产精品久久久久7777 | 亚洲国产一区二区三区在线观看 | 亚洲国产成人a精品不卡在线 | 国产精品无套呻吟在线 | 亚洲性无码av中文字幕 | 人人妻人人澡人人爽欧美一区 | 亚洲区小说区激情区图片区 | 欧美精品免费观看二区 | 亚洲人成影院在线无码按摩店 | 午夜成人1000部免费视频 | 亚洲精品午夜国产va久久成人 | 55夜色66夜色国产精品视频 | 国产精品va在线观看无码 | 国精品人妻无码一区二区三区蜜柚 | 国产高清不卡无码视频 | 日本爽爽爽爽爽爽在线观看免 | 国产精品美女久久久久av爽李琼 | 中文字幕av伊人av无码av | 牲交欧美兽交欧美 | 日日碰狠狠躁久久躁蜜桃 | 蜜桃av抽搐高潮一区二区 | 亚洲男人av香蕉爽爽爽爽 | 麻豆md0077饥渴少妇 | 亚洲 另类 在线 欧美 制服 | 国精产品一品二品国精品69xx | 麻豆国产人妻欲求不满 | 少妇无码av无码专区在线观看 | 亚洲男人av香蕉爽爽爽爽 | 日韩欧美成人免费观看 | 自拍偷自拍亚洲精品被多人伦好爽 | 国产两女互慰高潮视频在线观看 | 粗大的内捧猛烈进出视频 | 国产成人久久精品流白浆 | 狂野欧美性猛xxxx乱大交 | 国产黄在线观看免费观看不卡 | 精品国产乱码久久久久乱码 | 成在人线av无码免观看麻豆 | 青青青爽视频在线观看 | 久久国产36精品色熟妇 | 国产电影无码午夜在线播放 | 九一九色国产 | 日韩无码专区 | 中文字幕日韩精品一区二区三区 | 人人妻人人澡人人爽精品欧美 | 日本免费一区二区三区最新 | 国产成人精品一区二区在线小狼 | 国产精品手机免费 | 国产精品第一国产精品 | 蜜臀aⅴ国产精品久久久国产老师 | 无码国模国产在线观看 | 亚洲国产午夜精品理论片 | 日本一卡2卡3卡四卡精品网站 | 国模大胆一区二区三区 | 无码人妻av免费一区二区三区 | 中国女人内谢69xxxx | 中文字幕无码日韩专区 | 夜夜躁日日躁狠狠久久av | 精品国产一区二区三区四区在线看 | 国产av一区二区三区最新精品 | 嫩b人妻精品一区二区三区 | 国产在线无码精品电影网 | 久久综合色之久久综合 | 天堂а√在线中文在线 | 亚无码乱人伦一区二区 | 久久zyz资源站无码中文动漫 | 久久久精品456亚洲影院 | 久久精品国产亚洲精品 | 久久久精品人妻久久影视 | 日本饥渴人妻欲求不满 | 国产美女精品一区二区三区 | 日本欧美一区二区三区乱码 | 久久久久久av无码免费看大片 | 久久综合色之久久综合 | 亚洲中文字幕久久无码 | 国产免费久久精品国产传媒 | 国产精品久久久久无码av色戒 | 中文字幕人妻丝袜二区 | 四十如虎的丰满熟妇啪啪 | 欧美激情一区二区三区成人 | 中文字幕乱码人妻无码久久 | 正在播放老肥熟妇露脸 | 草草网站影院白丝内射 | 国产成人综合在线女婷五月99播放 | 一本精品99久久精品77 | 久精品国产欧美亚洲色aⅴ大片 | 麻豆国产97在线 | 欧洲 | 人妻少妇精品无码专区二区 | 人人妻人人藻人人爽欧美一区 | 国产偷自视频区视频 | 偷窥日本少妇撒尿chinese | 欧美怡红院免费全部视频 | 特黄特色大片免费播放器图片 | 亚洲精品国产a久久久久久 | 国产亚洲精品久久久久久国模美 | 中文字幕乱码中文乱码51精品 | 国产在线精品一区二区高清不卡 | 亚洲理论电影在线观看 | 99精品无人区乱码1区2区3区 | 日韩无套无码精品 | 国产小呦泬泬99精品 | 曰韩少妇内射免费播放 | 日韩成人一区二区三区在线观看 | 窝窝午夜理论片影院 | 精品国产一区二区三区四区 | 天下第一社区视频www日本 | 鲁大师影院在线观看 | 国产亚洲日韩欧美另类第八页 | 色综合天天综合狠狠爱 | 国产成人av免费观看 | 久久精品女人天堂av免费观看 | 久久伊人色av天堂九九小黄鸭 | 中文字幕无码视频专区 | 麻花豆传媒剧国产免费mv在线 | 亚洲日韩一区二区三区 | 中文字幕乱码人妻二区三区 | 国产精品美女久久久 | 亚洲一区二区三区无码久久 | 亚洲欧洲中文日韩av乱码 | 国产又爽又黄又刺激的视频 | 国产精品怡红院永久免费 | 久久熟妇人妻午夜寂寞影院 | av香港经典三级级 在线 | 亚洲成色www久久网站 | 亚洲人成影院在线无码按摩店 | 国内少妇偷人精品视频免费 | 人人超人人超碰超国产 | 熟女少妇人妻中文字幕 | 亚洲熟妇色xxxxx亚洲 | 国语自产偷拍精品视频偷 | 十八禁真人啪啪免费网站 | 麻豆果冻传媒2021精品传媒一区下载 | 国产激情无码一区二区 | 三上悠亚人妻中文字幕在线 | 少妇激情av一区二区 | 欧美三级a做爰在线观看 | 欧美日本免费一区二区三区 | 精品久久久久香蕉网 | 国产精品人妻一区二区三区四 | 国产成人无码av片在线观看不卡 | 国产精品人人爽人人做我的可爱 | 亚洲熟妇色xxxxx欧美老妇y | 国产真人无遮挡作爱免费视频 | 国产口爆吞精在线视频 | 纯爱无遮挡h肉动漫在线播放 | 成 人影片 免费观看 | 成人精品天堂一区二区三区 | 国产舌乚八伦偷品w中 | 人人妻人人澡人人爽欧美精品 | 亚洲成熟女人毛毛耸耸多 | 国产人妻精品一区二区三区不卡 | 国产成人无码a区在线观看视频app | 色一情一乱一伦一区二区三欧美 | 永久免费精品精品永久-夜色 | 精品成人av一区二区三区 | 精品水蜜桃久久久久久久 | 黑人大群体交免费视频 | 男女猛烈xx00免费视频试看 | 精品久久久久久人妻无码中文字幕 | 亚洲熟悉妇女xxx妇女av | 波多野结衣 黑人 | 无码帝国www无码专区色综合 | 亚洲精品无码国产 | 动漫av网站免费观看 | 国产激情综合五月久久 | 一本加勒比波多野结衣 | 成 人影片 免费观看 | 日本一卡2卡3卡四卡精品网站 | 色情久久久av熟女人妻网站 | 久久视频在线观看精品 | 青草视频在线播放 | 亚洲精品一区二区三区婷婷月 | 久久久亚洲欧洲日产国码αv | 国产色精品久久人妻 | 精品无码国产自产拍在线观看蜜 | 国产亚av手机在线观看 | 图片小说视频一区二区 | 国产偷国产偷精品高清尤物 | 欧洲精品码一区二区三区免费看 | 国产精品人妻一区二区三区四 | 99久久精品日本一区二区免费 | 正在播放老肥熟妇露脸 | 2020久久香蕉国产线看观看 | 日本熟妇人妻xxxxx人hd | 国产激情综合五月久久 | 青春草在线视频免费观看 | 亚洲综合另类小说色区 | 国产成人综合在线女婷五月99播放 | 真人与拘做受免费视频一 | 天堂а√在线中文在线 |