精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

日本一区二区高清视频| 久久久久9999亚洲精品| 欧美成aaa人片在线观看蜜臀| 久久久精品高清| 成人午夜在线影视| av男人天堂一区| 国产精品久久久久aaaa九色| 国产高潮国产高潮久久久91| 精品综合久久88少妇激情| 色婷婷亚洲综合| 91久久久一线二线三线品牌| 五月天精品在线| 日韩高清一区| 欧亚洲嫩模精品一区三区| 激情成人午夜视频| 欧美精品九九99久久| 999一区二区三区| 国际av在线| 国产精品一区二区不卡| 国产91精品网站| 激情视频在线播放| 精品国产一区二区三区久久久蜜臀| 欧美日韩国产精品成人| 国产h视频在线播放| 日本在线天堂| 久久久久久久一区| 成人av免费看| 亚洲天堂999| 精品中国亚洲| 日韩一区二区三区高清免费看看| 777米奇影视第四色| 午夜av在线免费观看| 国产精品麻豆一区二区| 欧美日韩一区在线视频| 国内爆初菊对白视频| 老汉av免费一区二区三区| 欧美在线视频一区二区| 日本亚洲色大成网站www久久| 久久日文中文字幕乱码| 国产香蕉97碰碰久久人人| 这里只有精品在线观看视频| 国产视频网站一区二区三区| 欧美日韩国产系列| 亚洲免费一级视频| 青青热久免费精品视频在线18| 亚洲成年人影院| 国产女教师bbwbbwbbw| 浪潮av一区| 国产精品伦一区| 亚洲精品二区| 国产精品玖玖玖| 日韩av在线播放中文字幕| 91精品国产高清久久久久久| 欧美精品videos极品| 欧美~级网站不卡| 精品中文字幕乱| 老湿机69福利| 黄色成人91| 高清一区二区三区四区五区| 久久久久黄色片| 黄色成人在线网站| 午夜精品福利在线观看| 国产在线观看成人| 亚洲精品看片| 人人澡人人澡人人看欧美| 青草视频在线观看免费| 欧美日韩一区二区三区视频播放| 亚洲性无码av在线| 免费黄色激情视频| 欧美 日韩 国产 一区| 欧美激情精品久久久久| 在线免费观看毛片| 午夜一区在线| 久久精品久久精品亚洲人| 视频国产一区二区| 国产精品草草| 91国语精品自产拍在线观看性色 | 草草视频在线免费观看| av中文字幕在线观看第一页 | 久久永久免费| 国产精品久久久久久久久久| 亚洲综合精品国产一区二区三区| 国产在线乱码一区二区三区| 99视频在线| 欧美日韩激情视频一区二区三区| 国产日韩欧美综合一区| 久久天天东北熟女毛茸茸| 97蜜桃久久| 在线欧美一区二区| 日本一二三四区视频| 桃子视频成人app| 欧美日本视频在线| 女同性αv亚洲女同志| 一区二区小说| 久久伊人色综合| www.国产色| 国产在线一区二区| 久中文字幕一区| 九色porny在线| 欧美日韩在线免费| 爽爽爽在线观看| 欧美日韩另类图片| 久久久精品2019中文字幕神马| www.天天色| 精品一区二区免费在线观看| 精品综合久久久| 丰满大乳国产精品| 国产欧美日韩三级| 欧美 日韩 国产 高清| 日韩一级二级| 精品99一区二区三区| 国产亚洲精品精品精品| 在线观看日韩av电影| 成人免费视频97| 国产男女猛烈无遮挡| 经典三级在线一区| 欧美亚洲免费高清在线观看| 里番在线播放| 欧美久久高跟鞋激| 在哪里可以看毛片| 亚洲精品日韩久久| 91视频国产精品| av大全在线免费看| 色综合天天综合网国产成人综合天| 亚洲热在线视频| 久久大综合网| 国产精品1区2区在线观看 | 欧美亚洲日本一区| 捆绑裸体绳奴bdsm亚洲| 欧美1区二区| 欧美日韩xxx| 一二三区中文字幕| 久久久99久久| 黄色片视频在线免费观看| 亚洲美女久久精品| 精品国产乱码91久久久久久网站| 欧美成人精品一区二区免费看片| 欧美三区在线| 91精品国产一区| 好吊色一区二区三区| 亚洲精品日日夜夜| 欧美激情第四页| 中国成人一区| 亚洲精品免费一区二区三区| 亚洲毛片在线播放| 亚洲综合色在线| 国产成人a亚洲精v品无码| 精品精品国产毛片在线看| 欧美日韩国产123| 性一交一乱一透一a级| 亚洲欧美激情视频在线观看一区二区三区| 亚洲老女人av| 97人人精品| 91欧美激情另类亚洲| 国产日产一区二区| 欧美一卡二卡三卡| 久久激情免费视频| 不卡的av中国片| 国产欧美在线一区| 精品国产91乱码一区二区三区四区| 日韩av免费在线看| av在线电影网| 亚洲成人动漫精品| 久久丫精品国产亚洲av不卡| 久久久综合网| 中文字幕中文字幕99| 精品国产18久久久久久二百| 欧美激情第三页| 天堂√在线中文官网在线| 欧美日韩激情视频| 亚洲精品午夜视频| 麻豆精品视频在线观看| 91看片淫黄大片91| 农村少妇一区二区三区四区五区| 日韩av观看网址| 米奇精品一区二区三区| 精品福利视频一区二区三区| 国产成人精品一区二三区| 国产欧美一区二区在线| 亚洲一二三不卡| 亚洲精品美女| 少妇免费毛片久久久久久久久 | 午夜视频在线观看网站| 欧美一级欧美一级在线播放| 日韩熟女精品一区二区三区| 国产午夜精品一区二区三区四区| 五月天开心婷婷| 精品动漫av| 日本一区视频在线| 欧美成人一级| 国产91久久婷婷一区二区| 成人看av片| 国产视频一区在线| 国产精品自偷自拍| 欧美日韩日本国产| 69夜色精品国产69乱| 91在线国产福利| 在线播放免费视频| 亚洲永久免费| 91免费版看片| av在线不卡免费观看| 国产成人一区二区三区免费看| 国产精品高清乱码在线观看| 欧美日韩成人在线视频| lutube成人福利在线观看| 精品国产亚洲一区二区三区在线观看| 免费的毛片视频| 又紧又大又爽精品一区二区| 熟女高潮一区二区三区| 丁香五精品蜜臀久久久久99网站| 国产一级特黄a大片免费| 91久久在线| 国产盗摄视频在线观看| 狠狠综合久久av一区二区蜜桃| 高清不卡日本v二区在线| 欧美电影在线观看网站| 欧美一级bbbbb性bbbb喷潮片| 亚洲成人黄色片| 欧美日韩一级片网站| 国产精品久久久免费视频| 一区二区欧美国产| 黄色录像免费观看| 国产精品色眯眯| 久久av无码精品人妻系列试探| 成人深夜在线观看| 一个人看的视频www| 欧美精选在线| aaa免费在线观看| 亚洲日本va中文字幕| 国产色视频一区| 黄色成人小视频| 国产精品久久97| 久久精品女人天堂av免费观看| 欧美激情一级精品国产| www在线免费观看视频| 色婷婷综合成人av| 99riav在线| 中文字幕亚洲专区| 在线看免费av| 日韩最新中文字幕电影免费看| 99国产精品久久久久久久成人 | 国产精品中文字幕制服诱惑| 91免费精品国自产拍在线不卡| 色哟哟网站在线观看| 国产精品一卡二卡| 精产国品一区二区三区| 国产精品一区二区男女羞羞无遮挡| 四虎成人在线播放| 国产激情精品久久久第一区二区| 东北少妇不带套对白| 欧美精品不卡| 国产精品无码免费专区午夜| 国产综合网站| 成人毛片一区二区| 国产美女诱惑一区二区| 欧洲黄色一级视频| 欧美亚洲自偷自偷| 久久久久免费精品| 秋霞电影一区二区| 中日韩av在线播放| 国产伦精品一区二区三区在线观看| 亚洲一区二区中文字幕在线观看| 国产99一区视频免费| 黄色片视频免费观看| 久久婷婷综合激情| 久久久久久成人网| 亚洲天堂成人在线观看| 欧美成人片在线观看| 亚洲国产精品一区二区www| 日本在线观看中文字幕| 色嗨嗨av一区二区三区| 91亚洲国产成人久久精品麻豆| 日韩一级大片在线观看| 日本人妻丰满熟妇久久久久久| 亚洲精品一区中文字幕乱码| aaa日本高清在线播放免费观看| 欧美超级免费视 在线| 欧美男人天堂| 国产玖玖精品视频| 国产精品网址| 日韩av大全| 中文字幕人成人乱码| 日韩a∨精品日韩在线观看| 日日摸夜夜添夜夜添精品视频| 亚洲免费黄色网| 丁香桃色午夜亚洲一区二区三区| 3d动漫精品啪啪一区二区下载 | 成人高清免费在线| 久久久久在线观看| 成人1区2区| 57pao国产精品一区| 国精产品一区一区三区四川| 成人在线视频网站| 麻豆成人入口| 中文字幕在线中文字幕日亚韩一区| 黄色成人精品网站| 天天操天天爱天天爽| av中文字幕一区| 蜜桃av.com| 福利视频第一区| 国产伦精品一区二区三区免.费 | 精品国产sm最大网站| 男人的天堂在线| 久久人人爽人人| 亚洲视频自拍| 日韩精品久久一区| 亚洲手机在线| 又黄又爽又色的视频| 国产人伦精品一区二区| 日韩人妻无码一区二区三区99| 欧美一区二区高清| 国产高清免费av在线| 91精品国产91久久久久久吃药| 无码国模国产在线观看| 亚洲欧美日韩另类精品一区二区三区 | 色综合亚洲精品激情狠狠| 日本黄色免费在线| 国产精品一 二 三| 亚洲欧洲美洲一区二区三区| 亚洲一二三区av| 91老师国产黑色丝袜在线| 精品无码av在线| 日韩一卡二卡三卡四卡| 欧美18hd| 国产精品视频一区二区三区四| 亚洲国产合集| 日韩小视频在线播放| 国产风韵犹存在线视精品| 青花影视在线观看免费高清| 欧美性受xxxx| 成人在线观看免费| 欧洲日本亚洲国产区| 欧美一级二级三级视频| 免费观看国产精品视频| 不卡av电影在线播放| 日韩人妻无码一区二区三区99 | 欧美激情性爽国产精品17p| 欧美美女一级片| 国产精品电影一区二区| 自拍偷拍第9页| 欧美色视频一区| 在线观看美女网站大全免费| 国产精品日韩在线一区| 成人综合一区| 午夜免费福利视频在线观看| 国产精品福利av| 国产日韩欧美一区二区东京热| 久久精品国产96久久久香蕉| 欧美亚洲福利| 女女百合国产免费网站| 国产成人精品免费在线| 国产主播在线播放| 亚洲福利视频久久| 中文字幕影音在线| 日本视频一区在线观看| 奇米精品一区二区三区四区| 亚洲激情图片网| 激情成人在线视频| 美国成人毛片| 国产精品日日摸夜夜添夜夜av| 99久久www免费| 香蕉视频色在线观看| 亚洲国产日日夜夜| www.99r| 欧美色蜜桃97| 久热免费在线观看| 国产精品乱人伦| 亚洲国产成人一区二区 | 亚洲欧美日韩综合一区| 国产在线精品免费| 亚洲一区二区91| 亚洲欧美精品伊人久久| 91麻豆免费在线视频| 粉嫩av免费一区二区三区| 久久成人免费| 午夜成人亚洲理伦片在线观看| 日韩一区二区影院| 免费一二一二在线视频| 午夜精品短视频| 国产精品99久久久| 毛片视频网站在线观看| 有码中文亚洲精品| 涩涩屋成人免费视频软件| 777久久久精品一区二区三区| 中文字幕精品三区| 成人高潮片免费视频| 精品国产一区二区三区久久| 亚洲一二三区视频| 成人在线观看a| 亚洲精品高清在线观看| 男人的天堂在线视频| 91久久精品国产91久久性色tv| 先锋影音久久| 国产高潮流白浆| 亚洲人线精品午夜| 99精品国产高清一区二区麻豆| 成人在线观看黄| 一区二区在线电影| 浮生影视网在线观看免费| 国产精品久久一区二区三区|