<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          熱文 | 卷積神經(jīng)網(wǎng)絡(luò)入門案例,輕松實現(xiàn)花朵分類

          共 17989字,需瀏覽 36分鐘

           ·

          2021-05-15 01:30



          作者 | 黎國溥
          責(zé)編 | 寇雪芹
          出品 | AI 科技大本營(ID:rgznai100)

          前言
          本文介紹卷積神經(jīng)網(wǎng)絡(luò)的入門案例,通過搭建和訓(xùn)練一個模型,來對幾種常見的花朵進行識別分類;使用到TF的花朵數(shù)據(jù)集,它包含5類,即:“雛菊”,“蒲公英”,“玫瑰”,“向日葵”,“郁金香”;共 3670 張彩色圖片;通過搭建和訓(xùn)練卷積神經(jīng)網(wǎng)絡(luò)模型,對圖像進行分類,能識別出圖像是“蒲公英”,或“玫瑰”,還是其它。
          本篇文章主要的意義是帶大家熟悉卷積神經(jīng)網(wǎng)絡(luò)的開發(fā)流程,包括數(shù)據(jù)集處理、搭建模型、訓(xùn)練模型、使用模型等;更重要的是解在訓(xùn)練模型時遇到“過擬合”,如何解決這個問題,從而得到“泛化”更好的模型。
          思路流程
          • 導(dǎo)入數(shù)據(jù)集

          • 探索集數(shù)據(jù),并進行數(shù)據(jù)預(yù)處理

          • 構(gòu)建模型(搭建神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)、編譯模型)

          • 訓(xùn)練模型(把數(shù)據(jù)輸入模型、評估準確性、作出預(yù)測、驗證預(yù)測)  

          • 使用訓(xùn)練好的模型

          • 優(yōu)化模型、重新構(gòu)建模型、訓(xùn)練模型、使用模型


          目錄
          1. 導(dǎo)入數(shù)據(jù)集

          2. 探索集數(shù)據(jù),并進行數(shù)據(jù)預(yù)處理

          3. 構(gòu)建模型

          4. 訓(xùn)練模型

          5. 使用模型

          6. 優(yōu)化模型、重新構(gòu)建模型、訓(xùn)練模型、使用模型過擬合、數(shù)據(jù)增強、正則化、重新編譯和訓(xùn)練模型、預(yù)測新數(shù)據(jù))



          導(dǎo)入數(shù)據(jù)集

          使用到TF的花朵數(shù)據(jù)集,它包含5類,即:“雛菊”,“蒲公英”,“玫瑰”,“向日葵”,“郁金香”;共 3670 張彩色圖片;數(shù)據(jù)集包含5個子目錄,每個子目錄種存放一個類別的花朵圖片。
          # 下載數(shù)據(jù)集
          import pathlib
          dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
          data_dir = tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)
          data_dir = pathlib.Path(data_dir)

          # 查看數(shù)據(jù)集圖片的總數(shù)量
          image_count = len(list(data_dir.glob('*/*.jpg')))
          print(image_count)

          探索集數(shù)據(jù),并進行數(shù)據(jù)預(yù)處理

          查看一張郁金香的圖片: 
          # 查看郁金香tulips目錄下的第1張圖片;
          tulips = list(data_dir.glob('tulips/*'))
          PIL.Image.open(str(tulips[0]))
          加載數(shù)據(jù)集的圖片,使用keras.preprocessing從磁盤上加載這些圖像。
          # 定義加載圖片的一些參數(shù),包括:批量大小、圖像高度、圖像寬度
          batch_size = 32
          img_height = 180
          img_width = 180

          # 將80%的圖像用于訓(xùn)練
          train_ds = tf.keras.preprocessing.image_dataset_from_directory(
            data_dir,
            validation_split=0.2,
            subset="training",
            seed=123,
            image_size=(img_height, img_width),
            batch_size=batch_size)

          # 將20%的圖像用于驗證
          val_ds = tf.keras.preprocessing.image_dataset_from_directory(
            data_dir,
            validation_split=0.2,
            subset="validation",
            seed=123,
            image_size=(img_height, img_width),
            batch_size=batch_size)

          # 打印數(shù)據(jù)集中花朵的類別名稱,字母順序?qū)?yīng)于目錄名稱
          class_names = train_ds.class_names
          print(class_names)

          查看一下訓(xùn)練數(shù)據(jù)集中的9張圖像
          # 查看一下訓(xùn)練數(shù)據(jù)集中的9張圖像
          import matplotlib.pyplot as plt

          plt.figure(figsize=(1010))
          for images, labels in train_ds.take(1):
            for i in range(9):
              ax = plt.subplot(33, i + 1)
              plt.imshow(images[i].numpy().astype("uint8"))
              plt.title(class_names[labels[i]])
              plt.axis("off")

          圖像形狀
          傳遞這些數(shù)據(jù)集來訓(xùn)練模型model.fit,可以手動遍歷數(shù)據(jù)集并檢索成批圖像:
          for image_batch, labels_batch in train_ds:
            print(image_batch.shape)
            print(labels_batch.shape)
            break
          能看到輸出:(32, 180, 180, 3)   (32,)
          image_batch是圖片形狀的張量(32, 180, 180, 3)。32是指批量大小;180,180分別表示圖像的高度、寬度,3是顏色通道RGB。32張圖片組成一個批次。
          label_batch是形狀的張量(32,),對應(yīng)32張圖片的標簽。
          數(shù)據(jù)集預(yù)處理
          下面進行數(shù)據(jù)集預(yù)處理,將像素的值標準化至0到1的區(qū)間內(nèi):
          # 將像素的值標準化至0到1的區(qū)間內(nèi)。
          normalization_layer = layers.experimental.preprocessing.Rescaling(1./255)
          為什么是除以255呢?由于圖片的像素范圍是0~255,我們把它變成0~1的范圍,于是每張圖像(訓(xùn)練集、測試集)都除以255。
          標準化數(shù)據(jù)
          # 調(diào)用map將其應(yīng)用于數(shù)據(jù)集:
          normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
          image_batch, labels_batch = next(iter(normalized_ds))
          first_image = image_batch[0]
          # Notice the pixels values are now in `[0,1]`.
          print(np.min(first_image), np.max(first_image))

          構(gòu)建模型

          常見卷積神經(jīng)網(wǎng)絡(luò)(CNN),主要由幾個 卷積層Conv2D 和 池化層MaxPooling2D 層組成。卷積層與池化層的疊加實現(xiàn)對輸入數(shù)據(jù)的特征提取,最后連接全連接層實現(xiàn)分類。
          • 特征提取——卷積層與池化層

          • 實現(xiàn)分類——全連接層

          CNN 的輸入是張量 (Tensor) 形式的 (image_height, image_width, color_channels),包含了圖像高度、寬度及顏色信息。通常圖像使用 RGB 色彩模式,color_channels 為 (R,G,B) 分別對應(yīng) RGB 的三個顏色通道,即:image_height 和 image_width 根據(jù)圖像的像素高度、寬度決定color_channels是3,對應(yīng)RGB的3通道。
          花朵數(shù)據(jù)集中的圖片,形狀是 (180, 180, 3),我們可以在聲明第一層時將形狀賦值給參數(shù) input_shape 。
          num_classes = 5

          model = Sequential([
            layers.experimental.preprocessing.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
            layers.Conv2D(163, padding='same', activation='relu'),
            layers.MaxPooling2D(),
            layers.Conv2D(323, padding='same', activation='relu'),
            layers.MaxPooling2D(),
            layers.Conv2D(643, padding='same', activation='relu'),
            layers.MaxPooling2D(),
            layers.Flatten(),
            layers.Dense(128, activation='relu'),
            layers.Dense(num_classes)
          ])

          該模型由三個卷積塊組成,每個卷積塊中包括2D卷積層+最大池化層。最后有一個全連接層,有128個單元,可以通過relu激活功能激活該層。
          編譯模型
          model.compile(optimizer='adam',
                        loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                        metrics=['accuracy'])
          查看一下網(wǎng)絡(luò)模型:tf.keras.utils.plot_model(model) ,或者用這樣方式看看:model.summary()

          訓(xùn)練模型

          這里我們輸入準備好的訓(xùn)練集數(shù)據(jù)(包括圖像、對應(yīng)的標簽),測試集的數(shù)據(jù)(包括圖像、對應(yīng)的標簽),模型一共訓(xùn)練10次。

          epochs=10
          history = model.fit(
            train_ds,
            validation_data=val_ds,
            epochs=epochs
          )

          下圖是訓(xùn)練過程的截圖:
          通常loss越小越好,對了解釋下什么是loss;簡單來說是 模型預(yù)測值 和 真實值 的相差的值,反映模型預(yù)測的結(jié)果和真實值的相差程度;通常準確度accuracy 越高,模型效果越好。
          評估模型
          在訓(xùn)練和驗證集上創(chuàng)建損失和準確性圖。
          acc = history.history['accuracy']
          val_acc = history.history['val_accuracy']

          loss = history.history['loss']
          val_loss = history.history['val_loss']

          epochs_range = range(epochs)

          plt.figure(figsize=(88))
          plt.subplot(121)
          plt.plot(epochs_range, acc, label='Training Accuracy')
          plt.plot(epochs_range, val_acc, label='Validation Accuracy')
          plt.legend(loc='lower right')
          plt.title('Training and Validation Accuracy')

          plt.subplot(122)
          plt.plot(epochs_range, loss, label='Training Loss')
          plt.plot(epochs_range, val_loss, label='Validation Loss')
          plt.legend(loc='upper right')
          plt.title('Training and Validation Loss')
          plt.show()
          從圖中可以看出,訓(xùn)練精度和驗證精度相差很大,模型僅在驗證集上獲得了約60%的精度。
          訓(xùn)練精度隨時間增長,而驗證精度在訓(xùn)練過程中停滯在60%左右。訓(xùn)練和驗證準確性之間的準確性差異很明顯,這是過擬合的標志。
          可能過擬合出現(xiàn)的原因 :當訓(xùn)練示例數(shù)量很少時,像這次的只有3000多張圖片,該模型有時會從訓(xùn)練示例中的噪音或不必要的細節(jié)中學(xué)習(xí),從而模型在新示例上的性能產(chǎn)生負面影響。 

          使用模型

          通常使用 model.predict( )  函數(shù)進行預(yù)測。 

          優(yōu)化模型、重新構(gòu)建模型、訓(xùn)練模型、使用模型

          這里的優(yōu)化模型,主要是針對模型出現(xiàn)“過擬合”的問題。
          過擬合
          模型將過度擬合訓(xùn)練數(shù)據(jù),在訓(xùn)練集上達到較高的準確性,但在未見的數(shù)據(jù)(測試集)上得到比較低的準確性;模型的“泛化能力”不足。
          我們訓(xùn)練模型的主要目的,也是希望模型在未見數(shù)據(jù)的預(yù)測上能有較高的準確性;解決過擬合問題是比較重要的。
          解決過擬合的思路
          • 使用更完整的訓(xùn)練數(shù)據(jù)。(最好的解決方案)

          • 使用正則化之類的技術(shù)。

          • 簡化神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)。

          使用更完整的訓(xùn)練數(shù)據(jù),數(shù)據(jù)集應(yīng)涵蓋模型應(yīng)處理的所有輸入范圍。僅當涉及新的有趣案例時,其他數(shù)據(jù)才有用。
          比如:在訓(xùn)練集的花朵圖片都是近距離拍攝的,測試集的花朵有部分是遠距離拍攝,訓(xùn)練出來的模型,自然在測試集的準確度不高了;如果一開始在訓(xùn)練集也包含部分遠距離的花朵圖片,那么模型在測試集時準確度會較高,基本和訓(xùn)練集的準確度接近。
          使用正規(guī)化等技術(shù),這些限制了模型可以存儲的信息的數(shù)量和類型。如果一個網(wǎng)絡(luò)只能記住少量的模式,優(yōu)化過程將迫使它專注于最突出的模式,這些模式更有可能很好地概括。
          簡化神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu),如果訓(xùn)練集比較小,網(wǎng)絡(luò)結(jié)構(gòu)又十分復(fù)雜,使得模型過度擬合訓(xùn)練數(shù)據(jù),這時需要考慮簡化模型了。減少一些神經(jīng)元數(shù)量,或減少一些網(wǎng)絡(luò)層。
          結(jié)合上面的例子,使用數(shù)據(jù)增強和正則化技術(shù),來優(yōu)化網(wǎng)絡(luò)。
          數(shù)據(jù)增強
          通過對已有的訓(xùn)練集圖片 隨機轉(zhuǎn)換(反轉(zhuǎn)、旋轉(zhuǎn)、縮放等),來生成其它訓(xùn)練數(shù)據(jù)。這有助于將模型暴露在數(shù)據(jù)的更多方面,并更好地概括。
          這里使用 tf.layers.experimental.preprocessing 層實現(xiàn)數(shù)據(jù)增強。
          data_augmentation = keras.Sequential(
            [
              layers.experimental.preprocessing.RandomFlip("horizontal"
                                                           input_shape=(img_height, 
                                                                        img_width,
                                                                        3)),
              layers.experimental.preprocessing.RandomRotation(0.1),
              layers.experimental.preprocessing.RandomZoom(0.1),
            ]
          )

          RandomFlip("horizontal", input_shape=(img_height,  img_width, 3)) 指定輸入圖片,并對圖片進行隨機水平反轉(zhuǎn)
          RandomRotation(0.1) 對圖片進行隨機旋轉(zhuǎn)
          RandomZoom(0.1)     對圖片進行隨機縮放
          通過將數(shù)據(jù)增強應(yīng)用到同一圖像中幾次來可視化幾個增強示例的外觀:
          plt.figure(figsize=(1010))
          for images, _ in train_ds.take(1):
            for i in range(9):
              augmented_images 
          = data_augmentation(images)
              ax = plt.subplot(33, i + 1)
              plt.imshow(augmented_images[0].numpy().astype("uint8"))
              plt.axis("off")
           
          正則化
          正則化的方法有多種,這里使用 Dropout 應(yīng)用到網(wǎng)絡(luò)層中,它會隨機將一部分神經(jīng)元的激活值停止工作,在訓(xùn)練過程中從該層中暫時退出,從而不對輸出產(chǎn)生影響;后續(xù)訓(xùn)練先恢復(fù)之前被停止工作的神經(jīng)元,再隨機將一部分神經(jīng)元停止工作,再訓(xùn)練。
          這樣使模型不會太依賴某些局部的特征,泛化性更強。a圖全連接結(jié)構(gòu)的模型。b圖是在a網(wǎng)絡(luò)結(jié)構(gòu)基礎(chǔ)上,使用 Dropout后,隨機將一部分神經(jīng)元的暫時停止工作。
          訓(xùn)練流程:
          首先隨機(臨時)刪除網(wǎng)絡(luò)中一些的隱藏層神經(jīng)元(退出此次訓(xùn)練),輸入輸出神經(jīng)元保存不變。
          然后把輸入x通過修改后的網(wǎng)絡(luò)前向傳播,得到的損失結(jié)果通過修改后的網(wǎng)絡(luò)反向傳播;一批訓(xùn)練樣本執(zhí)行完這個過程后,在沒有被刪除的神經(jīng)元上按照梯度下降法更新對應(yīng)的參數(shù)(w, b)。
          最后重復(fù)1、2步過程。恢復(fù)被刪掉的神經(jīng)元,此時被刪除的神經(jīng)元保持原樣,而沒有被刪除的神經(jīng)元已經(jīng)更新相關(guān)參數(shù)。
          參考:Dropout(正則化)
          Dropout 以一小部分數(shù)字作為其輸入值,形式為 0.1、0.2、0.4 等。使得此層的10%、20%、40%的神經(jīng)元被暫時停止工作。
          下面使用:layers.Dropout(0.2)
          model = Sequential([
            data_augmentation,
            layers.experimental.preprocessing.Rescaling(1./255),
            layers.Conv2D(163, padding='same', activation='relu'),
            layers.MaxPooling2D(),
            layers.Conv2D(323, padding='same', activation='relu'),
            layers.MaxPooling2D(),
            layers.Conv2D(643, padding='same', activation='relu'),
            layers.MaxPooling2D(),
            layers.Dropout(0.2),
            layers.Flatten(),
            layers.Dense(128, activation='relu'),
            layers.Dense(num_classes)
          ])

          重新編譯和訓(xùn)練模型
          # 編譯模型
          model.compile(optimizer='adam',
                        loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                        metrics=['accuracy'])
          # 查看網(wǎng)絡(luò)結(jié)構(gòu)
          model.summary()
          # 訓(xùn)練模型
          epochs = 15
          history = model.fit(
            train_ds,
            validation_data=val_ds,
            epochs=epochs
          )

          在訓(xùn)練和驗證集上查看損失值和準確性:
          acc = history.history['accuracy']
          val_acc = history.history['val_accuracy']

          loss = history.history['loss']
          val_loss = history.history['val_loss']

          epochs_range = range(epochs)

          plt.figure(figsize=(88))
          plt.subplot(121)
          plt.plot(epochs_range, acc, label='Training Accuracy')
          plt.plot(epochs_range, val_acc, label='Validation Accuracy')
          plt.legend(loc='lower right')
          plt.title('Training and Validation Accuracy')

          plt.subplot(122)
          plt.plot(epochs_range, loss, label='Training Loss')
          plt.plot(epochs_range, val_loss, label='Validation Loss')
          plt.legend(loc='upper right')
          plt.title('Training and Validation Loss')
          plt.show()

          對比之前模型的效果,差別還是挺大的;使用數(shù)據(jù)增強、正則化后的模型,降低了過擬合的影響;驗證集的損失和模型準確度,與訓(xùn)練集更接近了。
          預(yù)測新數(shù)據(jù)
          # 預(yù)測新數(shù)據(jù) 下載一張新圖片,來預(yù)測它屬于什么類型花朵
          sunflower_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/592px-Red_sunflower.jpg"
          sunflower_path = tf.keras.utils.get_file('Red_sunflower', origin=sunflower_url)

          img = keras.preprocessing.image.load_img(
              sunflower_path, target_size=(img_height, img_width)
          )
          img_array = keras.preprocessing.image.img_to_array(img)
          img_array = tf.expand_dims(img_array, 0) # Create a batch

          predictions = model.predict(img_array)
          score = tf.nn.softmax(predictions[0])

          print(
              "該圖像最有可能屬于{},置信度為 {:.2f}%"
              .format(class_names[np.argmax(score)], 100 * np.max(score))
          )
          該圖像最有可能屬于sunflowers,置信度為 97.38%
          完整代碼
          '''
          環(huán)境:Tensorflow2 Python3.x
          '''


          import matplotlib.pyplot as plt
          import numpy as np
          import os
          import PIL
          import tensorflow as tf

          from tensorflow import keras
          from tensorflow.keras import layers
          from tensorflow.keras.models import Sequential

          # 下載數(shù)據(jù)集
          import pathlib
          dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
          data_dir = tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)
          data_dir = pathlib.Path(data_dir)

          # 查看數(shù)據(jù)集圖片的總數(shù)量
          image_count = len(list(data_dir.glob('*/*.jpg')))
          print(image_count)

          # 查看郁金香tulips目錄下的第1張圖片;
          tulips = list(data_dir.glob('tulips/*'))
          PIL.Image.open(str(tulips[0]))

          # 定義加載圖片的一些參數(shù),包括:批量大小、圖像高度、圖像寬度
          batch_size = 32
          img_height = 180
          img_width = 180

          # 將80%的圖像用于訓(xùn)練
          train_ds = tf.keras.preprocessing.image_dataset_from_directory(
            data_dir,
            validation_split=0.2,
            subset="training",
            seed=123,
            image_size=(img_height, img_width),
            batch_size=batch_size)

          # 將20%的圖像用于驗證
          val_ds = tf.keras.preprocessing.image_dataset_from_directory(
            data_dir,
            validation_split=0.2,
            subset="validation",
            seed=123,
            image_size=(img_height, img_width),
            batch_size=batch_size)

          # 打印數(shù)據(jù)集中花朵的類別名稱,字母順序?qū)?yīng)于目錄名稱
          class_names = train_ds.class_names
          print(class_names)


          # 將像素的值標準化至0到1的區(qū)間內(nèi)。
          normalization_layer = layers.experimental.preprocessing.Rescaling(1./255)

          # 調(diào)用map將其應(yīng)用于數(shù)據(jù)集:
          normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
          image_batch, labels_batch = next(iter(normalized_ds))
          first_image = image_batch[0]
          # Notice the pixels values are now in `[0,1]`.
          print(np.min(first_image), np.max(first_image))

          # 數(shù)據(jù)增強 通過對已有的訓(xùn)練集圖片 隨機轉(zhuǎn)換(反轉(zhuǎn)、旋轉(zhuǎn)、縮放等),來生成其它訓(xùn)練數(shù)據(jù)
          data_augmentation = keras.Sequential(
            [
              layers.experimental.preprocessing.RandomFlip("horizontal"
                                                           input_shape=(img_height, 
                                                                        img_width,
                                                                        3)),
              layers.experimental.preprocessing.RandomRotation(0.1),
              layers.experimental.preprocessing.RandomZoom(0.1),
            ]
          )

          # 搭建 網(wǎng)絡(luò)模型
          model = Sequential([
            data_augmentation,
            layers.experimental.preprocessing.Rescaling(1./255),
            layers.Conv2D(163, padding='same', activation='relu'),
            layers.MaxPooling2D(),
            layers.Conv2D(323, padding='same', activation='relu'),
            layers.MaxPooling2D(),
            layers.Conv2D(643, padding='same', activation='relu'),
            layers.MaxPooling2D(),
            layers.Dropout(0.2),
            layers.Flatten(),
            layers.Dense(128, activation='relu'),
            layers.Dense(num_classes)
          ])

          # 編譯模型
          model.compile(optimizer='adam',
                        loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                        metrics=['accuracy'])

          # 查看網(wǎng)絡(luò)結(jié)構(gòu)
          model.summary()

          # 訓(xùn)練模型
          epochs = 15
          history = model.fit(
            train_ds,
            validation_data=val_ds,
            epochs=epochs
          )

          # 在訓(xùn)練和驗證集上查看損失值和準確性
          acc = history.history['accuracy']
          val_acc = history.history['val_accuracy']

          loss = history.history['loss']
          val_loss = history.history['val_loss']

          epochs_range = range(epochs)

          plt.figure(figsize=(88))
          plt.subplot(121)
          plt.plot(epochs_range, acc, label='Training Accuracy')
          plt.plot(epochs_range, val_acc, label='Validation Accuracy')
          plt.legend(loc='lower right')
          plt.title('Training and Validation Accuracy')

          plt.subplot(122)
          plt.plot(epochs_range, loss, label='Training Loss')
          plt.plot(epochs_range, val_loss, label='Validation Loss')
          plt.legend(loc='upper right')
          plt.title('Training and Validation Loss')
          plt.show()

          作者簡介:黎國溥,華為云-云享專家、CSDN博客專家、華為云-云創(chuàng)·首席貢獻官、華為云-年度社區(qū)風(fēng)云人物
          參考鏈接:
          https://colab.research.google.com/github/tensorflow/docs/blob/master/site/en/tutorials/images/classification.ipynb#scrollTo=L1WtoaOHVrVh
          原文鏈接:
          https://blog.csdn.net/qq_41204464/article/details/116567051


           End 


          聲明:部分內(nèi)容來源于網(wǎng)絡(luò),僅供讀者學(xué)術(shù)交流之目的。文章版權(quán)歸原作者所有。如有不妥,請聯(lián)系刪除。


          瀏覽 80
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产婷婷久久Av免费高清 | 日韩黄色在线播放 | 日韩AV三级在线观看 | 欧美乱搞乱操视频 | 久久大 |