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

使用深度學習檢測瘧疾

人工智能 深度學習 開源 后端
在本篇文章,我們將測試 AI 是如何與低成本、有效、精確的開源深度學習方法結合起來一起用來檢測致死的傳染病瘧疾。

??

[[266327]]

??

 人工智能結合開源硬件工具能夠提升嚴重傳染病瘧疾的診斷。

人工智能(AI)和開源工具、技術和框架是促進社會進步的強有力的結合。“健康就是財富”可能有點陳詞濫調,但它卻是非常準確的!在本篇文章,我們將測試 AI 是如何與低成本、有效、精確的開源深度學習方法結合起來一起用來檢測致死的傳染病瘧疾。

我既不是一個醫生,也不是一個醫療保健研究者,我也絕不像他們那樣合格,我只是對將 AI 應用到醫療保健研究感興趣。在這片文章中我的想法是展示 AI 和開源解決方案如何幫助瘧疾檢測和減少人工勞動的方法。

??

??

Python 和 TensorFlow: 一個構建開源深度學習方法的很棒的結合

感謝 Python 的強大和像 TensorFlow 這樣的深度學習框架,我們能夠構建健壯的、大規模的、有效的深度學習方法。因為這些工具是自由和開源的,我們能夠構建非常經濟且易于被任何人采納和使用的解決方案。讓我們開始吧!

項目動機

瘧疾是由瘧原蟲造成的致死的、有傳染性的、蚊子傳播的疾病,主要通過受感染的雌性按蚊叮咬傳播。共有五種寄生蟲能夠引起瘧疾,但是大多數病例是這兩種類型造成的:惡性瘧原蟲和間日瘧原蟲。

這個地圖顯示了瘧疾在全球傳播分布形勢,尤其在熱帶地區,但疾病的性質和致命性是該項目的主要動機。

如果一只受感染雌性蚊子叮咬了你,蚊子攜帶的寄生蟲進入你的血液,并且開始破壞攜帶氧氣的紅細胞(RBC)。通常,瘧疾的最初癥狀類似于流感病毒,在蚊子叮咬后,他們通常在幾天或幾周內發作。然而,這些致死的寄生蟲可以在你的身體里生存長達一年并且不會造成任何癥狀,延遲治療可能造成并發癥甚至死亡。因此,早期的檢查能夠挽救生命。

世界健康組織(WHO)的??瘧疾實情??表明,世界近乎一半的人口面臨瘧疾的風險,有超過 2 億的瘧疾病例,每年由于瘧疾造成的死亡將近 40 萬。這是使瘧疾檢測和診斷快速、簡單和有效的一個動機。

檢測瘧疾的方法

有幾種方法能夠用來檢測和診斷瘧疾。該文中的項目就是基于 Rajaraman, et al. 的論文:“??預先訓練的卷積神經網絡作為特征提取器,用于改善薄血涂片圖像中的瘧疾寄生蟲檢測??”介紹的一些方法,包含聚合酶鏈反應(PCR)和快速診斷測試(RDT)。這兩種測試通常用于無法提供高質量顯微鏡服務的地方。

標準的瘧疾診斷通常是基于血液涂片工作流程的,根據 Carlos Ariza 的文章“??Malaria Hero:一個更快診斷瘧原蟲的網絡應用???”,我從中了解到 Adrian Rosebrock 的“??使用 Keras 的深度學習和醫學圖像分析??”。我感激這些優秀的資源的作者,讓我在瘧原蟲預防、診斷和治療方面有了更多的想法。

??

??

一個瘧原蟲檢測的血涂片工作流程

根據 WHO 方案,診斷通常包括對放大 100 倍的血涂片的集中檢測。受過訓練的人們手工計算在 5000 個細胞中有多少紅細胞中包含瘧原蟲。正如上述解釋中引用的 Rajaraman, et al. 的論文:

厚血涂片有助于檢測寄生蟲的存在,而薄血涂片有助于識別引起感染的寄生蟲種類(疾病控制和預防中心, 2012)。診斷準確性在很大程度上取決于診斷人的專業知識,并且可能受到觀察者間差異和疾病流行/資源受限區域大規模診斷所造成的不利影響(Mitiku, Mengistu 和 Gelaw, 2003)。可替代的技術是使用聚合酶鏈反應(PCR)和快速診斷測試(RDT);然而,PCR 分析受限于它的性能(Hommelsheim, et al., 2014),RDT 在疾病流行的地區成本效益低(Hawkes, Katsuva 和 Masumbuko, 2009)。

因此,瘧疾檢測可能受益于使用機器學習的自動化。

瘧疾檢測的深度學習

人工診斷血涂片是一個繁重的手工過程,需要專業知識來分類和計數被寄生蟲感染的和未感染的細胞。這個過程可能不能很好的規模化,尤其在那些專業人士不足的地區。在利用最先進的圖像處理和分析技術提取人工選取特征和構建基于機器學習的分類模型方面取得了一些進展。然而,這些模型不能大規模推廣,因為沒有更多的數據用來訓練,并且人工選取特征需要花費很長時間。

深度學習模型,或者更具體地講,卷積神經網絡(CNN),已經被證明在各種計算機視覺任務中非常有效。(如果你想更多的了解關于 CNN 的背景知識,我推薦你閱讀??視覺識別的 CS2331n 卷積神經網絡??。)簡單地講,CNN 模型的關鍵層包含卷積和池化層,正如下圖所示。

??

??

一個典型的 CNN 架構

卷積層從數據中學習空間層級模式,它是平移不變的,因此它們能夠學習圖像的不同方面。例如,第一個卷積層將學習小的和局部圖案,例如邊緣和角落,第二個卷積層將基于第一層的特征學習更大的圖案,等等。這允許 CNN 自動化提取特征并且學習對于新數據點通用的有效的特征。池化層有助于下采樣和減少尺寸。

因此,CNN 有助于自動化和規模化的特征工程。同樣,在模型末尾加上密集層允許我們執行像圖像分類這樣的任務。使用像 CNN 這樣的深度學習模型自動的瘧疾檢測可能非常有效、便宜和具有規模性,尤其是遷移學習和預訓練模型效果非常好,甚至在少量數據的約束下。

Rajaraman, et al. 的論文在一個數據集上利用六個預訓練模型在檢測瘧疾對比無感染樣本獲取到令人吃驚的 95.9% 的準確率。我們的重點是從頭開始嘗試一些簡單的 CNN 模型和用一個預訓練的訓練模型使用遷移學習來查看我們能夠從相同的數據集中得到什么。我們將使用開源工具和框架,包括 Python 和 TensorFlow,來構建我們的模型。

數據集

我們分析的數據來自 Lister Hill 國家生物醫學交流中心(LHNCBC)的研究人員,該中心是國家醫學圖書館(NLM)的一部分,他們細心收集和標記了公開可用的健康和受感染的血涂片圖像的??數據集???。這些研究者已經開發了一個運行在 Android 智能手機的??瘧疾檢測手機應用??,連接到一個傳統的光學顯微鏡。它們使用吉姆薩染液將 150 個受惡性瘧原蟲感染的和 50 個健康病人的薄血涂片染色,這些薄血涂片是在孟加拉的吉大港醫學院附屬醫院收集和照相的。使用智能手機的內置相機獲取每個顯微鏡視窗內的圖像。這些圖片由在泰國曼谷的馬希多-牛津熱帶醫學研究所的一個專家使用幻燈片閱讀器標記的。

讓我們簡要地查看一下數據集的結構。首先,我將安裝一些基礎的依賴(基于使用的操作系統)。

??

??

Installing dependencies

我使用的是云上的帶有一個 GPU 的基于 Debian 的操作系統,這樣我能更快的運行我的模型。為了查看目錄結構,我們必須使用 ??sudo apt install tree??? 安裝 ??tree?? 及其依賴(如果我們沒有安裝的話)。

??

??

Installing the tree dependency

我們有兩個文件夾包含血細胞的圖像,包括受感染的和健康的。我們通過輸入可以獲取關于圖像總數更多的細節:

import os
import glob

base_dir = os.path.join('./cell_images')
infected_dir = os.path.join(base_dir,'Parasitized')
healthy_dir = os.path.join(base_dir,'Uninfected')

infected_files = glob.glob(infected_dir+'/*.png')
healthy_files = glob.glob(healthy_dir+'/*.png')
len(infected_files), len(healthy_files)

# Output
(13779, 13779)

看起來我們有一個平衡的數據集,包含 13,779 張瘧疾的和 13,779 張非瘧疾的(健康的)血細胞圖像。讓我們根據這些構建數據幀,我們將用這些數據幀來構建我們的數據集。

import numpy as np
import pandas as pd

np.random.seed(42)

files_df = pd.DataFrame({
'filename': infected_files + healthy_files,
'label': ['malaria'] * len(infected_files) + ['healthy'] * len(healthy_files)
}).sample(frac=1, random_state=42).reset_index(drop=True)

files_df.head()

??

??

Datasets

構建和了解圖像數據集

為了構建深度學習模型,我們需要訓練數據,但是我們還需要使用不可見的數據測試模型的性能。相應的,我們將使用 60:10:30 的比例來劃分用于訓練、驗證和測試的數據集。我們將在訓練期間應用訓練和驗證數據集,并用測試數據集來檢查模型的性能。

from sklearn.model_selection import train_test_split
from collections import Counter

train_files, test_files, train_labels, test_labels = train_test_split(files_df['filename'].values,
files_df['label'].values,
test_size=0.3, random_state=42)
train_files, val_files, train_labels, val_labels = train_test_split(train_files,
train_labels,
test_size=0.1, random_state=42)

print(train_files.shape, val_files.shape, test_files.shape)
print('Train:', Counter(train_labels), '\nVal:', Counter(val_labels), '\nTest:', Counter(test_labels))

# Output
(17361,) (1929,) (8268,)
Train: Counter({'healthy': 8734, 'malaria': 8627})
Val: Counter({'healthy': 970, 'malaria': 959})
Test: Counter({'malaria': 4193, 'healthy': 4075})

這些圖片尺寸并不相同,因為血涂片和細胞圖像是基于人、測試方法、圖片方向不同而不同的。讓我們總結我們的訓練數據集的統計信息來決定最佳的圖像尺寸(牢記,我們根本不會碰測試數據集)。

import cv2
from concurrent import futures
import threading

def get_img_shape_parallel(idx, img, total_imgs):
if idx % 5000 == 0 or idx == (total_imgs - 1):
print('{}: working on img num: {}'.format(threading.current_thread().name,
idx))
return cv2.imread(img).shape

ex = futures.ThreadPoolExecutor(max_workers=None)
data_inp = [(idx, img, len(train_files)) for idx, img in enumerate(train_files)]
print('Starting Img shape computation:')
train_img_dims_map = ex.map(get_img_shape_parallel,
[record[0] for record in data_inp],
[record[1] for record in data_inp],
[record[2] for record in data_inp])
train_img_dims = list(train_img_dims_map)
print('Min Dimensions:', np.min(train_img_dims, axis=0))
print('Avg Dimensions:', np.mean(train_img_dims, axis=0))
print('Median Dimensions:', np.median(train_img_dims, axis=0))
print('Max Dimensions:', np.max(train_img_dims, axis=0))


# Output
Starting Img shape computation:
ThreadPoolExecutor-0_0: working on img num: 0
ThreadPoolExecutor-0_17: working on img num: 5000
ThreadPoolExecutor-0_15: working on img num: 10000
ThreadPoolExecutor-0_1: working on img num: 15000
ThreadPoolExecutor-0_7: working on img num: 17360
Min Dimensions: [46 46 3]
Avg Dimensions: [132.77311215 132.45757733 3.]
Median Dimensions: [130. 130. 3.]
Max Dimensions: [385 394 3]

我們應用并行處理來加速圖像讀取,并且基于匯總統計結果,我們將每幅圖片的尺寸重新調整到 125x125 像素。讓我們載入我們所有的圖像并重新調整它們為這些固定尺寸。

IMG_DIMS = (125, 125)

def get_img_data_parallel(idx, img, total_imgs):
if idx % 5000 == 0 or idx == (total_imgs - 1):
print('{}: working on img num: {}'.format(threading.current_thread().name,
idx))
img = cv2.imread(img)
img = cv2.resize(img, dsize=IMG_DIMS,
interpolation=cv2.INTER_CUBIC)
img = np.array(img, dtype=np.float32)
return img

ex = futures.ThreadPoolExecutor(max_workers=None)
train_data_inp = [(idx, img, len(train_files)) for idx, img in enumerate(train_files)]
val_data_inp = [(idx, img, len(val_files)) for idx, img in enumerate(val_files)]
test_data_inp = [(idx, img, len(test_files)) for idx, img in enumerate(test_files)]

print('Loading Train Images:')
train_data_map = ex.map(get_img_data_parallel,
[record[0] for record in train_data_inp],
[record[1] for record in train_data_inp],
[record[2] for record in train_data_inp])
train_data = np.array(list(train_data_map))

print('\nLoading Validation Images:')
val_data_map = ex.map(get_img_data_parallel,
[record[0] for record in val_data_inp],
[record[1] for record in val_data_inp],
[record[2] for record in val_data_inp])
val_data = np.array(list(val_data_map))

print('\nLoading Test Images:')
test_data_map = ex.map(get_img_data_parallel,
[record[0] for record in test_data_inp],
[record[1] for record in test_data_inp],
[record[2] for record in test_data_inp])
test_data = np.array(list(test_data_map))

train_data.shape, val_data.shape, test_data.shape


# Output
Loading Train Images:
ThreadPoolExecutor-1_0: working on img num: 0
ThreadPoolExecutor-1_12: working on img num: 5000
ThreadPoolExecutor-1_6: working on img num: 10000
ThreadPoolExecutor-1_10: working on img num: 15000
ThreadPoolExecutor-1_3: working on img num: 17360

Loading Validation Images:
ThreadPoolExecutor-1_13: working on img num: 0
ThreadPoolExecutor-1_18: working on img num: 1928

Loading Test Images:
ThreadPoolExecutor-1_5: working on img num: 0
ThreadPoolExecutor-1_19: working on img num: 5000
ThreadPoolExecutor-1_8: working on img num: 8267
((17361, 125, 125, 3), (1929, 125, 125, 3), (8268, 125, 125, 3))

我們再次應用并行處理來加速有關圖像載入和重新調整大小的計算。最終,我們獲得了所需尺寸的圖片張量,正如前面的輸出所示。我們現在查看一些血細胞圖像樣本,以對我們的數據有個印象。

import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(1 , figsize = (8 , 8))
n = 0
for i in range(16):
n += 1
r = np.random.randint(0 , train_data.shape[0] , 1)
plt.subplot(4 , 4 , n)
plt.subplots_adjust(hspace = 0.5 , wspace = 0.5)
plt.imshow(train_data[r[0]]/255.)
plt.title('{}'.format(train_labels[r[0]]))
plt.xticks([]) , plt.yticks([])

??

??

Malaria cell samples

基于這些樣本圖像,我們看到一些瘧疾和健康細胞圖像的細微不同。我們將使我們的深度學習模型試圖在模型訓練中學習這些模式。

開始我們的模型訓練前,我們必須建立一些基礎的配置設置。

BATCH_SIZE = 64
NUM_CLASSES = 2
EPOCHS = 25
INPUT_SHAPE = (125, 125, 3)

train_imgs_scaled = train_data / 255.
val_imgs_scaled = val_data / 255.

# encode text category labels
from sklearn.preprocessing import LabelEncoder

le = LabelEncoder()
le.fit(train_labels)
train_labels_enc = le.transform(train_labels)
val_labels_enc = le.transform(val_labels)

print(train_labels[:6], train_labels_enc[:6])


# Output
['malaria' 'malaria' 'malaria' 'healthy' 'healthy' 'malaria'] [1 1 1 0 0 1]

我們修復我們的圖像尺寸、批量大小,和紀元,并編碼我們的分類的類標簽。TensorFlow 2.0 于 2019 年三月發布,這個練習是嘗試它的完美理由。

import tensorflow as tf

# Load the TensorBoard notebook extension (optional)
%load_ext tensorboard.notebook

tf.random.set_seed(42)
tf.__version__

# Output
'2.0.0-alpha0'

深度學習訓練

在模型訓練階段,我們將構建三個深度訓練模型,使用我們的訓練集訓練,使用驗證數據比較它們的性能。然后,我們保存這些模型并在之后的模型評估階段使用它們。

模型 1:從頭開始的 CNN

我們的第一個瘧疾檢測模型將從頭開始構建和訓練一個基礎的 CNN。首先,讓我們定義我們的模型架構,

inp = tf.keras.layers.Input(shape=INPUT_SHAPE)

conv1 = tf.keras.layers.Conv2D(32, kernel_size=(3, 3),
activation='relu', padding='same')(inp)
pool1 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(conv1)
conv2 = tf.keras.layers.Conv2D(64, kernel_size=(3, 3),
activation='relu', padding='same')(pool1)
pool2 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(conv2)
conv3 = tf.keras.layers.Conv2D(128, kernel_size=(3, 3),
activation='relu', padding='same')(pool2)
pool3 = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(conv3)

flat = tf.keras.layers.Flatten()(pool3)

hidden1 = tf.keras.layers.Dense(512, activation='relu')(flat)
drop1 = tf.keras.layers.Dropout(rate=0.3)(hidden1)
hidden2 = tf.keras.layers.Dense(512, activation='relu')(drop1)
drop2 = tf.keras.layers.Dropout(rate=0.3)(hidden2)

out = tf.keras.layers.Dense(1, activation='sigmoid')(drop2)

model = tf.keras.Model(inputs=inp, outputs=out)
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
model.summary()


# Output
Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 125, 125, 3)] 0
_________________________________________________________________
conv2d (Conv2D) (None, 125, 125, 32) 896
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 62, 62, 32) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 62, 62, 64) 18496
_________________________________________________________________
...
...
_________________________________________________________________
dense_1 (Dense) (None, 512) 262656
_________________________________________________________________
dropout_1 (Dropout) (None, 512) 0
_________________________________________________________________
dense_2 (Dense) (None, 1) 513
=================================================================
Total params: 15,102,529
Trainable params: 15,102,529
Non-trainable params: 0
_________________________________________________________________

基于這些代碼的架構,我們的 CNN 模型有三個卷積和一個池化層,其后是兩個致密層,以及用于正則化的失活。讓我們訓練我們的模型。

import datetime

logdir = os.path.join('/home/dipanzan_sarkar/projects/tensorboard_logs',
datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
tensorboard_callback = tf.keras.callbacks.TensorBoard(logdir, histogram_freq=1)
reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.5,
patience=2, min_lr=0.000001)
callbacks = [reduce_lr, tensorboard_callback]

history = model.fit(x=train_imgs_scaled, y=train_labels_enc,
batch_size=BATCH_SIZE,
epochs=EPOCHS,
validation_data=(val_imgs_scaled, val_labels_enc),
callbacks=callbacks,
verbose=1)


# Output
Train on 17361 samples, validate on 1929 samples
Epoch 1/25
17361/17361 [====] - 32s 2ms/sample - loss: 0.4373 - accuracy: 0.7814 - val_loss: 0.1834 - val_accuracy: 0.9393
Epoch 2/25
17361/17361 [====] - 30s 2ms/sample - loss: 0.1725 - accuracy: 0.9434 - val_loss: 0.1567 - val_accuracy: 0.9513
...
...
Epoch 24/25
17361/17361 [====] - 30s 2ms/sample - loss: 0.0036 - accuracy: 0.9993 - val_loss: 0.3693 - val_accuracy: 0.9565
Epoch 25/25
17361/17361 [====] - 30s 2ms/sample - loss: 0.0034 - accuracy: 0.9994 - val_loss: 0.3699 - val_accuracy: 0.9559

我們獲得了 95.6% 的驗證精確率,這很好,盡管我們的模型看起來有些過擬合(通過查看我們的訓練精確度,是 99.9%)。通過繪制訓練和驗證的精度和損失曲線,我們可以清楚地看到這一點。

f, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
t = f.suptitle('Basic CNN Performance', fontsize=12)
f.subplots_adjust(top=0.85, wspace=0.3)

max_epoch = len(history.history['accuracy'])+1
epoch_list = list(range(1,max_epoch))
ax1.plot(epoch_list, history.history['accuracy'], label='Train Accuracy')
ax1.plot(epoch_list, history.history['val_accuracy'], label='Validation Accuracy')
ax1.set_xticks(np.arange(1, max_epoch, 5))
ax1.set_ylabel('Accuracy Value')
ax1.set_xlabel('Epoch')
ax1.set_title('Accuracy')
l1 = ax1.legend(loc="best")

ax2.plot(epoch_list, history.history['loss'], label='Train Loss')
ax2.plot(epoch_list, history.history['val_loss'], label='Validation Loss')
ax2.set_xticks(np.arange(1, max_epoch, 5))
ax2.set_ylabel('Loss Value')
ax2.set_xlabel('Epoch')
ax2.set_title('Loss')
l2 = ax2.legend(loc="best")

??

??

基礎 CNN 學習曲線

我們可以看在在第五個紀元,情況并沒有改善很多。讓我們保存這個模型用于將來的評估。

model.save('basic_cnn.h5')

深度遷移學習

就像人類有與生俱來在不同任務間傳輸知識的能力一樣,遷移學習允許我們利用從以前任務學到的知識用到新的相關的任務,即使在機器學習或深度學習的情況下也是如此。如果想深入探究遷移學習,你應該看我的文章“??一個易于理解與現實應用一起學習深度學習中的遷移學習的指導實踐???”和我的書《??Python 遷移學習實踐??》。

??

??

深度遷移學習的想法

在這篇實踐中我們想要探索的想法是:

在我們的問題背景下,我們能夠利用一個預訓練深度學習模型(在大數據集上訓練的,像 ImageNet)通過應用和遷移知識來解決瘧疾檢測的問題嗎?

我們將應用兩個最流行的深度遷移學習策略。

  • 預訓練模型作為特征提取器
  • 微調的預訓練模型

我們將使用預訓練的 VGG-19 深度訓練模型(由劍橋大學的視覺幾何組(VGG)開發)進行我們的實驗。像 VGG-19 這樣的預訓練模型是在一個大的數據集(??Imagenet??)上使用了很多不同的圖像分類訓練的。因此,這個模型應該已經學習到了健壯的特征層級結構,相對于你的 CNN 模型學到的特征,是空間不變的、轉動不變的、平移不變的。因此,這個模型,已經從百萬幅圖片中學習到了一個好的特征顯示,對于像瘧疾檢測這樣的計算機視覺問題,可以作為一個好的合適新圖像的特征提取器。在我們的問題中發揮遷移學習的能力之前,讓我們先討論 VGG-19 模型。

理解 VGG-19 模型

VGG-19 模型是一個構建在 ImageNet 數據庫之上的 19 層(卷積和全連接的)的深度學習網絡,ImageNet 數據庫為了圖像識別和分類的目的而開發。該模型是由 Karen Simonyan 和 Andrew Zisserman 構建的,在他們的論文“??大規模圖像識別的非常深的卷積網絡??”中進行了描述。VGG-19 的架構模型是:

??

??

VGG-19 模型架構

你可以看到我們總共有 16 個使用 3x3 卷積過濾器的卷積層,與最大的池化層來下采樣,和由 4096 個單元組成的兩個全連接的隱藏層,每個隱藏層之后跟隨一個由 1000 個單元組成的致密層,每個單元代表 ImageNet 數據庫中的一個分類。我們不需要最后三層,因為我們將使用我們自己的全連接致密層來預測瘧疾。我們更關心前五個塊,因此我們可以利用 VGG 模型作為一個有效的特征提取器。

我們將使用模型之一作為一個簡單的特征提取器,通過凍結五個卷積塊的方式來確保它們的位權在每個紀元后不會更新。對于最后一個模型,我們會對 VGG 模型進行微調,我們會解凍最后兩個塊(第 4 和第 5)因此當我們訓練我們的模型時,它們的位權在每個時期(每批數據)被更新。

模型 2:預訓練的模型作為一個特征提取器

為了構建這個模型,我們將利用 TensorFlow 載入 VGG-19 模型并凍結卷積塊,因此我們能夠將它們用作特征提取器。我們在末尾插入我們自己的致密層來執行分類任務。

vgg = tf.keras.applications.vgg19.VGG19(include_top=False, weights='imagenet', 
input_shape=INPUT_SHAPE)
vgg.trainable = False
# Freeze the layers
for layer in vgg.layers:
layer.trainable = False

base_vgg = vgg
base_out = base_vgg.output
pool_out = tf.keras.layers.Flatten()(base_out)
hidden1 = tf.keras.layers.Dense(512, activation='relu')(pool_out)
drop1 = tf.keras.layers.Dropout(rate=0.3)(hidden1)
hidden2 = tf.keras.layers.Dense(512, activation='relu')(drop1)
drop2 = tf.keras.layers.Dropout(rate=0.3)(hidden2)

out = tf.keras.layers.Dense(1, activation='sigmoid')(drop2)

model = tf.keras.Model(inputs=base_vgg.input, outputs=out)
model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=1e-4),
loss='binary_crossentropy',
metrics=['accuracy'])
model.summary()


# Output
Model: "model_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_2 (InputLayer) [(None, 125, 125, 3)] 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 125, 125, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 125, 125, 64) 36928
_________________________________________________________________
...
...
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 3, 3, 512) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 4608) 0
_________________________________________________________________
dense_3 (Dense) (None, 512) 2359808
_________________________________________________________________
dropout_2 (Dropout) (None, 512) 0
_________________________________________________________________
dense_4 (Dense) (None, 512) 262656
_________________________________________________________________
dropout_3 (Dropout) (None, 512) 0
_________________________________________________________________
dense_5 (Dense) (None, 1) 513
=================================================================
Total params: 22,647,361
Trainable params: 2,622,977
Non-trainable params: 20,024,384
_________________________________________________________________

從整個輸出可以明顯看出,在我們的模型中我們有了很多層,我們將只利用 VGG-19 模型的凍結層作為特征提取器。你可以使用下列代碼來驗證我們的模型有多少層是實際可訓練的,以及我們的網絡中總共存在多少層。

print("Total Layers:", len(model.layers))
print("Total trainable layers:",
sum([1 for l in model.layers if l.trainable]))

# Output
Total Layers: 28
Total trainable layers: 6

我們將使用和我們之前的模型相似的配置和回調來訓練我們的模型。參考??我的 GitHub 倉庫??以獲取訓練模型的完整代碼。我們觀察下列圖表,以顯示模型精確度和損失曲線。

??

??

凍結的預訓練的 CNN 的學習曲線

這表明我們的模型沒有像我們的基礎 CNN 模型那樣過擬合,但是性能有點不如我們的基礎的 CNN 模型。讓我們保存這個模型,以備將來的評估。

model.save('vgg_frozen.h5')

模型 3:使用圖像增強來微調預訓練的模型

在我們的最后一個模型中,我們將在預定義好的 VGG-19 模型的最后兩個塊中微調層的位權。我們同樣引入了圖像增強的概念。圖像增強背后的想法和其名字一樣。我們從訓練數據集中載入現有圖像,并且應用轉換操作,例如旋轉、裁剪、轉換、放大縮小等等,來產生新的、改變過的版本。由于這些隨機轉換,我們每次獲取到的圖像不一樣。我們將應用 tf.keras 中的一個名為 ImageDataGenerator 的優秀工具來幫助構建圖像增強器。

train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255,
zoom_range=0.05,
rotation_range=25,
width_shift_range=0.05,
height_shift_range=0.05,
shear_range=0.05, horizontal_flip=True,
fill_mode='nearest')

val_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255)

# build image augmentation generators
train_generator = train_datagen.flow(train_data, train_labels_enc, batch_size=BATCH_SIZE, shuffle=True)
val_generator = val_datagen.flow(val_data, val_labels_enc, batch_size=BATCH_SIZE, shuffle=False)

我們不會對我們的驗證數據集應用任何轉換(除非是調整大小,因為這是必須的),因為我們將使用它評估每個紀元的模型性能。對于在傳輸學習環境中的圖像增強的詳細解釋,請隨時查看我上面引用的??文章??。讓我們從一批圖像增強轉換中查看一些樣本結果。

img_id = 0
sample_generator = train_datagen.flow(train_data[img_id:img_id+1], train_labels[img_id:img_id+1],
batch_size=1)
sample = [next(sample_generator) for i in range(0,5)]
fig, ax = plt.subplots(1,5, figsize=(16, 6))
print('Labels:', [item[1][0] for item in sample])
l = [ax[i].imshow(sample[i][0][0]) for i in range(0,5)]

??

??

Sample augmented images

你可以清晰的看到與之前的輸出的我們圖像的輕微變化。我們現在構建我們的學習模型,確保 VGG-19 模型的最后兩塊是可以訓練的。

vgg = tf.keras.applications.vgg19.VGG19(include_top=False, weights='imagenet', 
input_shape=INPUT_SHAPE)
# Freeze the layers
vgg.trainable = True

set_trainable = False
for layer in vgg.layers:
if layer.name in ['block5_conv1', 'block4_conv1']:
set_trainable = True
if set_trainable:
layer.trainable = True
else:
layer.trainable = False

base_vgg = vgg
base_out = base_vgg.output
pool_out = tf.keras.layers.Flatten()(base_out)
hidden1 = tf.keras.layers.Dense(512, activation='relu')(pool_out)
drop1 = tf.keras.layers.Dropout(rate=0.3)(hidden1)
hidden2 = tf.keras.layers.Dense(512, activation='relu')(drop1)
drop2 = tf.keras.layers.Dropout(rate=0.3)(hidden2)

out = tf.keras.layers.Dense(1, activation='sigmoid')(drop2)

model = tf.keras.Model(inputs=base_vgg.input, outputs=out)
model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=1e-5),
loss='binary_crossentropy',
metrics=['accuracy'])

print("Total Layers:", len(model.layers))
print("Total trainable layers:", sum([1 for l in model.layers if l.trainable]))


# Output
Total Layers: 28
Total trainable layers: 16

在我們的模型中我們降低了學習率,因為我們不想在微調的時候對預訓練的層做大的位權更新。模型的訓練過程可能有輕微的不同,因為我們使用了數據生成器,因此我們將應用 ??fit_generator(...)?? 函數。

tensorboard_callback = tf.keras.callbacks.TensorBoard(logdir, histogram_freq=1)
reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.5,
patience=2, min_lr=0.000001)

callbacks = [reduce_lr, tensorboard_callback]
train_steps_per_epoch = train_generator.n // train_generator.batch_size
val_steps_per_epoch = val_generator.n // val_generator.batch_size
history = model.fit_generator(train_generator, steps_per_epoch=train_steps_per_epoch, epochs=EPOCHS,
validation_data=val_generator, validation_steps=val_steps_per_epoch,
verbose=1)


# Output
Epoch 1/25
271/271 [====] - 133s 489ms/step - loss: 0.2267 - accuracy: 0.9117 - val_loss: 0.1414 - val_accuracy: 0.9531
Epoch 2/25
271/271 [====] - 129s 475ms/step - loss: 0.1399 - accuracy: 0.9552 - val_loss: 0.1292 - val_accuracy: 0.9589
...
...
Epoch 24/25
271/271 [====] - 128s 473ms/step - loss: 0.0815 - accuracy: 0.9727 - val_loss: 0.1466 - val_accuracy: 0.9682
Epoch 25/25
271/271 [====] - 128s 473ms/step - loss: 0.0792 - accuracy: 0.9729 - val_loss: 0.1127 - val_accuracy: 0.9641

這看起來是我們的最好的模型。它給了我們近乎 96.5% 的驗證精確率,基于訓練精度,它看起來不像我們的第一個模型那樣過擬合。這可以通過下列的學習曲線驗證。

??

??

微調過的預訓練 CNN 的學習曲線

讓我們保存這個模型,因此我們能夠在測試集上使用。

model.save('vgg_finetuned.h5')

這就完成了我們的模型訓練階段。現在我們準備好了在測試集上測試我們模型的性能。

深度學習模型性能評估

我們將通過在我們的測試集上做預測來評估我們在訓練階段構建的三個模型,因為僅僅驗證是不夠的!我們同樣構建了一個檢測工具模塊叫做 ??model_evaluation_utils??,我們可以使用相關分類指標用來評估使用我們深度學習模型的性能。第一步是擴展我們的數據集。

test_imgs_scaled = test_data / 255.
test_imgs_scaled.shape, test_labels.shape

# Output
((8268, 125, 125, 3), (8268,))

下一步包括載入我們保存的深度學習模型,在測試集上預測。

# Load Saved Deep Learning Models
basic_cnn = tf.keras.models.load_model('./basic_cnn.h5')
vgg_frz = tf.keras.models.load_model('./vgg_frozen.h5')
vgg_ft = tf.keras.models.load_model('./vgg_finetuned.h5')

# Make Predictions on Test Data
basic_cnn_preds = basic_cnn.predict(test_imgs_scaled, batch_size=512)
vgg_frz_preds = vgg_frz.predict(test_imgs_scaled, batch_size=512)
vgg_ft_preds = vgg_ft.predict(test_imgs_scaled, batch_size=512)

basic_cnn_pred_labels = le.inverse_transform([1 if pred > 0.5 else 0
for pred in basic_cnn_preds.ravel()])
vgg_frz_pred_labels = le.inverse_transform([1 if pred > 0.5 else 0
for pred in vgg_frz_preds.ravel()])
vgg_ft_pred_labels = le.inverse_transform([1 if pred > 0.5 else 0
for pred in vgg_ft_preds.ravel()])

下一步是應用我們的 ??model_evaluation_utils?? 模塊根據相應分類指標來檢查每個模塊的性能。

import model_evaluation_utils as meu
import pandas as pd

basic_cnn_metrics = meu.get_metrics(true_labels=test_labels, predicted_labels=basic_cnn_pred_labels)
vgg_frz_metrics = meu.get_metrics(true_labels=test_labels, predicted_labels=vgg_frz_pred_labels)
vgg_ft_metrics = meu.get_metrics(true_labels=test_labels, predicted_labels=vgg_ft_pred_labels)

pd.DataFrame([basic_cnn_metrics, vgg_frz_metrics, vgg_ft_metrics],
index=['Basic CNN', 'VGG-19 Frozen', 'VGG-19 Fine-tuned'])

??

??

Model accuracy

看起來我們的第三個模型在我們的測試集上執行的最好,給出了一個模型精確性為 96% 的 F1 得分,這非常好,與我們之前提到的研究論文和文章中的更復雜的模型相當。

總結

瘧疾檢測不是一個簡單的過程,全球的合格人員的不足在病例診斷和治療當中是一個嚴重的問題。我們研究了一個關于瘧疾的有趣的真實世界的醫學影像案例。利用 AI 的、易于構建的、開源的技術在檢測瘧疾方面可以為我們提供最先進的精確性,因此使 AI 具有社會效益。

我鼓勵你查看這篇文章中提到的文章和研究論文,沒有它們,我就不能形成概念并寫出來。如果你對運行和采納這些技術感興趣,本篇文章所有的代碼都可以在??我的 GitHub 倉庫???獲得。記得從??官方網站??下載數據。

讓我們希望在健康醫療方面更多的采納開源的 AI 能力,使它在世界范圍內變得更便宜、更易用。

責任編輯:龐桂玉 來源: Linux中國
相關推薦

2017-08-03 11:00:20

2017-07-14 10:35:06

2021-07-01 08:00:00

深度學習神經網絡架構

2022-10-26 15:41:38

深度學習Deepfake機器學習

2021-10-08 09:46:42

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

2016-03-16 09:33:40

2019-06-25 10:09:42

Web攻擊機器學習網絡攻擊

2025-01-13 10:00:00

2017-09-20 16:25:00

深度學習視覺領域計算機

2023-12-19 16:01:40

深度學習人工智能目標檢測

2017-10-20 14:46:26

深度學習復數噪聲

2017-10-09 14:51:15

深度學習復數實數

2021-06-11 05:37:20

TensorFlow2深度學習Keras API

2017-09-22 11:45:10

深度學習OpenCVPython

2021-11-02 11:48:39

深度學習惡意軟件觀察

2023-01-09 08:00:00

遷移學習機器學習數據集

2017-10-02 16:13:47

深度學習目標檢測計算機視覺

2023-08-23 12:38:10

2021-03-08 11:28:59

人工智能深度學習Python

2023-02-23 07:46:48

學習模型數據倉庫
點贊
收藏

51CTO技術棧公眾號

亚瑟一区二区三区四区| 伊人福利在线| 精品一区二区在线免费观看| 久久这里有精品视频| 久久无码专区国产精品s| 免费毛片b在线观看| 国产精品久久毛片av大全日韩| 97碰碰视频| 成人a v视频| 欧美在线精品一区| 亚洲男人av电影| 手机av在线网站| 国模套图日韩精品一区二区| 中文字幕一区二区视频| 九色一区二区| 99热这里只有精品9| 国产精品久久久亚洲一区| 久久久国产精彩视频美女艺术照福利| free性中国hd国语露脸| 成人精品在线| 日本丶国产丶欧美色综合| 日本不卡一区二区三区四区| 日韩大片b站免费观看直播| 激情图片小说一区| 日本高清不卡的在线| 在线看的片片片免费| 台湾色综合娱乐中文网| 日韩视频免费观看高清完整版| 国产精品69页| 国产直播在线| 亚洲五码中文字幕| 免费看啪啪网站| 国产女主播在线直播| 成人a免费在线看| 91最新在线免费观看| 糖心vlog精品一区二区| 免费欧美日韩| 97香蕉久久超级碰碰高清版| 国产亚洲精品久久久久久无几年桃| 99精品视频在线观看免费播放| 亚洲九九九在线观看| 国产ts在线观看| 精品视频在线一区| 欧美视频在线不卡| 激情视频综合网| 女海盗2成人h版中文字幕| 亚洲一区二区在线观看视频 | 国产成人精品免费看视频| 日日欢夜夜爽一区| 日本中文字幕久久看| 国产成人无码精品| 夜夜嗨av一区二区三区网站四季av| 欧美乱大交xxxxx| 久久久久久久久久97| 大片网站久久| 这里只有视频精品| 色欲AV无码精品一区二区久久| 亚洲精品3区| 亚洲另类图片色| 97人妻精品一区二区三区免| 免费一区二区| 一级做a爰片久久毛片美女图片| 一区二区精品免费| 成人在线国产| 久热国产精品视频| 久久久无码精品亚洲国产| 黄色成人91| 91国产视频在线| 久久青青草原亚洲av无码麻豆 | 亚洲自拍偷拍网站| www.国产在线视频| а√在线中文网新版地址在线| 精品福利一区二区| 日韩中文字幕二区| 成人一级视频| 日韩一区二区三区四区五区六区 | 波多野结衣在线一区二区| 亚洲成人精品久久久| 久久午夜夜伦鲁鲁片| 久久不见久久见免费视频7| 国产一区二区三区欧美| 特一级黄色录像| 亚洲国产午夜| 国产999在线观看| 国产精品无码久久av| 成人久久视频在线观看| 欧美午夜精品久久久久久蜜| 在线免费观看黄色网址| 亚洲男帅同性gay1069| 天天夜碰日日摸日日澡性色av| 日韩在线影院| 欧美一区二区三区婷婷月色| 黄色录像a级片| 99久久综合狠狠综合久久aⅴ| 欧美日韩999| 超碰在线观看91| 国产精品99久久久| 欧美日韩视频在线一区二区观看视频| 99re热久久这里只有精品34| 一级日本不卡的影视| 久热免费在线观看| 日本精品视频| 一本色道久久综合狠狠躁篇的优点 | 国产91对白在线播放| 中文字幕日韩三级| av福利精品导航| 中文字幕免费高| 亚洲日本在线观看视频| 精品人在线二区三区| 中国1级黄色片| 一区二区三区四区五区精品视频| 国产日本欧美一区二区三区在线| 色噜噜在线播放| 1024成人网色www| 久久精品网站视频| 红杏一区二区三区| 久久久av一区| 成人免费一区二区三区| 久久在线观看免费| 久久国产午夜精品理论片最新版本| 久久免费资源| 亚洲三级免费看| 亚洲 欧美 视频| 国产一区二区毛片| 亚洲欧美日产图| 综合在线影院| 亚洲日本成人女熟在线观看| 99久在线精品99re8热| 国产精品123| 992tv成人免费观看| 精品国产黄a∨片高清在线| 亚洲精品电影在线| 劲爆欧美第一页| 国产老肥熟一区二区三区| 亚洲精品高清国产一线久久| 澳门av一区二区三区| 亚洲另类xxxx| 亚洲大片免费观看| 26uuu成人网一区二区三区| 青青草精品视频在线| 91夜夜蜜桃臀一区二区三区| 欧美成人合集magnet| 国产精品区在线观看| 综合久久一区二区三区| mm131国产精品| 水蜜桃精品av一区二区| 国产精品久久久久久一区二区 | 国语一区二区三区| 久久久久久亚洲精品| 国产91麻豆视频| 亚洲成人精品影院| 97香蕉碰碰人妻国产欧美| 亚洲美女毛片| 久久久久资源| 国产成人精品一区二三区在线观看 | 91精品国产综合久久香蕉922| 欧美18hd| 日韩亚洲欧美在线| 久久精品国产亚洲av香蕉| 成人成人成人在线视频| 亚洲 高清 成人 动漫| 免费久久精品| 国产免费一区二区三区在线能观看| 137大胆人体在线观看| 69堂国产成人免费视频| 青春草免费视频| 成人av免费网站| 无遮挡又爽又刺激的视频 | 最近2019中文字幕第三页视频| 亚洲视频中文字幕在线观看| 亚洲免费伊人电影| 熟妇高潮一区二区| 奶水喷射视频一区| 亚洲人成影视在线观看| 日韩一区二区三区高清在线观看| 久久人人爽人人| 激情在线视频| 91精品在线免费| 日本少妇xxxx动漫| 久久精品人人做人人爽97| 天堂av在线8| av不卡在线| 亚洲高清视频一区二区| 91精品国产乱码久久久竹菊| 国产91精品在线播放| mm1313亚洲国产精品美女| 亚洲黄色av女优在线观看| 中文字幕+乱码+中文| 亚洲夂夂婷婷色拍ww47| 一级黄色片大全| 国产一区二区三区四区五区入口| 男人和女人啪啪网站| 日韩成人免费| 国产一区二区三区色淫影院| 欧美少妇激情| 欧美在线视频观看免费网站| dy888亚洲精品一区二区三区| 亚洲国产精品高清久久久| 伊人免费在线观看高清版| 亚洲成av人影院| 黑人狂躁日本娇小| 久久影院午夜片一区| 乱码一区二区三区| 久久成人久久爱| 精品一区二区中文字幕| 午夜日韩电影| 亚洲欧洲一二三| 在线成人动漫av| 超碰国产精品久久国产精品99| 欧美一级二级视频| 欧美激情欧美激情在线五月| 在线看的av网站| 亚洲免费一在线| 色噜噜一区二区三区| 日韩一区二区精品葵司在线| 特级西西444www高清大视频| 欧美日韩免费看| 国产性猛交普通话对白| 亚洲特级片在线| 萌白酱视频在线| 国产精品丝袜91| 亚洲国产av一区| 91丨porny丨中文| 久久久久亚洲AV成人网人人小说| 久久99精品久久久久| 成人羞羞国产免费网站| 亚洲激情欧美| avav在线播放| 女人色偷偷aa久久天堂| 在线播放豆国产99亚洲| av一区二区高清| 欧美一二三区| 欧美人妖在线| 欧美亚洲国产免费| 九九视频免费观看视频精品 | 91综合视频| 亚洲人成网站在线观看播放| 成人在线亚洲| 一区二区三区免费看| 99久久www免费| 宅男一区二区三区| 婷婷久久综合| 男女爱爱视频网站| 中文字幕日韩欧美精品高清在线| 一区二区三区在线观看www| 日韩中文字幕高清在线观看| 五码日韩精品一区二区三区视频| 国产一区二区三区四区| 日本在线一区| 欧美wwwww| 超碰免费在线公开| 欧美福利在线| 老太脱裤子让老头玩xxxxx| 99精品福利视频| 天天摸天天碰天天添| 久久亚洲视频| 中国黄色片免费看| 国产一区美女在线| 中文字幕18页| 久久天堂av综合合色蜜桃网 | 亚洲一区在线观看视频| 久久综合加勒比| 精品成人av一区| 无码人妻精品一区二区| 精品视频1区2区3区| 99久久精品国产成人一区二区| 欧美成人bangbros| 天堂中文在线视频| 在线观看欧美日韩国产| 国产在线高清视频| 久久露脸国产精品| 免费成人动漫| 成人精品福利视频| 都市激情亚洲欧美| 日韩电影天堂视频一区二区| 99精品视频在线| 自拍日韩亚洲一区在线| 蜜桃久久av一区| 一级全黄裸体片| 国产日韩欧美综合在线| 国产大片免费看| 精品欧美激情精品一区| 最近中文字幕在线视频| 欧美变态tickling挠脚心| 免费在线观看一级毛片| 久久久999精品视频| 神马久久午夜| 91影院在线免费观看视频| 日韩大胆成人| 天堂v在线视频| 欧美亚洲一区二区三区| 国产又粗又长又爽又黄的视频| 2021久久国产精品不只是精品| 久久99久久99精品免费看小说| 婷婷久久综合九色国产成人 | 亚洲第一页中文字幕| 国产高清视频免费最新在线| 欧美国产乱视频| 国产一区二区三区朝在线观看| 国产精品久久亚洲| 成人影院在线| 成人在线观看a| 成人一级黄色片| 日韩在线一卡二卡| 日韩欧美在线视频观看| 亚洲xxx在线| 日韩视频免费中文字幕| 惠美惠精品网| 国产精品一区二区三区免费| 日本一本不卡| 欧美亚洲一二三区| 国产不卡一区视频| 多男操一女视频| 欧美伊人精品成人久久综合97| 殴美一级特黄aaaaaa| 久久中文字幕一区| 国产精品久久久久久久久久齐齐| 久久99国产精品| 一区在线免费观看| 三上悠亚 电影| 亚洲色图制服丝袜| 伊人22222| 中文字幕一精品亚洲无线一区| 欧美大片免费观看网址| 精品免费国产| 在线看片一区| 性生活在线视频| 亚洲欧美日韩精品久久久久| 在线观看国产小视频| 国产一区二区三区在线视频| 夜鲁夜鲁夜鲁视频在线播放| 精品国产乱码久久久久久108| 黄色日韩在线| 91福利视频免费观看| 亚洲欧美激情插| 国产三级漂亮女教师| 久久久精品免费| 精品国产一区二区三区性色av | 欧美黑人猛交| 91超碰在线电影| 欧美一区综合| www.日本久久| 亚洲久草在线视频| 性一交一乱一伧老太| 欧美肥老妇视频| 成人在线超碰| 精品人妻少妇一区二区| aaa国产一区| 精品免费囯产一区二区三区| 亚洲视频在线观看免费| 国产精品亚洲d| 亚洲在线色站| 国产一区二区三区免费| 九九视频在线免费观看| 亚洲电影免费观看高清| 蜜桃视频www网站在线观看| 欧美日韩精品一区| 日本va欧美va精品发布| 免费黄色国产视频| 欧美一区二区视频网站| 久草在线新免费首页资源站| 九色一区二区| 日本大胆欧美人术艺术动态| 日韩亚洲欧美中文字幕| 精品国产髙清在线看国产毛片 | 国产一区红桃视频| 中出一区二区| 波多野结衣有码| 91久久精品日日躁夜夜躁欧美| 三级外国片在线观看视频| 99在线观看| 日韩一区精品字幕| 伊人在线视频观看| 亚洲高清免费观看高清完整版| 亚洲第一av| www.午夜色| 99视频一区二区三区| 中文字幕码精品视频网站| 欧美大胆在线视频| 亚洲免费专区| 国产探花在线观看视频| 天天色 色综合| 巨大荫蒂视频欧美另类大| 精品日本一区二区三区在线观看| 麻豆精品在线看| 好吊妞视频一区二区三区| 久久精品国产一区| 欧美亚洲色图校园春色| 中文av字幕在线观看| 狠狠久久亚洲欧美专区| 自拍视频在线| 久久99精品久久久久久青青日本 | 精品午夜一区二区| 蜜桃视频一区二区三区在线观看| 久久精品久久国产| 丝袜一区二区三区| 日韩激情啪啪| 樱花草www在线| 欧美性做爰猛烈叫床潮| 91www在线|