<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 用 Keras 在 Python 中使用卷積神經網絡進行手寫數字識別 > 原文: [https://machinelearningmastery.com/handwritten-digit-recognition-using-convolutional-neural-networks-python-keras/](https://machinelearningmastery.com/handwritten-digit-recognition-using-convolutional-neural-networks-python-keras/) 圖像數據中的物體識別是深度學習技術的廣泛示例。 用于機器學習和深度學習的物體識別的“hello world”是用于手寫數字識別的 MNIST 數據集。 在這篇文章中,您將了解如何使用 Keras 深度學習庫開發深度學習模型,以便在 Python 中使用 MNIST 手寫數字識別任務實現近乎最優性能。 完成本教程后,您將了解: * 如何在 Keras 中加載 MNIST 數據集。 * 如何開發和評估 MNIST 問題的基線神經網絡模型。 * 如何實現和評估一個簡單的 MNIST 卷積神經網絡。 * 如何實現接近最先進的 MNIST 深度學習模型。 讓我們開始吧! * **2016 年 10 月更新**:更新了 Keras 1.1.0,TensorFlow 0.10.0 和 scikit-learn v0.18 的示例。 * **2017 年 3 月更新**:更新了 Keras 2.0.2,TensorFlow 1.0.1 和 Theano 0.9.0 的示例。 ![Handwritten Digit Recognition using Convolutional Neural Networks in Python with Keras](https://img.kancloud.cn/04/73/0473b5e394ff5e89e93cf78627e4a970_640x426.png) 照片由 [Jamie](https://www.flickr.com/photos/jamiesrabbits/5947373341/)提供,并保留所屬權利。 ## MNIST 手寫數字識別問題的描述 [MNIST](http://yann.lecun.com/exdb/mnist/) 問題是由 Yann LeCun,Corinna Cortes 和 Christopher Burges 開發的用于評估手寫數字分類問題的機器學習模型的數據集。 該數據集由許多可從[國家標準與技術研究所](http://www.nist.gov/)(NIST)獲得的掃描文檔數據集構建。這是數據集作為 Modified NIST 或 MNIST 數據集的名稱來源。 數字圖像取自各種掃描文檔,標準化并居中,這使其成為評估模型的優秀數據集,使開發人員能夠專注于機器學習,只需要很少的數據清理或數據預處理工作。 每個圖像是 28 乘 28 像素的正方形(總共 784 個像素),數據集的標準輸出用于評估和比較模型,其中 60,000 個圖像用于訓練模型,并且有單獨的 10,000 個圖像集用于測試模型。 這是一項數字識別任務,因此,有 10 個數字(0 到 9)或 10 個類來預測,使用預測誤差報告結果,預測誤差僅僅是反向分類精度。 一些優異的成果實現了小于 1%的預測誤差,最先進的方案是使用大型卷積神經網絡可以實現約 0.2%的預測誤差。有一份最新的成果列表,以及有關 MNIST 和 [Rodrigo Benenson 網頁](http://rodrigob.github.io/are_we_there_yet/build/classification_datasets_results.html#4d4e495354)上其他數據集的相關論文的鏈接。 ## 在 Keras 中加載 MNIST 數據集 Keras 深度學習庫提供了一種加載 MNIST 數據集的便捷方法。 第一次調用此函數時會自動下載數據集,并將其作為 15MB 文件存儲在?/ .keras / datasets / mnist.pkl.gz 的主目錄中。 這對于開發和測試深度學習模型非常方便。 為了演示加載 MNIST 數據集是多么容易,我們將首先編寫一個小腳本來下載和可視化訓練數據集中的前 4 個圖像。 ```py # 繪制 ad hoc minst 實例圖像 from keras.datasets import mnist import matplotlib.pyplot as plt # 加載數據集 (X_train, y_train), (X_test, y_test) = mnist.load_data() # 繪制灰度級別的4幅圖像 plt.subplot(221) plt.imshow(X_train[0], cmap=plt.get_cmap('gray')) plt.subplot(222) plt.imshow(X_train[1], cmap=plt.get_cmap('gray')) plt.subplot(223) plt.imshow(X_train[2], cmap=plt.get_cmap('gray')) plt.subplot(224) plt.imshow(X_train[3], cmap=plt.get_cmap('gray')) # 圖像顯示 plt.show() ``` 您可以看到下載和加載 MNIST 數據集就像調用`mnist.load_data()`函數一樣簡單。運行上面的示例,您應該看到以下圖像: ![Examples from the MNIST dataset](https://img.kancloud.cn/99/69/9969a6fe4bf09f63b9fc5a7125c53c1c_812x612.png) MNIST 數據集中的示例 ## 具有多層感知器的基線模型 我們真的需要像卷積神經網絡這樣的復雜模型來獲得 MNIST 的最佳結果嗎? 使用具有單個隱藏層的非常簡單的神經網絡模型,您可以獲得非常好的結果。在本節中,我們將創建一個簡單的多層感知器模型,其誤差率為 1.74%,我們將使用它作為比較更復雜的卷積神經網絡模型的基準。 讓我們從導入我們需要的類和函數開始。 ```py import numpy from keras.datasets import mnist from keras.models import Sequential from keras.layers import Dense from keras.layers import Dropout from keras.utils import np_utils ``` 將隨機數生成器初始化為常量始終是一個好主意,以確保腳本的結果是可重現的。 ```py # 固定隨機種子再現性 seed = 7 numpy.random.seed(seed) ``` 現在我們可以使用 Keras 輔助函數加載 MNIST 數據集。 ```py # 加載數據集 (X_train, y_train), (X_test, y_test) = mnist.load_data() ``` 訓練數據集被構造為實例,圖像寬度和圖像高度的三維陣列。對于多層感知器模型,我們必須將圖像縮小為像素向量,在這種情況下,28×28 大小的圖像將是 784 像素輸入值。 我們可以使用 NumPy 數組上的 [reshape()函數](http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.reshape.html)輕松地進行轉換,我們還可以通過強制像素值的精度為 32 位來降低我們的內存需求,這是 Keras 使用的默認精度。 ```py # 將像素矩陣轉換為向量 num_pixels = X_train.shape[1] * X_train.shape[2] X_train = X_train.reshape(X_train.shape[0], num_pixels).astype('float32') X_test = X_test.reshape(X_test.shape[0], num_pixels).astype('float32') ``` 像素值是 0 到 255 之間的灰度級,在使用神經網絡模型時,執行輸入值的某些縮放幾乎總是一個好主意。因為這些比例是眾所周知的并且性能良好,所以我們可以通過將每個值除以最大值 255 來非常快速地將像素值標準化到 0 和 1 的范圍。 ```py # 標準化輸入 0-255 to 0-1 X_train = X_train / 255 X_test = X_test / 255 ``` 最后,輸出變量是 0 到 9 之間的整數。這是一個多類分類問題,因此,較好的實現方法是使用類值的一個熱編碼,將類整數的向量轉換為二進制矩陣。 我們可以使用 Keras 中內置的 np_utils.to_categorical()輔助函數輕松完成此操作。 ```py # 單熱編碼輸出 y_train = np_utils.to_categorical(y_train) y_test = np_utils.to_categorical(y_test) num_classes = y_test.shape[1] ``` 我們現在準備創建我們簡單的神經網絡模型,我們將在函數中定義我們的模型。如果您想稍后擴展示例并嘗試獲得更好的分數,這將會非常方便。 ```py # 定義基線模型 def baseline_model(): # 創建模型 model = Sequential() model.add(Dense(num_pixels, input_dim=num_pixels, kernel_initializer='normal', activation='relu')) model.add(Dense(num_classes, kernel_initializer='normal', activation='softmax')) # 編譯模型 model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) return model ``` 該模型是一個簡單的神經網絡,其中一個隱藏層具有與輸入相同數量的神經元(784),非線性激活函數被用于隱藏層中的神經元。 在輸出層上使用 softmax 激活函數將輸出轉換為類似概率的值,并允許選擇 10個類別中的一個類作為模型的輸出預測,對數損失用作損失函數(在 Keras 中稱為 categorical_crossentropy),并且使用有效的 ADAM 梯度下降算法來學習權重。 我們現在可以擬合和評估模型,該模型將擬合10次迭代,每 200 個圖像更新一次。測試數據用作驗證數據集,允許您在訓練時查看模型的性能。參數`verbose=2`表示將每個訓練時期的輸出減少到一行。 最后,測試數據集用于評估模型并打印分類錯誤率。 ```py # 構建模型 model = baseline_model() # 擬合模型 model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=200, verbose=2) # 最后,評估模型 scores = model.evaluate(X_test, y_test, verbose=0) print("Baseline Error: %.2f%%" % (100-scores[1]*100)) ``` 在 CPU 上運行時運行該示例可能需要幾分鐘,您應該看到下面的輸出,在極少數代碼行中定義的這種非常簡單的網絡實現了可觀的 1.91%的錯誤率。 ```py Train on 60000 samples, validate on 10000 samples Epoch 1/10 8s - loss: 0.2797 - acc: 0.9209 - val_loss: 0.1413 - val_acc: 0.9576 Epoch 2/10 8s - loss: 0.1117 - acc: 0.9677 - val_loss: 0.0919 - val_acc: 0.9702 Epoch 3/10 8s - loss: 0.0718 - acc: 0.9796 - val_loss: 0.0782 - val_acc: 0.9774 Epoch 4/10 8s - loss: 0.0505 - acc: 0.9858 - val_loss: 0.0758 - val_acc: 0.9762 Epoch 5/10 8s - loss: 0.0374 - acc: 0.9892 - val_loss: 0.0670 - val_acc: 0.9792 Epoch 6/10 8s - loss: 0.0268 - acc: 0.9929 - val_loss: 0.0630 - val_acc: 0.9803 Epoch 7/10 8s - loss: 0.0210 - acc: 0.9945 - val_loss: 0.0604 - val_acc: 0.9815 Epoch 8/10 8s - loss: 0.0140 - acc: 0.9969 - val_loss: 0.0620 - val_acc: 0.9808 Epoch 9/10 8s - loss: 0.0107 - acc: 0.9978 - val_loss: 0.0598 - val_acc: 0.9812 Epoch 10/10 7s - loss: 0.0080 - acc: 0.9985 - val_loss: 0.0588 - val_acc: 0.9809 Baseline Error: 1.91% ``` ## 用于 MNIST 的簡單卷積神經網絡 現在我們已經看到如何加載 MNIST 數據集并在其上訓練一個簡單的多層感知器模型,現在可以開發更復雜的卷積神經網絡或 CNN 模型。 Keras 確實為[創建卷積神經網絡](http://keras.io/layers/convolutional/)提供了很多函數。 在本節中,我們將為 MNIST 創建一個簡單的 CNN,演示如何使用現代 CNN 實現的所有方面,包括卷積層,池化層和全連接層。 第一步是導入所需的類和函數。 ```py import numpy from keras.datasets import mnist from keras.models import Sequential from keras.layers import Dense from keras.layers import Dropout from keras.layers import Flatten from keras.layers.convolutional import Conv2D from keras.layers.convolutional import MaxPooling2D from keras.utils import np_utils from keras import backend as K K.set_image_dim_ordering('th') ``` 同樣,我們總是將隨機數生成器初始化為恒定的隨機種子值,以便重現結果。 ```py # 固定隨機種子再現性 seed = 7 numpy.random.seed(seed) ``` 接下來,我們需要加載 MNIST 數據集并對其進行整形,以便它適合用于訓練 CNN。在 Keras 中,用于二維卷積的層期望像素值具有[像素] [寬度] [高度]的尺寸。 在 RGB 的情況下,對于紅色,綠色和藍色分量,第一維像素將是 3,并且對于每個彩色圖像將具有 3 維圖像分量輸入,在 MNIST 中像素值是灰度級的情況下,像素維度將設置為 1。 ```py # 加載數據 (X_train, y_train), (X_test, y_test) = mnist.load_data() # reshape to be [samples][pixels][width][height] X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32') X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype('float32') ``` 和之前前一樣,最好將像素值標準化為 0 和 1 范圍,并對輸出變量進行熱編碼。 ```py #標準化輸入 from 0-255 to 0-1 X_train = X_train / 255 X_test = X_test / 255 # 單熱編碼輸出 outputs y_train = np_utils.to_categorical(y_train) y_test = np_utils.to_categorical(y_test) num_classes = y_test.shape[1] ``` 接下來我們定義我們的神經網絡模型 卷積神經網絡比標準的多層感知器更復雜,因此我們將首先使用一個簡單的結構,使用所有元素來獲得最先進的結果。下面總結了網絡的架構。 1. 第一個隱藏層是卷積層,稱為 Convolution2D。該層具有 32 個特征圖,其大小為 5×5,并具有非線性激活函數。這是輸入層,預期結構輪廓在[像素] [寬度] [高度]以上的圖像。 2. 接下來,我們定義一個池化層,它采用最大的 MaxPooling2D。池大小設置為 2×2。 3. 下一層是使用 dropout 的正則化層,稱為 Dropout。它被配置為隨機消除層中 20%的神經元以減少過度擬合。 4. 接下來是將 2D 矩陣數據轉換為名為 Flatten 的向量的層。它允許輸出由標準的完全連接層處理。 5. 接下來是具有 128 個神經元和非線性激活函數的完全連接層。 6. 最后,輸出層有 10 個類的 10 個神經元和 softmax 激活函數,為每個類輸出類似概率的預測。 如前所述,使用對數損失和 ADAM 梯度下降算法訓練模型。 ```py def baseline_model(): # 創建模型 model = Sequential() model.add(Conv2D(32, (5, 5), input_shape=(1, 28, 28), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.2)) model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dense(num_classes, activation='softmax')) # 編譯模型 model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) return model ``` 我們使用多層感知器以與以前相同的方式評估模型,CNN 擬合用于 10 個迭代次數,批大小設置為 200。 ```py # 構建模型 model = baseline_model() # 擬合模型 model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=200, verbose=2) # 最后評估模型 scores = model.evaluate(X_test, y_test, verbose=0) print("CNN Error: %.2f%%" % (100-scores[1]*100)) ``` 運行該示例,在每個時期打印訓練和驗證測試的準確性,并且在末尾打印分類的錯誤率。 時期可能需要大約 45 秒才能在 GPU 上運行(例如在 AWS 上)。您可以看到網絡的錯誤率達到 1.03,這比我們上面的簡單多層感知器模型要好。 ```py Train on 60000 samples, validate on 10000 samples Epoch 1/10 60000/60000 [==============================] - 120s - loss: 0.2346 - acc: 0.9334 - val_loss: 0.0774 - val_acc: 0.9762 Epoch 2/10 60000/60000 [==============================] - 42s - loss: 0.0716 - acc: 0.9782 - val_loss: 0.0454 - val_acc: 0.9856 Epoch 3/10 60000/60000 [==============================] - 42s - loss: 0.0520 - acc: 0.9842 - val_loss: 0.0429 - val_acc: 0.9853 Epoch 4/10 60000/60000 [==============================] - 42s - loss: 0.0406 - acc: 0.9868 - val_loss: 0.0369 - val_acc: 0.9876 Epoch 5/10 60000/60000 [==============================] - 42s - loss: 0.0331 - acc: 0.9898 - val_loss: 0.0345 - val_acc: 0.9884 Epoch 6/10 60000/60000 [==============================] - 42s - loss: 0.0265 - acc: 0.9917 - val_loss: 0.0323 - val_acc: 0.9905 Epoch 7/10 60000/60000 [==============================] - 42s - loss: 0.0220 - acc: 0.9931 - val_loss: 0.0337 - val_acc: 0.9894 Epoch 8/10 60000/60000 [==============================] - 42s - loss: 0.0201 - acc: 0.9934 - val_loss: 0.0316 - val_acc: 0.9892 Epoch 9/10 60000/60000 [==============================] - 42s - loss: 0.0163 - acc: 0.9947 - val_loss: 0.0281 - val_acc: 0.9908 Epoch 10/10 60000/60000 [==============================] - 42s - loss: 0.0135 - acc: 0.9956 - val_loss: 0.0327 - val_acc: 0.9897 CNN Error: 1.03% ``` ## 用于 MNIST 的較大卷積神經網絡 現在我們已經看到了如何創建一個簡單的 CNN,讓我們來看看能夠接近最新結果的模型。 我們導入類和函數,然后加載與前一個 CNN 示例相同的預處理數據。 ```py # MNIST Dataset更大的CNN import numpy from keras.datasets import mnist from keras.models import Sequential from keras.layers import Dense from keras.layers import Dropout from keras.layers import Flatten from keras.layers.convolutional import Conv2D from keras.layers.convolutional import MaxPooling2D from keras.utils import np_utils from keras import backend as K K.set_image_dim_ordering('th') # 固定隨機種子再現性 seed = 7 numpy.random.seed(seed) # 加載數據 (X_train, y_train), (X_test, y_test) = mnist.load_data() # reshape to be [samples][pixels][width][height] X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32') X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype('float32') # 標準化輸入 0-255 to 0-1 X_train = X_train / 255 X_test = X_test / 255 # 單熱編碼輸出 y_train = np_utils.to_categorical(y_train) y_test = np_utils.to_categorical(y_test) num_classes = y_test.shape[1] ``` 這次我們定義了一個大型 CNN 架構,其中包含額外的卷積,最大池化層和完全連接的層。網絡拓撲可以總結如下。 1. 具有 30 個大小為 5×5 的特征圖的卷積層。 2. 池化層最多超過 2 * 2 patches。 3. 具有 15 個維度為 3×3 的特征圖的卷積層。 4. 池化層最多超過 2 * 2 patches。 5. dropout層的概率設置為 20%。 6. 將矩陣轉換為向量。 7. 完全連接的層有 128 個神經元和非線性激活函數。 8. 完全連接的層有 50 個神經元和非線性激活函數。 9. 輸出層。 ```py # 定義一個大模型 def larger_model(): # 創建模型 model = Sequential() model.add(Conv2D(30, (5, 5), input_shape=(1, 28, 28), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(15, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.2)) model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dense(50, activation='relu')) model.add(Dense(num_classes, activation='softmax')) # 編譯模型 model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) return model ``` 與前兩個實驗一樣,該模型擬合10個迭代次數,批大小為 200。 ```py # 構建模型 model = larger_model() # 擬合模型 model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=200) # 最后評估模型 scores = model.evaluate(X_test, y_test, verbose=0) print("Large CNN Error: %.2f%%" % (100-scores[1]*100)) ``` 運行示例將在每個迭代期間的訓練集和驗證集上輸出分類精確度,并最終顯示分類錯誤率。 該模型每個跌打的運行大約需要 100 秒,這個略大的模型實現了 0.89%的可觀分類錯誤率。 ```py Train on 60000 samples, validate on 10000 samples Epoch 1/10 60000/60000 [==============================] - 45s - loss: 0.3912 - acc: 0.8798 - val_loss: 0.0874 - val_acc: 0.9726 Epoch 2/10 60000/60000 [==============================] - 43s - loss: 0.0944 - acc: 0.9713 - val_loss: 0.0603 - val_acc: 0.9800 Epoch 3/10 60000/60000 [==============================] - 43s - loss: 0.0697 - acc: 0.9781 - val_loss: 0.0377 - val_acc: 0.9880 Epoch 4/10 60000/60000 [==============================] - 44s - loss: 0.0558 - acc: 0.9819 - val_loss: 0.0331 - val_acc: 0.9885 Epoch 5/10 60000/60000 [==============================] - 44s - loss: 0.0480 - acc: 0.9852 - val_loss: 0.0300 - val_acc: 0.9900 Epoch 6/10 60000/60000 [==============================] - 44s - loss: 0.0430 - acc: 0.9862 - val_loss: 0.0293 - val_acc: 0.9897 Epoch 7/10 60000/60000 [==============================] - 44s - loss: 0.0385 - acc: 0.9877 - val_loss: 0.0260 - val_acc: 0.9911 Epoch 8/10 60000/60000 [==============================] - 44s - loss: 0.0349 - acc: 0.9895 - val_loss: 0.0264 - val_acc: 0.9910 Epoch 9/10 60000/60000 [==============================] - 44s - loss: 0.0332 - acc: 0.9898 - val_loss: 0.0222 - val_acc: 0.9931 Epoch 10/10 60000/60000 [==============================] - 44s - loss: 0.0289 - acc: 0.9908 - val_loss: 0.0226 - val_acc: 0.9918 Large CNN Error: 0.82% ``` 這不是最優化的網絡拓撲,也不是復現最近的論文的網絡結構,您可以嘗試多次調整和改進此模型。 您可以達到的最佳錯誤率分數是多少? 在評論中發布您的配置和最佳分數。 ## 關于 MNIST 的資源 MNIST 數據集得到了很好的研究,以下是您可能希望了解的一些其他資源。 * [官方 MNIST 數據集網頁](http://yann.lecun.com/exdb/mnist/)。 * [Rodrigo Benenson 的網頁列出了最新的結果](http://rodrigob.github.io/are_we_there_yet/build/classification_datasets_results.html#4d4e495354)。 * [使用此數據集](https://www.kaggle.com/c/digit-recognizer)的 Kaggle 競賽(查看腳本和論壇部分以獲取示例代碼) * [在 MNIST 上訓練的只讀模型,您可以在瀏覽器中測試](http://myselph.de/neuralNet.html)(非常酷) ## 摘要 在這篇文章中,您發現了 MNIST 手寫數字識別問題和使用 Keras 庫在 Python 中開發的深度學習模型,這些模型能夠獲得出色的結果。 通過本教程,您了解到: * 如何在 Keras 中加載 MNIST 數據集并生成數據集的圖。 * 如何重塑 MNIST 數據集并開發一個簡單但性能良好的多層感知器模型來解決這個問題。 * 如何使用 Keras 為 MNIST 創建卷積神經網絡模型。 * 如何為具有近乎世界級成果的 MNIST 開發和評估更大的 CNN 模型。 您對深度學習或此帖的手寫識別有任何疑問嗎?在評論中提出您的問題,我會盡力回答。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看