精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一文搞懂神經網絡模型量化

人工智能
模型量化是一種模型壓縮技術,其核心是將浮點數(如FP32)表示的模型參數轉換為整數(如INT8、INT4)表示。

一、定點和浮點

定點和浮點是兩種不同的數值表示方式,它們的主要區別在于如何處理整數部分和小數部分的分隔點(即“小數點”的位置)。

1. 定點數

小數點的位置是固定的,整數部分和小數部分的位數在表示中是預先確定的。例如,一個16位定點數可以分配為8位整數部分 + 8位小數部分,則數值范圍為。例如,數值 00001000.10010000 表示為十進制:

2. 浮點數

小數點的位置是浮動的,它通過科學計數法的形式來表達實數,包含符號位、指數部分和尾數部分。以單精度浮點數FP32為例,

  • 符號位 (s):1位,表示正負號。
  • 指數部分 (k):8位,表示2的多少次冪(實際使用時需要加上偏移值)。
  • 尾數部分 (M):23位,表示有效數字。

基于上述表示,浮點數的值可以用以下公式計算:

其中:

  • :符號位,決定數值的正負。
  • :尾數部分,表示有效數字。
  • :指數部分,表示2的冪次。

例如,單精度浮點數 0 10000000 10010010000111111011011:

  • 符號位,表示正值。
  • 指數部分(偏移值為127)。
  • 尾數部分(隱含的1在前)。

計算結果為:

二、什么是模型量化?

模型量化是一種模型壓縮技術,其核心是將浮點數(如FP32)表示的模型參數轉換為整數(如INT8、INT4)表示。通過減少每個權重值占用的空間(從32位減少到8位或更少),可以顯著降低模型的存儲需求和計算資源消耗。

三、模型量化優點

1. 減小模型大小

通過量化,模型參數從32位浮點數(FP32)壓縮為8位整數(INT8),模型大小可以減少到原來的1/4。 從而可以:

  • 節省存儲空間:在端側設備(如手機、嵌入式設備)中,存儲空間通常有限。量化后的模型占用更少的空間,更適合部署在這些資源受限的環境中。
  • 降低內存占用:更小的模型意味著在運行時需要更少的內存來加載和處理數據,從而減少了對設備內存的需求。
  • 減少設備功耗:內存占用減少和推理速度提升,直接降低了設備的能耗。這對于電池供電的設備(如手機、無人機等)尤為重要。

2. 加快推理速度

訪問一次32位浮點數的時間可以用來訪問四次8位整數,且整數運算通常比浮點運算更快。特別是在支持INT8加速的硬件(如CPU、DSP、NPU)上,INT8運算的遠超FP32運算。

3. 兼容特定硬件

某些硬件加速器(如DSP、NPU)只支持INT8運算。對于這些設備,量化是必不可少的步驟,以確保模型能夠高效運行。例如,一些微處理器屬于8位架構,運行FP32浮點運算效率低下,而INT8量化可以顯著提升其性

四、業界模型量化實踐

業界一般只使用INT8量化模型,如NCNN、TNN等移動端模型推理框架都支持模型的INT8量化和量化模型的推理功能。以下是兩種常見的量化推理方案:

1. 混合FP32/INT8 推理

在這種方案中,模型本身和輸入/輸出仍采用FP32格式,但在卷積或全連接層等支持量化的算子中插入Quantize和Dequantize層,將數據在FP32和INT8之間進行轉換。具體流程如下:

  • Quantize層:將FP32數據轉換為INT8格式。
  • Dequantize 層:將INT8數據轉換回FP32格式,以支持其他只接受FP32輸入的算子。

這種方案的優點是兼容性強,適用于部分算子尚未完全支持INT8的場景。然而,頻繁的 Quantize 和 Dequantize 操作會帶來額外的開銷。

2. 純INT8推理

隨著技術的發展,越來越多的算子開始支持INT8運算,因此可以將整個網絡轉換為INT8格式,避免了 Quantize 和 Dequantize 的轉換開銷。在這種方案中:

  • 所有數據流均為INT8格式。
  • 算子直接處理INT8數據,無需轉換為FP32。

純INT8推理的優勢在于更高的效率和更低的功耗,但要求所有算子都支持INT8運算。對于不支持的算子,通常會回退到 Quantize/Dequantize 方案。

五、模型量化方案

在實踐中,將浮點模型轉換為量化模型的方法主要分為以下三種:

1. Data Free(無校準集)

不使用校準集,直接將浮點參數轉換為量化數。實現簡單,無需額外的數據或復雜的流程。對于某些特定場景(如高通的DFQ方法),即使不使用校準集,也能達到較高的精度。但是,通常會導致較大的精度損失,因為沒有考慮實際數據分布,不適合對精度要求較高的任務。

2. Calibration(基于校準集)

通過輸入少量真實數據進行統計分析,計算量化參數(如縮放因子S和零點Z)。精度損失較小,能夠更好地適應實際數據分布,很多芯片廠商(如NVIDIA、高通、海思、地平線、寒武紀等)都提供了這種功能。

3. Fine-tune(基于訓練微調)

在訓練過程中模擬量化誤差,并調整權重以使其更適合量化。能夠顯著提升量化后的模型精度,更加靈活,可以根據具體任務需求進行定制化優化。但是需要修改模型訓練代碼,開發周期較長。

六、模型量化分類

根據映射函數是否是線性可以分為兩類——即線性量化和非線性量化,本文主要研究的是線性量化技術。

1. 線性量化

線性量化的過程可以用以下數學表達式來表示:

其中:

  • q表示原始的浮點數值(通常是Float32)。
  • Z表示浮點數值的偏移量(通常稱為 Zero Point)。
  • S表示浮點數值的縮放因子(通常稱為Scale)。
  • Round(?)表示四舍五入近似取整的數學函數,也可以使用向上或向下取整。

根據參數Z是否為零可以將線性量化分為兩類——即對稱量化和非對稱量化。

(1) 對稱量化

對稱量化,即使用一個映射公式將輸入浮點數據映射到[-128,127]的范圍內,圖中-max(|Xf|)表示的是輸入數據的最小值,max(|Xf|)表示輸入數據的最大值。

對稱量化的一個核心即零點的處理,映射公式需要保證原始零點(即輸入浮點數中的0)在量化后依然對應于整數區間的0。總而言之,對稱量化通過映射關系將輸入數據映射在[-128,127]的范圍內,對于映射關系而言,我們需要求解的參數即Z和S。

在對稱量化中,r是用有符號的整型數值(int8)來表示的,此時Z=0,且q=0時恰好有r=0。S的計算公式如下:

其中,

  • n表示用來表示該數值的位寬。
  • max(|x|)表示數據集中所有樣本的絕對值的最大值。

(2) 非對稱量化

非對稱量化,即使用一個映射公式將輸入數據映射到[0,255]的范圍內,圖中min(Xf)表示的是輸入數據的最小值,max(Xf)表示輸入數據的最大值。

對稱量化通過映射關系將輸入數據映射在[0,255]的范圍內,對于映射關系而言,我們需要求解的參數即Z和S。

在非對稱量化中,r 是用有符號的整型數值(uint8)來表示的。可以取Z=min(x),S的計算公式如下:

2. 逐層量化、逐組量化和逐通道量化

根據量化的粒度(即共享量化參數的范圍),可以將量化方法分為逐層量化、逐組量化和逐通道量化。

(1) 逐層量化

以一個層為單位,整個層的所有權重上使用相同的縮放因子 S 和偏移量 Z 。

(2) 逐組量化

將權重按組劃分,每個group使用一組S和Z。

(3) 逐通道量化

以通道為單位,每個channel單獨使用一組S和Z。

當 group=1 時,逐組量化與逐層量化等價;當group=num_filters (即dw卷積)時,逐組量化逐通道量化等價。

3. 在線量化與離線量化

根據激活值的量化方式,可以分為在線量化和離線量化兩種方法。這兩種方法的主要區別在于量化參數(縮放因子S和偏移量Z)是否在實際推理過程中動態計算。

(1) 在線量化

指在實際推理過程中,根據實際的激活值動態計算量化參數S和Z。

(2) 離線量化

離線量化是指提前確定好激活值的量化參數S和Z。這樣,在實際推理時就可以直接使用這些預計算好的參數,而不需要動態計算,從而提高了推理速度。

離線量化通常采用以下幾種方法來確定量化參數:

  • 指數平滑法:將校準數據集送入模型,收集每個量化層的輸出特征圖,計算每個batch的S和Z值,并通過指數平滑法來更新S和Z值。
  • 直方圖截斷法:在計算量化參數S和Z的過程中,考慮到有些特征圖可能會出現偏離較遠的奇異值,導致最大值非常大。可以采用直方圖截取的形式,比如拋棄最大的前 1% 數據,以前 1% 分界點的數值作為最大值來計算量化參數。
  • KL 散度校準法:通過計算量化前后的兩個分布之間的 KL 散度(也稱為相對熵)來評估這兩個分布之間的差異,以搜索并選取KL散度最小的量化參數Z和S作為最終的結果。

4.比特量化

根據存儲一個權重元素所需的位數,可以將其分為8bit量化、4bit量化、2bit量化和1bit量化。

  • 二進制神經網絡:即在運行時具有二進制權重和激活的神經網絡,以及在訓練時計算參數的梯度。
  • 三元權重網絡:即權重約束為+1,0和-1的神經網絡。
  • XNOR網絡:即過濾器和卷積層的輸入是二進制的。XNOR網絡主要使用二進制運算來近似卷積。

七、模型量化原理詳解

1. 原理詳解

模型量化橋接定點和浮點,建立一種有效的數據映射關系。要弄懂模型量化的原理就要弄懂這種數據映射關系。浮點與定點數據的轉換公式如下:

其中:

  • R表示輸入的浮點數據
  • Q表示量化之后的定點數據
  • Z表示零點(Zero Point)的數值
  • S表示縮放因子(Scale)的數值

根據S和Z這兩個參數來確定這個映射關系。求解 S 和 Z 有很多種方法,這里列舉中其中的一種求解方式(MinMax)如下:

其中,

  • max(R)表示輸入浮點數值的最大值。
  • min(R)表示輸入浮點數值的最小值。
  • max(Q)表示量化之后的整數數值的最大值(127/255)。
  • min(Q)表示量化之后的整數數值的最小值(-128/0)。

每通道或每張量的權重用int8進行定點量化的可表示范圍為[-127,127],且zero-point就是量化值0。

每張量的激活值或輸入值用int8進行定點量化的可表示范圍為[-128,127],其zero-point在[-128,127]內依據公式求得。

2. 具體案例

在這個案例中,我們將展示如何根據給定的激活值范圍 [-2.0, 6.0] 使用 int8 類型進行定點量化的過程。

步驟1: 計算量化尺度S和zero-point Z

量化尺度S的計算公式為:

Zero-point Z的計算公式為:

代入給定的值:

  • 激活值范圍 [-2.0, 6.0],因此 max_val = 6.0 和 min_val = -2.0
  • 定點量化值范圍 [-128, 127],因此 quant_max = 127 和 quant_min = -128

計算得到:

步驟 2: 對激活值進行量化

使用計算出的 S 和 Z 值對一個具體的激活值進行量化。假設有一個真實的激活值R = 0.28,則量化后的值 Q為:

代入S和Z的值:

八、模型量化實現步驟

模型量化具體的執行步驟如下所示:

  • 在量化前,需要先統計出輸入數據(通常是權重或者激活值)中的最小值 min_value 和最大值 max_value。
  • 根據模型的需求選擇合適的量化類型,常見的有對稱量化(int8)和非對稱量化(uint8)。
  • 根據選擇的量化類型,計算量化參數 Z(Zero point)和 S(Scale)。
  • 根據計算出的量化參數 Z 和 S,對模型執行量化操作,即將 FP32 數據轉換為 INT8 數據。
  • 驗證量化后的模型性能是否滿足要求。如果不滿足,可以嘗試使用不同的方式計算 S 和 Z,然后重新執行量化操作。

九、Pytorch模型量化詳解

PyTorch提供了三種量化模型的方法,具體包括訓練后動態量化、訓練后靜態量化和訓練時量化。

1. 訓練后動態量化

訓練后動態量化(Post Training Dynamic Quantization,PTDQ)是最簡單的量化形式,其中權重被提前量化,而激活在推理過程中被動態量化。這種方法用于模型執行時間由從內存加載權重而不是計算矩陣乘法所支配的情況,適合批量較小的LSTM和Transformer模型。步驟如下:

  • 準備模型:將模型設置為評估模式 (model.eval()),對于需要動態量化的模型,通常不需要添加額外的量化或反量化模塊。
  • 量化模型:使用 torch.quantization.quantize_dynamic() 函數來量化模型,這個函數會自動識別模型中適合動態量化的層,并將其轉換為量化版本。

2. 訓練后靜態量化

訓練后靜態量化(Post-Training Static Quantization, PTQ)是最常用的量化形式,其中權重是提前量化的,并且基于在校準過程中觀察模型的行為來預先計算激活張量的比例因子和偏差。CNN是一個典型的用例,訓練后量化通常是在內存帶寬和計算節省都很重要的情況下進行的。訓練后量化的步驟如下:

  • 準備模型:添加 QuantStub 和 DeQuantStub 模塊,以指定在何處顯式量化和反量化激活值。確保不重復使用模塊。將需要重新量化的任何操作轉換為模塊的模式。
  • 融合操作:將諸如 conv + relu 或 conv + batchnorm + relu 之類的組合操作融合在一起,以提高模型的準確性和性能。
  • 指定量化配置:例如選擇對稱或非對稱量化以及MinMax或L2Norm校準技術。
  • 使用 torch.quantization.prepare() 函數來插入觀察模塊,以便在校準期間觀察激活張量。
  • 使用校準數據集對模型執行校準操作。
  • 使用 torch.quantization.convert() 函數來轉換模型。包括計算并存儲每個激活張量要使用的比例和偏差值,并替換關鍵算子的量化實現。

3. 訓練時量化

在某些情況下,訓練后量化不能提供足夠的準確性,這時可以使用訓練時量化(Quantization-Aware Training,QAT)。步驟:

  • 準備模型:添加 QuantStub 和 DeQuantStub 模塊,以指定在何處顯式量化和反量化激活值。確保不重復使用模塊。將需要重新量化的任何操作轉換為模塊的模式。
  • 將諸如 conv + relu 或 conv + batchnorm + relu 之類的組合操作融合在一起,以提高模型的準確性和性能。
  • 指定偽量化配置:例如選擇對稱或非對稱量化以及MinMax或L2Norm校準技術.
  • 用 torch.quantization.prepare_qat() 函數來插入偽量化模塊,以便在訓練過程中模擬量化。
  • 使用標準訓練流程訓練或微調模型。
  • 使用 torch.quantization.convert() 函數來轉換模型,包括計算并存儲每個激活張量要使用的比例和偏差值,并替換關鍵算子的量化實現。

下面是一個簡單的示例,展示了如何使用PyTorch進行模型量化。

# 導入第三方的庫函數
import os
from io import open
import time

import torch
import torch.nn as nn
import torch.quantization
import torch.nn.functional as F

# 創建LSTM模型類
class LSTMModel(nn.Module):
    """整個網絡包含一個encoder, 一個recurrent模塊和一個decoder."""

    def __init__(self, ntoken, ninp, nhid, nlayers, dropout=0.5):
        super(LSTMModel, self).__init__()
        # 預定義一些網絡層
        self.drop = nn.Dropout(dropout)
        # 嵌入層
        self.encoder = nn.Embedding(ntoken, ninp)
        # LSTM層
        self.rnn = nn.LSTM(ninp, nhid, nlayers, dropout=dropout)
        # 線性層
        self.decoder = nn.Linear(nhid, ntoken)
        self.init_weights()
        self.nhid = nhid
        self.nlayers = nlayers

    def init_weights(self):
     '''
     初始化模型權重
     '''
        initrange = 0.1
        self.encoder.weight.data.uniform_(-initrange, initrange)
        self.decoder.bias.data.zero_()
        self.decoder.weight.data.uniform_(-initrange, initrange)

    def forward(self, input, hidden):
     '''
     搭建網絡并執行前向推理
     '''
        emb = self.drop(self.encoder(input))
        output, hidden = self.rnn(emb, hidden)
        output = self.drop(output)
        decoded = self.decoder(output)
        return decoded, hidden

    def init_hidden(self, bsz):
     '''
     初始化hidden層的權重
     '''
        weight = next(self.parameters())
        return (weight.new_zeros(self.nlayers, bsz, self.nhid),
                weight.new_zeros(self.nlayers, bsz, self.nhid))

# 創建一個詞典類,用來處理數據
# 構建詞匯表,包括詞到索引的映射和索引到詞的映射
class Dictionary(object):
    def __init__(self):
        self.word2idx = {}
        self.idx2word = []

    def add_word(self, word):
     '''
     在詞典中添加新的word
     '''
        if word not in self.word2idx:
            self.idx2word.append(word)
            self.word2idx[word] = len(self.idx2word) - 1
        return self.word2idx[word]

    def __len__(self):
     '''
     返回詞典的長度
     '''
        return len(self.idx2word)

#  Corpus 類:處理文本數據,包括讀取文件、構建詞匯表和將文本轉換為索引序列
class Corpus(object):
    def __init__(self, path):
        self.dictionary = Dictionary()
        # 分別獲取訓練集、驗證集和測試集
        self.train = self.tokenize(os.path.join(path, 'train.txt'))
        self.valid = self.tokenize(os.path.join(path, 'valid.txt'))
        self.test = self.tokenize(os.path.join(path, 'test.txt'))

    def tokenize(self, path):
        """對輸入的文件執行分詞操作"""
        assert os.path.exists(path)
        # 將新的單詞添加到詞典中
        with open(path, 'r', encoding="utf8") as f:
            for line in f:
                words = line.split() + ['<eos>']
                for word in words:
                    self.dictionary.add_word(word)

        # 標記文件的內容
        with open(path, 'r', encoding="utf8") as f:
            idss = []
            for line in f:
                words = line.split() + ['<eos>']
                ids = []
                for word in words:
                    ids.append(self.dictionary.word2idx[word])
                idss.append(torch.tensor(ids).type(torch.int64))
            ids = torch.cat(idss)
        return ids

# 設置模型的路徑
model_data_filepath = 'data/'
corpus = Corpus(model_data_filepath + 'wikitext-2')
ntokens = len(corpus.dictionary)

# 搭建網絡模型
model = LSTMModel(
    ntoken = ntokens,
    ninp = 512,
    nhid = 256,
    nlayers = 5,
)

# 加載預訓練的模型權重
model.load_state_dict(
    torch.load(
        model_data_filepath + 'word_language_model_quantize.pth',
        map_location=torch.device('cpu')
        )
    )
# 將模型切換為推理模式,并打印整個模型
model.eval()
print(model)

# 獲取一個隨機的輸入數值
input_ = torch.randint(ntokens, (1, 1), dtype=torch.long)
hidden = model.init_hidden(1)
temperature = 1.0
num_words = 1000

# 遍歷數據集進行前向推理并將結果保存起來
with open(model_data_filepath + 'out.txt', 'w') as outf:
    with torch.no_grad():  # no tracking history
        for i in range(num_words):
            output, hidden = model(input_, hidden)
            word_weights = output.squeeze().div(temperature).exp().cpu()
            word_idx = torch.multinomial(word_weights, 1)[0]
            input_.fill_(word_idx)
            word = corpus.dictionary.idx2word[word_idx]
            outf.write(str(word.encode('utf-8')) + ('\n' if i % 20 == 19 else ' '))
            if i % 100 == 0:
                print('| Generated {}/{} words'.format(i, 1000))

with open(model_data_filepath + 'out.txt', 'r') as outf:
    all_output = outf.read()
    print(all_output)

bptt = 25
criterion = nn.CrossEntropyLoss()
eval_batch_size = 1

# 創建測試數據集
def batchify(data, bsz):
    # 對測試數據集進行分塊
    nbatch = data.size(0) // bsz
    # 去掉多余的元素
    data = data.narrow(0, 0, nbatch * bsz)
    # 在bsz批處理中平均劃分數據
    return data.view(bsz, -1).t().contiguous()

test_data = batchify(corpus.test, eval_batch_size)

# 獲取bath塊的輸入數據
def get_batch(source, i):
    seq_len = min(bptt, len(source) - 1 - i)
    data = source[i:i+seq_len]
    target = source[i+1:i+1+seq_len].view(-1)
    return data, target

def repackage_hidden(h):
  """
  用新的張量把隱藏的狀態包裝起來,把它們從歷史中分離出來
  """
  if isinstance(h, torch.Tensor):
      return h.detach()
  else:
      return tuple(repackage_hidden(v) for v in h)
# 評估函數
def evaluate(model_, data_source):
    # 打開評估模式
    model_.eval()
    total_loss = 0.
    hidden = model_.init_hidden(eval_batch_size)
    with torch.no_grad():
        for i in range(0, data_source.size(0) - 1, bptt):
         # 獲取測試數據
            data, targets = get_batch(data_source, i)
            # 執行前向推理
            output, hidden = model_(data, hidden)
            hidden = repackage_hidden(hidden)
            output_flat = output.view(-1, ntokens)
            # 獲取訓練loss
            total_loss += len(data) * criterion(output_flat, targets).item()
    return total_loss / (len(data_source) - 1)

# 初始化動態量化模塊
quantized_model = torch.quantization.quantize_dynamic(
    model, {nn.LSTM, nn.Linear}, dtype=torch.qint8
)
print(quantized_model)

def print_size_of_model(model):
    torch.save(model.state_dict(), "temp.p")
    print('Size (MB):', os.path.getsize("temp.p")/1e6)
    os.remove('temp.p')

print_size_of_model(model)
print_size_of_model(quantized_model)

torch.set_num_threads(1)
# 評估模型的運行時間
def time_model_evaluation(model, test_data):
    s = time.time()
    loss = evaluate(model, test_data)
    elapsed = time.time() - s
    print('''loss: {0:.3f}\nelapsed time (seconds): {1:.1f}'''.format(loss, elapsed))

time_model_evaluation(model, test_data)
time_model_evaluation(quantized_model, test_data)


責任編輯:趙寧寧 來源: 小喵學AI
相關推薦

2019-11-19 08:00:00

神經網絡AI人工智能

2023-09-17 23:09:24

Transforme深度學習

2017-11-29 13:55:55

神經網絡循環神經網絡RNN

2018-07-29 06:46:07

神經網絡RNN循環神經網絡

2017-04-17 13:10:09

神經網絡人工智能網絡

2020-12-08 20:20:15

神經網絡深度學習機器學習

2020-08-14 10:20:49

神經網絡人工智能池化層

2022-05-05 16:47:24

Docker網絡空間容器

2024-04-12 12:19:08

語言模型AI

2022-03-24 08:51:48

Redis互聯網NoSQL

2019-11-06 17:00:51

深度學習神經網絡人工智能

2019-03-26 19:00:02

神經網絡AI人工智能

2017-07-06 17:03:45

BP算法Python神經網絡

2021-03-22 10:05:59

netstat命令Linux

2023-09-15 12:00:01

API應用程序接口

2023-09-08 08:20:46

ThreadLoca多線程工具

2024-11-05 14:00:56

2024-09-04 16:19:06

語言模型統計語言模型

2017-04-26 14:32:24

神經網絡人工智能對杭樣本

2025-03-12 02:00:00

經營分析模型策略
點贊
收藏

51CTO技術棧公眾號

久久久99久久| 亚洲一区成人| 精品国内片67194| 亚洲熟妇无码另类久久久| 日韩大片b站免费观看直播| 久久一日本道色综合久久| 久久夜色精品国产亚洲aⅴ| 制服丝袜av在线| 免费在线成人激情电影| 中文字幕制服丝袜成人av| 国产成人精品福利一区二区三区| 东京热一区二区三区四区| 91精品一区国产高清在线gif| 亚洲国产日韩欧美在线动漫| 五月婷婷六月丁香激情| 成年人黄色大片在线| 国产精品的网站| 久久本道综合色狠狠五月| 国产又大又长又粗| 亚洲欧美视频一区二区三区| 欧美二区乱c黑人| 岛国片在线免费观看| 女一区二区三区| 在线不卡欧美精品一区二区三区| 亚洲午夜精品久久久久久人妖| 久操视频在线| 国产精品毛片无遮挡高清| 久久久久久久久久码影片| 国产丰满果冻videossex| 视频在线观看国产精品| 精品国产一区二区三区久久狼黑人| 国产精品无码在线| 亚洲精品在线国产| 4438成人网| 一本色道久久亚洲综合精品蜜桃| 中文字幕在线官网| 亚洲h动漫在线| 999久久欧美人妻一区二区| www.av在线| 久久亚洲综合色一区二区三区 | 韩国三级成人在线| 欧美视频在线一区| 午夜免费精品视频| 丝袜美腿诱惑一区二区三区| 午夜精品久久久久| 农民人伦一区二区三区| 牛牛精品在线视频| 亚洲一区二区成人在线观看| 中国黄色录像片| 欧美性天天影视| 国产精品毛片高清在线完整版| 日本一区二区高清视频| 久久电影视频| 91麻豆免费看片| 久久国产精品久久| 欧美美女搞黄| 国产亚洲成aⅴ人片在线观看| 久久艳妇乳肉豪妇荡乳av| 性感美女一级片| 久久综合九色综合97婷婷| 精品视频免费观看| 涩涩视频在线观看免费| 久久久久9999亚洲精品| 日韩欧美99| av天在线观看| 亚洲欧洲成人av每日更新| 一区二区三区四区五区视频| 毛片免费不卡| 一区二区在线免费观看| 免费网站永久免费观看| 欧洲中文在线| 欧美日韩国产一区二区| 欧美国产亚洲精品久久久8v| 国产一区二区精彩视频| 欧美日韩综合| 91超碰caoporn97人人| 天堂中文字幕在线观看| 日韩电影一区二区三区| 成人深夜直播免费观看| 精品欧美一区二区精品少妇| 99久久精品免费看国产免费软件| 久久精品日韩精品| 中国日本在线视频中文字幕| 亚洲精选一二三| 男女视频网站在线观看| 电影久久久久久| 91精品国产91热久久久做人人| 午夜诱惑痒痒网| 成人性生交大片免费看中文视频| 亚洲国产99精品国自产| 玖玖爱在线精品视频| 精品国产一区二区三区小蝌蚪 | 日韩精品黄色网| 国产99在线 | 亚洲| 欧美一区高清| 日本久久久久久| 国产熟女一区二区三区四区| 99视频在线观看一区三区| 日韩视频在线播放| 国精一区二区三区| 欧美日韩视频第一区| 无码国产69精品久久久久网站| 国产午夜一区| 久久久久久国产| 亚洲一级视频在线观看| 粉嫩av一区二区三区粉嫩| 日本精品视频一区| 丁香花电影在线观看完整版| 欧美视频一区二区三区在线观看| 亚洲av无码一区东京热久久| 久久亚洲国产| 日本成人精品在线| 亚洲精品久久久蜜桃动漫 | 亚洲午夜在线观看| 久草在线资源福利站| 日韩一级二级三级| 欧美成人久久久免费播放| 在线亚洲免费| 国产成人亚洲欧美| 超碰在线网址| 欧美日韩国产美女| 黑人巨大精品欧美| 亚洲国产精品一区制服丝袜| 91久久久久久久久| 国产成人天天5g影院在线观看| 亚洲mv在线观看| 免费看91视频| 欧美国产三级| 亚洲精品日韩av| 日本视频不卡| 欧美最猛黑人xxxxx猛交| 国产肉体xxxx裸体784大胆| 午夜电影亚洲| 亚洲一区中文字幕| 日本在线观看| 欧美精品久久久久久久多人混战| 韩国三级hd中文字幕| 噜噜爱69成人精品| 免费成人深夜夜行视频| 久热在线观看视频| 亚洲精品国产精品国自产观看浪潮| 久久久久久国产精品免费播放| 黄色资源网久久资源365| 性刺激综合网| 91九色综合| 在线视频亚洲欧美| 在线视频 91| 一区在线观看免费| 午夜激情视频网| 综合一区av| 91嫩草视频在线观看| 怡红院红怡院欧美aⅴ怡春院| 91精品国产综合久久福利软件| 日本午夜在线观看| 国产乱对白刺激视频不卡| 真人做人试看60分钟免费| gogo久久日韩裸体艺术| 久久久久久久影院| 亚洲区小说区图片区| 欧美性生交大片免费| 精品国产av无码| 天使萌一区二区三区免费观看| 欧洲av一区| 成人国产精选| 欧美成人精品激情在线观看 | 国产91丝袜在线观看| 隔壁人妻偷人bd中字| 欧美大胆视频| 国产精品99久久久久久白浆小说| sese一区| 欧美一级日韩不卡播放免费| 久久免费视频6| 91女神在线视频| 欧美三级理论片| 亚洲国产一区二区在线观看| 国产99午夜精品一区二区三区| 黄色污网站在线观看| 国产香蕉精品视频一区二区三区 | 久久久久免费看| 99久久久久久| 午夜久久福利视频| 激情久久久久| 日韩亚洲不卡在线| 日韩区一区二| 奇米影视亚洲狠狠色| 中国日本在线视频中文字幕| 欧美大片在线观看一区| 亚洲AV无码成人精品区东京热| 国产精品久久久久久久久图文区| 手机在线播放av| 久久精品国语| japanese在线播放| 精品九九在线| 国产精品入口免费| 日本成人在线网站| 91av网站在线播放| 理论片午午伦夜理片在线播放| 亚洲国产91色在线| 国产乱子伦精品无码码专区| 欧美日韩国产影院| 免费在线观看h片| 久久久久99精品一区| 日本一级大毛片a一| 免费看欧美女人艹b| 免费一级特黄特色毛片久久看| 日韩精品一区二区三区免费观影| 国产精品青青草| 日本午夜精品久久久久| 欧美一区二区三区艳史| 国产欧美久久久久久久久| 亚洲毛片一区二区| 丰满人妻一区二区三区四区53| 在线观看日产精品| 日韩特级黄色片| 亚洲一区在线视频| 91香蕉视频在线播放| 欧美韩国日本不卡| 女同毛片一区二区三区| 国产凹凸在线观看一区二区 | 懂色av一区二区三区免费观看 | 日韩欧美国产综合在线| 久久香蕉国产| 亚洲 国产 欧美一区| 日本午夜精品| 国产在线精品日韩| 伊人久久噜噜噜躁狠狠躁| 91欧美日韩一区| 全球最大av网站久久| 国产成人aa精品一区在线播放| 啊啊啊久久久| 国模极品一区二区三区| 污污的视频在线观看| 久久天堂电影网| 欧洲不卡av| 精品国产区一区二区三区在线观看| av在线播放网站| 亚洲人成自拍网站| 美女欧美视频在线观看免费 | jizz性欧美| 久久久av电影| 精品自拍一区| 久久在线免费观看视频| 精产国品自在线www| 久久精品亚洲一区| 91网址在线观看| 欧美国产日韩在线| 91桃色在线| 2019精品视频| 天天免费亚洲黑人免费| 国产成人精品日本亚洲| 亚洲爱爱视频| 国产在线不卡精品| 国产午夜精品一区在线观看 | 美女网站一区| 日韩精品资源| 久久国产亚洲精品| 资源网第一页久久久| 欧美一区二区三区另类| 波多野结衣av一区二区全免费观看| 韩国精品一区二区三区| 欧美黑人经典片免费观看| 久久国产高清| 日韩一级免费片| 国产一区 二区 三区一级| 国产成人精品一区二区三区在线观看| 福利电影一区二区| 玖草视频在线观看| 欧美国产一区视频在线观看| 午夜精品一区二区三区视频| 亚洲专区一二三| 国产精品久久久久久久妇| 91高清在线观看| 国产有码在线观看| 欧美精品一区二区久久婷婷| 青青视频在线观| 久久精品91久久香蕉加勒比| 免费看电影在线| 欧美在线不卡区| 99久久这里有精品| 久久精品国产99精品国产亚洲性色| 国产99久久精品一区二区300| 中国成人在线视频| 亚洲经典三级| www.com黄色片| 成人毛片老司机大片| 亚洲码无人客一区二区三区| 亚洲人成人一区二区在线观看| 国产精品500部| 欧美精品1区2区| 亚洲人成色777777精品音频| 日韩中文字幕在线精品| av资源中文在线天堂| 国产精品男女猛烈高潮激情| www.亚洲一二| 亚洲欧洲免费无码| 国产一区导航| 亚洲国产日韩在线一区| 国产亚洲成av人在线观看导航| 青娱乐91视频| 欧美日韩卡一卡二| 深夜福利免费在线观看| 欧美精品一区三区| 韩日精品一区| 久久国产一区| 日本黄网免费一区二区精品| 好吊一区二区三区| 国产又黄又猛的视频| 26uuu精品一区二区在线观看| 欧美黄色aaa| 欧美性猛交一区二区三区精品| 手机看片福利永久| 欧美成aaa人片免费看| 国产精品久久久久77777丨| 久久综合九九| 激情成人综合| 成人啪啪18免费游戏链接| 国产精品二区一区二区aⅴ污介绍| 久久国产视频精品| 亚洲精品福利视频| 91超碰在线播放| 99在线观看视频| 亚洲先锋影音| 日日干夜夜操s8| 中文字幕国产精品一区二区| 午夜影院免费在线观看| 亚洲精品国产精品国自产观看浪潮| 色呦呦在线视频| 91久久大香伊蕉在人线| 久久久人成影片免费观看| 性生活免费在线观看| 欧美激情自拍偷拍| 波多野结衣不卡| 国产亚洲精品美女| 电影久久久久久| 色爱区成人综合网| 日本vs亚洲vs韩国一区三区| 精品国产无码在线观看| 色综合久久六月婷婷中文字幕| 婷婷五月综合久久中文字幕| 午夜免费久久久久| 噜噜噜狠狠夜夜躁精品仙踪林| 无码 制服 丝袜 国产 另类| 成人性视频免费网站| 久久精品视频8| 国产精品丝袜一区| 亚洲乱码国产乱码精品| 亚洲性视频网址| 激情中国色综合| 永久域名在线精品| 国产一区二区免费在线| 免费一级全黄少妇性色生活片| 精品国产伦理网| 草草影院在线| 蜜桃成人在线| 全国精品久久少妇| 中国一级片在线观看| 欧美一级在线观看| 黄色漫画在线免费看| 欧美福利一区二区三区| 日本欧美在线看| 天天看天天摸天天操| 日韩你懂的在线播放| 国产色播av在线| 欧美午夜免费| 精品一区中文字幕| 久久免费视频播放| 亚洲欧洲第一视频| 涩涩涩久久久成人精品| 人人妻人人澡人人爽欧美一区| 99久久综合精品| 99re热视频| 欧美夫妻性视频| 欧美女王vk| 色婷婷综合在线观看| 亚洲aaa精品| 在线观看精品一区二区三区| 亚洲va欧美va国产综合剧情| 亚洲成人中文| 日本黄色激情视频| 精品99一区二区三区| 国产经典一区| 男人添女荫道口女人有什么感觉| 91女厕偷拍女厕偷拍高清| 国产人妖一区二区| 欧美孕妇孕交黑巨大网站| 香港欧美日韩三级黄色一级电影网站| 国产人妻精品午夜福利免费| 色婷婷香蕉在线一区二区| 91亚洲天堂| 日韩妆和欧美的一区二区| 国产精品羞羞答答xxdd| 免费黄色片视频| 欧美激情第6页| 91视频综合| 免费在线观看成年人视频| 91精品国产欧美一区二区成人| 午夜影院在线观看国产主播| 水蜜桃在线免费观看| 国产午夜亚洲精品理论片色戒 | 99re这里只有精品视频首页|