# 六、圖像識別與分類
知識投資永遠是最大的利益。
——本杰明·富蘭克林
在計算機視覺的保護下,圖像識別是一個活躍的跨學科研究領域。 顧名思義,圖像或對象識別是識別圖像或視頻序列中的對象的任務。 傳統上,該領域利用數學和計算機輔助建模以及對象設計方面的進步。 這些年來,已經開發了一些手工標注的數據集,以測試和評估圖像識別系統。 我們現在稱它們為傳統技術,一直統治著整個場景,并且不斷地改進這項任務,直到最近。 2012 年,深度學習參加了 ImageNet 競賽,為快速改善和進步計算機視覺和深度學習技術打開了閘門。
在本章中,我們將從深度學習(尤其是遷移學習)的角度介紹圖像識別和分類的概念。 本章將涵蓋以下方面:
* 深度學習圖像分類簡介
* 基準數據集
* 最新的深度圖像分類模型
* 圖像分類和遷移學習用例
本章從本書的第三部分開始。 在本書的這一部分中,我們將涵蓋涉及前兩部分中討論的概念和技術的案例研究。 這些用例將呈現現實世界的主題/研究領域,并幫助您了解如何在不同的環境中利用遷移學習。 您可以在 [GitHub 存儲庫](https://github.com/dipanjanS/hands-on-transfer-learning-with-python)中的`Chapter 6`文件夾中快速閱讀本章的代碼。 可以根據需要參考本章。
# 基于深度學習的圖像分類
**卷積神經網絡**(**CNN**)是這項深度學習革命的核心,旨在改善圖像分類任務。 CNN 是處理圖像數據的專用神經網絡。 作為快速補充,CNN 可以通過它們共享的權重架構幫助我們推斷出位移和空間不變特征,并且基本上是前饋網絡的變體。 在第 3 章“了解深度學習架構”和第 5 章中,我們已經詳細介紹了 CNN 的基礎知識。 在繼續進行之前,我們鼓勵讀者快速復習以更好地理解。 下圖展示了運行中的典型 CNN:

典型的 CNN,[來自這個頁面](https://en.wikipedia.org/wiki/File:Typical_cnn.png)
神經網絡最早出現在 2011 年的圖像分類競賽中。受 GPU 訓練的網絡開始贏得競賽。 在 2012 年,深層的 CNN 在 ImageNet 圖像分類任務上的表現從以前的最好水平提高到 83%,這是世界上第一次注意到。 結果令人驚訝,足以引起全球關注,并有助于通過深度學習解決用例的泛濫。
# 基準數據集
圖像分類,或就此而言,任何分類任務,本質上都是監督學習任務。 受監督的任務通過可用的基礎訓練集了解不同的類別。
即使 CNN 是共享權重的優化前饋網絡,但要在深層 ConvNet 中訓練的參數數量可能仍然很大。 這就是為什么需要大量的訓練才能獲得表現更好的網絡的原因之一。 幸運的是,全球研究小組一直在努力收集,手工標注和眾包不同的數據集。 這些數據集可用于對不同算法的表現進行基準測試,以及識別不同比賽中的獲勝者。
以下是圖像分類領域中廣泛接受的基準數據集的簡要列表:
* **ImageNet**:這是一個具有黃金標準的可視數據集,具有超過 1400 萬個帶有手工標注的高分辨率彩色圖像,涵蓋了 20,000 個類別。 它是 2009 年由普林斯頓大學計算機科學系設計用于視覺對象識別任務的。此后,此數據集(在其 1000 個非重疊類的修整版本中)已用作 [*ImageNet 大規模視覺識別挑戰*](https://arxiv.org/abs/1409.0575)的基礎。
* **8000 萬個微小圖像數據集**:顧名思義,該 MIT 數據集包含從互聯網收集的 8000 萬個圖像,并標記了 75,000 多個不同的非抽象英語名詞。 該數據集還為其他廣泛使用的數據集(包括 CIFAR 數據集)奠定了基礎。
* **CIFAR-10**:由加拿大高級研究所開發,CIFAR-10 是**機器學習**(**ML**)研究中使用最廣泛的數據集之一。 該數據集包含 60,000 張橫跨 10 個非重疊類的低分辨率圖像。
* **CIFAR-100**:來自同一研究組,該數據集包含 60,000 張圖像,均勻分布在 100 個不同的類別中。
* **上下文中的公共對象**:**上下文中的公共對象**(**COCO**)是用于對象標識,分段和字幕的大型可視數據庫。 該數據集包含超過 200,000 張跨越不同類別的標記圖像。
* **開放圖像**:這可能是最大的可用標注數據集之一。 該數據集的版本 4 包含超過 900 萬個帶標注的圖像。
* **Caltech 101 和 Caltech 256**:這些數據集包含分別跨越 101 和 256 個類別的帶標注的圖像。 加州理工學院 101 包含約 9,000 張圖像,而加州理工學院 256 包含近 30,000 張圖像。
* **斯坦福犬數據集**:這是一個有趣的數據集,特定于不同的犬種。 它包含 20,000 個彩色圖像,涵蓋 120 個不同的犬種。
* **MNIST**:MNIST 是有史以來最著名的視覺數據集之一,已成為 ML 愛好者的事實上的 *HelloWorld* 數據集。 它包含超過 60,000 個手工標記的數字(零到九個數字)。
上面的列表僅是冰山一角。 還有許多其他數據集可以捕獲世界的不同方面。 準備這些數據集是一個痛苦且耗時的過程,但是這些數據集使深度學習在當前形式下如此成功。 鼓勵讀者詳細研究這些和其他此類數據集,以了解它們背??后的細微差別以及這些數據集為我們解決的挑戰。 在本章和后續章節中,我們將利用其中的一些數據集來理解遷移學習的概念。
# 最新的深度圖像分類模型
多年來,深度學習已引起了廣泛的關注和炒作。 不足為奇的是,在全球范圍內以深度學習為中心的知名競賽,會議和期刊上共享了大量研究工作。 尤其是圖像分類架構已經引起人們的關注,這幾年來,定期進行迭代改進一直是人們關注的重點。 讓我們快速了解一些表現最佳,最流行的最新深度圖像分類架構:
* **AlexNet**:這是可以歸功于*打開閘門*的網絡。 由深度學習的先驅之一 Geoffrey Hinton 和團隊設計,該網絡將前五名的錯誤率降低到了 15.3%。 它也是最早利用 GPU 加快學習過程的架構之一。
* **VGG-16**:牛津大學視覺幾何小組的網絡是表現最好的架構之一,廣泛用于對其他設計進行基準測試。 VGG-16 采用了一個簡單的架構,該架構是基于`3 x 3`個卷積層(一個 16 層)相互堆疊,然后是一個最大池化層,以實現強大的表現。 該模型由稍微更復雜的模型 **VGG19** 繼承。
* **Inception**:也稱為 **GoogleNet** ,該網絡是在 **ImageNet 大規模視覺識別挑戰賽**(**ILSVRC**)在 2014 年實現了前五名的錯誤率為 6.67%。 它是最早實現接近人類表現的架構之一。 該網絡背后的新穎之處在于使用了起始層,該起始層包括了在同一級別將不同大小的內核連接在一起的過程。
* **ResNet**:由 Microsoft Research Asia 引入,**殘差網絡**(**ResNet**)是一種新穎的架構,利用批量規范化和跳過連接來實現僅僅 3.57% 的前五位的錯誤率。 它比諸如 VGG 之類的簡單架構要深很多(152 層)并且要復雜得多。
* **MobileNet**:盡管大多數架構都在競爭中勝過其他架構,但每個新的復雜網絡都需要更多的計算能力和數據資源。 MobileNet 偏離了此類架構,并被設計為適用于移動和嵌入式系統。 該網絡利用了一種新穎的思想,即使用深度可分離卷積來減少訓練網絡所需的參數總數。
我們提供了基于深度學習的圖像分類空間中一些最新架構的快速概述和概述。 有關詳細討論,讀者可以查看第 3 章,“了解深度學習架構”中的“卷積神經網絡”部分。
# 圖像分類與遷移學習
到目前為止,我們已經討論了什么是圖像分類。 在本節中,我們將通過構建自己的分類器來弄清手。 在本章的較早部分中,我們簡要提到了著名的基準測試數據集,包括 CIFAR-10 和 Stanford Dogs 數據集,我們將在接下來的部分中重點介紹這些數據集。 我們還將利用預先訓練的模型來了解我們如何利用遷移學習來改進我們的模型。
# CIFAR-10
**CIFAR-10** 是深度學習領域中使用最廣泛的圖像數據集之一。 由加拿大高級研究所準備,這是一個相當不錯的數據集。 該數據集的主要優點是它包含 10 個非重疊類別的平衡分布。 圖像的分辨率和尺寸較低,因此可以將數據集用于在較小的內存占用量系統上進行訓練。
# 建立圖像分類器
CIFAR-10 是少數可用的平衡數據集之一。 它的整體大小為 60,000 張圖像。 以下代碼段加載 CIFAR-10 數據集,并設置訓練變量和測試變量:
```py
# load CIFAR dataset
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
```
數據集中的圖像分辨率很低,有時甚至很難貼上標簽。 IPython 筆記本`CIFAR-10_CNN_Classifier.ipynb`中提供了本節中共享的代碼。
我們已經討論了 CNN 以及如何針對視覺數據集對其進行優化。 CNN 遵循權重分配原則以減少參數數量; 從頭開始開發它們不僅需要強大的深度學習技能,還需要巨大的基礎架構需求。 牢記這一點,從頭開始開發 CNN 并測試我們的技能將很有趣。
以下代碼片段展示了使用 Keras 構建的非常簡單的 CNN,它只有五層(兩層卷積,一層最大池化,一層密集和一層最終 softmax 層):
```py
model = Sequential()
model.add(Conv2D(16, kernel_size=(3, 3),
activation='relu',
input_shape=INPUT_SHAPE))
model.add(Conv2D(32, (3,3), padding='same',
kernel_regularizer=regularizers.l2(WEIGHT_DECAY),
activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(NUM_CLASSES, activation='softmax'))
```
為了提高總體泛化表現,該模型還包含`BatchNormalization`層和`DropOut`層。 這些層有助于我們控制過擬合,還可以防止網絡存儲數據集本身。
我們僅用 25 個周期來運行模型,以在驗證集上達到約 65% 的準確率。 以下屏幕快照顯示了訓練后的模型的輸出預測:

來自基于 CNN 的 CIFAR-10 分類器的預測
盡管絕不是最先進的結果,但結果足夠不錯。 讀者應該記住,這個 CNN 只是為了展示手頭的巨大潛力,我們鼓勵您嘗試在同一行上進行實驗。
# 遷移知識
由于本章和書著重于遷移學習,因此讓我們快速進行利用和遷移所學信息的實際任務。 在上一節中,我們討論了不同的最新 CNN 架構。 現在,讓我們利用在 ImageNet 上訓練的 VGG-16 模型對 CIFAR-10 數據集中的圖像進行分類。 該部分的代碼在 IPython 筆記本`CIFAR10_VGG16_Transfer_Learning_Classifier.ipynb`中可用。
ImageNet 是一個龐大的視覺數據集,具有 20,000 多個不同類別。 另一方面,CIFAR-10 僅限于 10 個非重疊類別。 像 VGG-16 這樣的強大網絡需要巨大的計算能力和時間來訓練,以達到比人類更好的表現。 這將遷移學習帶入了畫面。 由于我們大多數人都無法訪問無限的計算,因此我們可以在兩種不同的設置下利用這些網絡:
* 使用經過預訓練的最新網絡作為特征提取器。 這是通過刪除頂部分類層并使用倒數第二層的輸出來完成的。
* 在新數據集上微調最新的網絡。
我們將利用 VGG-16 作為特征提取器,并在其之上構建自定義分類器。 以下代碼段加載并準備了 CIFAR-10 數據集以供使用:
```py
# extract data
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
#split train into train and validation sets
X_train, X_val, y_train, y_val = train_test_split(X_train,
y_train,
test_size=0.15,
stratify=np.array
(y_train),
random_state=42)
# perform one hot encoding
Y_train = np_utils.to_categorical(y_train, NUM_CLASSES)
Y_val = np_utils.to_categorical(y_val, NUM_CLASSES)
Y_test = np_utils.to_categorical(y_test, NUM_CLASSES)
# Scale up images to 48x48
X_train = np.array([sp.misc.imresize(x,
(48, 48)) for x in X_train])
X_val = np.array([sp.misc.imresize(x,
(48, 48)) for x in X_val])
X_test = np.array([sp.misc.imresize(x,
(48, 48)) for x in X_test])
```
前面的代碼片段不僅將訓練數據集拆分為訓練集和驗證集,還將目標變量轉換為單熱編碼形式。 我們還將圖像尺寸從`32 x 32`調整為`48 x 48`,以符合 VGG-16 輸入要求。 訓練,驗證和測試數據集準備就緒后,我們可以朝著準備分類器的方向努力。
以下代碼段顯示了我們如何輕松地在現有模型之上附加新層。 因為我們的目標是僅訓練分類層,所以通過將可訓練參數設置為`False`凍結其余層。 這使我們即使在功能較弱的基礎架構上也可以利用現有架構,并將學到的權重從一個域轉移到另一個域:
```py
base_model = vgg.VGG16(weights='imagenet',
include_top=False,
input_shape=(48, 48, 3))
# Extract the last layer from third block of vgg16 model
last = base_model.get_layer('block3_pool').output
# Add classification layers on top of it
x = GlobalAveragePooling2D()(last)
x= BatchNormalization()(x)
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)
x = Dropout(0.6)(x)
pred = Dense(NUM_CLASSES, activation='softmax')(x)
model = Model(base_model.input, pred)
for layer in base_model.layers:
layer.trainable = False
```
我們有基本的成分。 整個流水線中剩下的最后一塊是數據擴充。 整個數據集僅包含 60,000 張圖像; 數據擴充非常方便,可以為手頭的樣本集添加某些變化。 這些變體使網絡能夠學習比其他方法更通用的功能。 以下代碼段利用`ImageDataGenerator()`實用工具準備訓練和驗證增強對象:
```py
# prepare data augmentation configuration
train_datagen = ImageDataGenerator(rescale=1\. / 255,
horizontal_flip=False)
train_datagen.fit(X_train)
train_generator = train_datagen.flow(X_train,
Y_train,
batch_size=BATCH_SIZE)
val_datagen = ImageDataGenerator(rescale=1\. / 255,
horizontal_flip=False)
val_datagen.fit(X_val)
val_generator = val_datagen.flow(X_val,
Y_val,
batch_size=BATCH_SIZE)
```
現在讓我們訓練模型幾個周期并衡量其表現。 以下代碼段調用`fit_generator()`函數將新添加的層訓練到模型中:
```py
train_steps_per_epoch = X_train.shape[0] // BATCH_SIZE
val_steps_per_epoch = X_val.shape[0] // BATCH_SIZE
history = model.fit_generator(train_generator,
steps_per_epoch=train_steps_per_epoch,
validation_data=val_generator,
validation_steps=val_steps_per_epoch,
epochs=EPOCHS,
verbose=1)
```
`fit_generator()`返回的歷史對象包含有關每個周期的詳細信息。 我們利用這些來繪制模型在精度和損失方面的整體表現。 結果如下所示:

訓練驗證表現
如我們所見,與從頭開始開發的模型相比,遷移學習幫助我們在整體表現上實現了驚人的提升。 這項改進利用了訓練有素的 VGG-16 權重將學習到的特征轉移到該域。 讀者可以使用相同的工具`plot_predictions()`可視化隨機樣本上的分類結果,如以下屏幕截圖所示:

使用基于 VGG-16 的遷移學習構建的分類器的預測結果
神經網絡是相當復雜的學習機器,很難調試和優化。 盡管有許多可用的技術,但需要經驗來微調網絡。 在當前情況下,使用像 VGG-16 這樣的深層 CNN 可能對如此小尺寸的圖像來說是過大的殺傷力,但它顯示了巨大的潛力。 明智地使用它!
這是遷移學習的快速簡單的應用,其中我們利用了像 VGG-16 這樣令人驚訝的復雜深度 CNN 來準備 CIFAR-10 分類器。 鼓勵讀者不僅嘗試定制分類器的不同配置,而且嘗試甚至使用不同的預訓練網絡來理解所涉及的復雜性。
# 狗品種鑒定數據集
在上一節中,我們利用低分辨率圖像數據集將圖像分類為 10 個非重疊類別。 這絕非易事,但我們以最小的努力獲得了不錯的表現。
現在讓我們升級游戲,并使圖像分類的任務更加令人興奮。 在本節中,我們將專注于細粒度圖像分類的任務。 與常規圖像分類任務不同,細粒度圖像分類是指識別更高級別類別中不同子類別的任務。
為了更好地理解此任務,我們將圍繞[**斯坦福犬**數據集](http://vision.stanford.edu/aditya86/ImageNetDogs/)進行討論。 顧名思義,該數據集包含不同犬種的圖像。 在這種情況下,任務是識別每種犬種。 因此,高級概念是狗本身,而任務是正確分類不同的子概念或子類(在這種情況下為品種)。 該數據集包含來自 ImageNet 數據集的 20,000 個帶有標簽的圖像,該圖像集由 120 個不同的犬種組成。 為了便于討論,我們將利用 **Kaggle** 提供的數據集。 [該數據集位于以下鏈接中](https://www.kaggle.com/c/dog-breed-identification/data)。
讓我們開始構建狗分類器的任務。 但是,在實際模型之前,讓我們對數據集本身進行快速探索性分析,以更好地理解。
# 探索性分析
我們不能足夠強調理解底層數據集的重要性。 在當前情況下,我們正在處理一個視覺數據集,該數據集由 10,000 個樣本組成,分布在 120 個類別(狗的品種)中。 讀者可以在名為`dog_breed_eda.ipynb`的 IPython 筆記本中參考與探索性分析有關的所有步驟。
由于這是一個可視數據集,因此我們首先將數據集中的一些樣本可視化。 有多種方法可以在 Python 中提取和可視化圖像數據。 我們將依靠 SciPy 和與 matplotlib 相關的工具來做到這一點。 以下代碼片段導入所需的庫:
```py
In [1]: import os
...: import scipy as sp
...: import numpy as np
...: import pandas as pd
...:
...: import PIL
...: import scipy.ndimage as spi
...:
...: import matplotlib.pyplot as plt
...: import seaborn as sns
...:
...:np.random.seed(42)
```
由于數據集很大,因此我們準備了幾個工具來加載隨機的圖像批量并顯示選定的批量。 工具的標題為`load_batch()`和`plot_batch()`; 這些細節在 IPython 筆記本中可用。 以下代碼段繪制了隨機批次以供參考:
```py
In [7]:batch_df = load_batch(dataset_df,
...: batch_size=36)
In [8]:plot_batch(batch_df, grid_width=6, grid_height=6
...: ,im_scale_x=64, im_scale_y=64)
```
生成的輸出如下網格所示:

狗品種識別數據集的樣本圖像
從前面的網格中,我們可以看到在分辨率,照明,縮放級別等方面存在很多變化,并且圖像不僅包含一只狗,而且還包含其他狗和周圍環境。 項目。 我們還需要了解圖像尺寸的差異。 使用以下代碼段,我們生成了一個散點圖來理解它們:
```py
In [12]: plt.plot(file_dimension_list[:, 0],
file_dimension_list[:, 1], "ro")
...: plt.title("Image sizes")
...: plt.xlabel("width")
...: plt.ylabel("height")
```
生成的散點圖如下所示。 我們可以清楚地看到最大圖像數量在`500 x 500`尺寸之內,但是形狀確實有所不同:

圖像大小的散點圖
還需要檢查狗的品種分布,以了解我們正在處理什么。 由于我們具有標記的數據集,因此我們可以輕松地進行檢查。 以下代碼段使用`pandas`繪制品種分布:
```py
In [13]: fig = plt.figure(figsize = (12,5))
...:
...: ax1 = fig.add_subplot(1,2, 1)
...:dataset_df.breed.value_counts().tail().plot('bar',
...: ax=ax1,color='gray',
...: title="Breeds with Lowest Counts")
...:
...: ax2 = fig.add_subplot(1,2, 2)
...:dataset_df.breed.value_counts().head().plot('bar',
...: ax=ax2,color='black',
...: title="Breeds with Highest Counts")
```
數據集沒有被平均分割; 與其他品種相比,某些品種的樣本更多。 從下圖中的圖可以明顯看出:

最高和最低犬種樣本數
這樣的數據集需要徹底的探索。 我們已經在本節中介紹了一些探索性步驟。 進一步的步驟在引用的 IPython 筆記本中列出/執行。 鼓勵讀者逐步了解圖像大小調整的影響,不同層如何檢測不同特征,灰度等。
# 數據準備
探索性分析有助于我們更好地了解手頭的數據集。 下一個任務是為數據集構建一個實際的分類器。 眾所周知,對于任何分類問題,第一步都是將數據集分為訓練集和驗證集。 由于我們正在使用 Keras,因此我們將從其工具中獲取幫助以幫助準備我們的數據集。 以下代碼段展示了將原始數據集組織為訓練集和驗證集的過程:
```py
# Prepare column to store image path
data_labels['image_path'] = data_labels.apply(
lambda row: (train_folder +
row["id"] + ".jpg" ),
axis=1)
# load image data as arrays of defined size
train_data = np.array([img_to_array(load_img(img, target_size=(299,
299)))
for img in data_labels['image_path'].values.tolist()
]).astype('float32')
# split data into train and test
x_train, x_test, y_train, y_test = train_test_split(train_data,
target_labels,
test_size=0.3,
stratify=np.array(target_labels),
random_state=42)
# split train dataset into train and validation sets
x_train, x_val, y_train, y_val = train_test_split(x_train,
y_train,
test_size=0.15,
stratify=
np.array(y_train),
random_state=42)
```
前面顯示的第一步是準備標簽`dataframe`中的派生列以保存實際圖像路徑。 然后,我們繼續簡單地將數據集分為訓練,驗證和測試數據集。 下一步是在將標簽輸入模型之前,將標簽快速轉換為一次性編碼形式。 以下代碼段準備了目標變量的一鍵編碼形式:
```py
y_train_ohe = pd.get_dummies(y_train.reset_index(
drop=True)
).as_matrix()
y_val_ohe = pd.get_dummies(y_val.reset_index(
drop=True)
).as_matrix()
y_test_ohe = pd.get_dummies(y_test.reset_index(
drop=True)
).as_matrix()
```
眾所周知,深度學習算法需要大量數據。 在這種情況下,即使我們總共有 10,000 張圖像,每個類別的計數也不是很大。 為了對此進行改進,我們執行增強。 簡單來說,**數據增強**是利用策展的數據集通過生成現有數據點的變體來擴大自身的過程。 在這種情況下,我們利用`keras`中的`ImageDataGenerator`來擴充訓練和驗證數據集,如以下代碼片段所示:
```py
# Create train generator.
train_datagen = ImageDataGenerator(rescale=1./255,
rotation_range=30,
width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip = 'true')
train_generator = train_datagen.flow(x_train,
y_train_ohe,
shuffle=False,
batch_size=BATCH_SIZE,
seed=1)
# Prepare Validation data augmentation
val_datagen = ImageDataGenerator(rescale = 1./255)
val_generator = train_datagen.flow(x_val,
y_val_ohe,
shuffle=False,
batch_size=BATCH_SIZE,
seed=1)
```
現在我們已經準備好數據,下一步是準備實際的分類器。
# 使用遷移學習的狗分類器
現在我們的數據集已經準備好,讓我們開始建模過程。 我們已經知道如何從頭開始構建深度的卷積網絡。 我們也了解達到良好表現所需的微調數量。 對于此任務,我們將利用遷移學習的概念。
預訓練模型是開始進行遷移學習任務所需的基本特征。 如前幾章所述,可以通過在當前任務上微調預訓練網絡的權重,或將預訓練模型用作特征提取器,來利用遷移學習。
在這種用例中,我們將集中精力利用預訓練的模型作為特征提取器。 眾所周知,深度學習模型基本上是神經元相互連接的層的堆疊,最后一層充當分類器。 這種架構使深度神經網絡能夠捕獲網絡中不同級別的不同特征。 因此,我們可以利用此屬性將它們用作特征提取器。 通過刪除最后一層或使用倒數第二層的輸出,可以做到這一點。 然后,將倒數第二層的輸出饋送到其他一組層,然后是分類層。 以下代碼段展示了基于 **InceptionV3** 預訓練模型的特征提取,并堆疊了其他層以準備分類器:
```py
# Get the InceptionV3 model so we can do transfer learning
base_inception = InceptionV3(weights='imagenet',
include_top = False,
input_shape=(299, 299, 3))
# Add a global spatial average pooling layer
out = base_inception.output
out = GlobalAveragePooling2D()(out)
out = Dense(512, activation='relu')(out)
out = Dense(512, activation='relu')(out)
total_classes = y_train_ohe.shape[1]
predictions = Dense(total_classes,
activation='softmax')(out)
```
如前面的代碼片段所示, **Keras** 提供了用于處理許多預訓練模型的簡單工具,將它們用作特征提取器就像將標志`include_top`設置為`False`一樣簡單。 在下面的代碼片段中,我們通過將兩組層堆疊在一起,然后凍結 InceptionV3 中的層來準備最終模型:
```py
model = Model(inputs=base_inception.input,
outputs=predictions)
# only if we want to freeze layers
for layer in base_inception.layers:
layer.trainable = False
```
現在,我們有了模型,所有模型都將在“狗品種識別”數據集中進行訓練。 我們使用`fit_generator()`方法訓練模型,以利用上一步中準備的數據增強。 我們將批次大小設置為 32,并訓練模型 13 個周期。 以下代碼片段設定了滾動的方向:
```py
batch_size = BATCH_SIZE
train_steps_per_epoch = x_train.shape[0] // batch_size
val_steps_per_epoch = x_val.shape[0] // batch_size
history = model.fit_generator(train_generator,
steps_per_epoch=train_steps_per_epoch,
validation_data=val_generator,
validation_steps=val_steps_per_epoch,
epochs=15,
verbose=1)
```
由于我們在每個周期(`history`對象)之后都保存了模型參數和表現的輸出,因此我們現在將利用它來了解模型表現。 下圖繪制了模型的訓練和測試精度以及其損失表現:

狗品種分類器表現
該模型在訓練集和驗證集上僅在 15 個周期內就獲得了 **80%** 精度以上的可嘉表現。 右側的圖顯示了損耗下降并收斂到 **0.5** 的速度。 這是一個很好的例子,說明了遷移學習的強大而簡單。
訓練和驗證的表現相當不錯,但是對看不見的數據的表現如何? 由于我們已經將原始數據集分為三個單獨的部分。 這里要記住的重要一點是,測試數據集必須經過與訓練數據集相似的預處理。 為了解決這個問題,在將測試數據集輸入到函數之前,我們還對它進行了縮放。
該模型在測試數據集上實現了驚人的 **85% 準確率**以及 **0.85 F1 得分**。 鑒于我們僅用最少的投入就訓練了 15 個周期,遷移學習幫助我們實現了一個不錯的分類器:

狗的品種分類器預測
上圖顯示了模型表現的視覺證明。 正如我們所看到的,在大多數情況下,該模型不僅可以預測正確的犬種,而且還可以非常有把握地進行預測。
# 總結
在本書的前兩個部分中,我們討論了很多理論。 建立了強大的概念和技術基礎后,我們在本章中開始了用例驅動的旅程。 本章是一系列后續章節中的第一章,這些章節將展示不同場景和領域中遷移學習的實際用例。 在本章中,我們將遷移學習應用于視覺對象識別或俗稱**圖像分類**的領域。
我們從圍繞 CNN 的快速更新開始,并隨著 2012 年深度學習模型的出現,計算機輔助對象識別的整個過程將一勞永逸。我們簡要介紹了各種最新的圖像分類模型 ,它已經超越了人類的表現。 我們還快速瀏覽了學術界和行業專家用于訓練和調整模型的不同基準數據集。 設置上下文后,我們從 CIFAR-10 數據集開始。 我們使用 Keras 和 TensorFlow 作為后端從頭開始構建了一個分類器。 我們利用 VGG-16 作為特征提取的預訓練模型,利用遷移學習來改善此表現。
在本章的最后部分,我們利用遷移學習來解決稍微復雜的問題。 我們準備了一個犬種分類器,而不是基于類別不重疊的數據集(CIFAR-10),以基于 Stanford Dogs 數據集識別 120 種不同的犬種。 只需幾行代碼,我們就可以實現近乎最新的表現。 第二種用例也稱為*細粒度圖像分類*任務,并且比通常的圖像分類任務復雜。 在本章中,我們展示了通過遷移學習獲得驚人結果的強大功能和簡便性。 在接下來的章節中,請繼續關注來自計算機視覺,音頻分析等領域的驚人用例。
- TensorFlow 1.x 深度學習秘籍
- 零、前言
- 一、TensorFlow 簡介
- 二、回歸
- 三、神經網絡:感知器
- 四、卷積神經網絡
- 五、高級卷積神經網絡
- 六、循環神經網絡
- 七、無監督學習
- 八、自編碼器
- 九、強化學習
- 十、移動計算
- 十一、生成模型和 CapsNet
- 十二、分布式 TensorFlow 和云深度學習
- 十三、AutoML 和學習如何學習(元學習)
- 十四、TensorFlow 處理單元
- 使用 TensorFlow 構建機器學習項目中文版
- 一、探索和轉換數據
- 二、聚類
- 三、線性回歸
- 四、邏輯回歸
- 五、簡單的前饋神經網絡
- 六、卷積神經網絡
- 七、循環神經網絡和 LSTM
- 八、深度神經網絡
- 九、大規模運行模型 -- GPU 和服務
- 十、庫安裝和其他提示
- TensorFlow 深度學習中文第二版
- 一、人工神經網絡
- 二、TensorFlow v1.6 的新功能是什么?
- 三、實現前饋神經網絡
- 四、CNN 實戰
- 五、使用 TensorFlow 實現自編碼器
- 六、RNN 和梯度消失或爆炸問題
- 七、TensorFlow GPU 配置
- 八、TFLearn
- 九、使用協同過濾的電影推薦
- 十、OpenAI Gym
- TensorFlow 深度學習實戰指南中文版
- 一、入門
- 二、深度神經網絡
- 三、卷積神經網絡
- 四、循環神經網絡介紹
- 五、總結
- 精通 TensorFlow 1.x
- 一、TensorFlow 101
- 二、TensorFlow 的高級庫
- 三、Keras 101
- 四、TensorFlow 中的經典機器學習
- 五、TensorFlow 和 Keras 中的神經網絡和 MLP
- 六、TensorFlow 和 Keras 中的 RNN
- 七、TensorFlow 和 Keras 中的用于時間序列數據的 RNN
- 八、TensorFlow 和 Keras 中的用于文本數據的 RNN
- 九、TensorFlow 和 Keras 中的 CNN
- 十、TensorFlow 和 Keras 中的自編碼器
- 十一、TF 服務:生產中的 TensorFlow 模型
- 十二、遷移學習和預訓練模型
- 十三、深度強化學習
- 十四、生成對抗網絡
- 十五、TensorFlow 集群的分布式模型
- 十六、移動和嵌入式平臺上的 TensorFlow 模型
- 十七、R 中的 TensorFlow 和 Keras
- 十八、調試 TensorFlow 模型
- 十九、張量處理單元
- TensorFlow 機器學習秘籍中文第二版
- 一、TensorFlow 入門
- 二、TensorFlow 的方式
- 三、線性回歸
- 四、支持向量機
- 五、最近鄰方法
- 六、神經網絡
- 七、自然語言處理
- 八、卷積神經網絡
- 九、循環神經網絡
- 十、將 TensorFlow 投入生產
- 十一、更多 TensorFlow
- 與 TensorFlow 的初次接觸
- 前言
- 1.?TensorFlow 基礎知識
- 2. TensorFlow 中的線性回歸
- 3. TensorFlow 中的聚類
- 4. TensorFlow 中的單層神經網絡
- 5. TensorFlow 中的多層神經網絡
- 6. 并行
- 后記
- TensorFlow 學習指南
- 一、基礎
- 二、線性模型
- 三、學習
- 四、分布式
- TensorFlow Rager 教程
- 一、如何使用 TensorFlow Eager 構建簡單的神經網絡
- 二、在 Eager 模式中使用指標
- 三、如何保存和恢復訓練模型
- 四、文本序列到 TFRecords
- 五、如何將原始圖片數據轉換為 TFRecords
- 六、如何使用 TensorFlow Eager 從 TFRecords 批量讀取數據
- 七、使用 TensorFlow Eager 構建用于情感識別的卷積神經網絡(CNN)
- 八、用于 TensorFlow Eager 序列分類的動態循壞神經網絡
- 九、用于 TensorFlow Eager 時間序列回歸的遞歸神經網絡
- TensorFlow 高效編程
- 圖嵌入綜述:問題,技術與應用
- 一、引言
- 三、圖嵌入的問題設定
- 四、圖嵌入技術
- 基于邊重構的優化問題
- 應用
- 基于深度學習的推薦系統:綜述和新視角
- 引言
- 基于深度學習的推薦:最先進的技術
- 基于卷積神經網絡的推薦
- 關于卷積神經網絡我們理解了什么
- 第1章概論
- 第2章多層網絡
- 2.1.4生成對抗網絡
- 2.2.1最近ConvNets演變中的關鍵架構
- 2.2.2走向ConvNet不變性
- 2.3時空卷積網絡
- 第3章了解ConvNets構建塊
- 3.2整改
- 3.3規范化
- 3.4匯集
- 第四章現狀
- 4.2打開問題
- 參考
- 機器學習超級復習筆記
- Python 遷移學習實用指南
- 零、前言
- 一、機器學習基礎
- 二、深度學習基礎
- 三、了解深度學習架構
- 四、遷移學習基礎
- 五、釋放遷移學習的力量
- 六、圖像識別與分類
- 七、文本文件分類
- 八、音頻事件識別與分類
- 九、DeepDream
- 十、自動圖像字幕生成器
- 十一、圖像著色
- 面向計算機視覺的深度學習
- 零、前言
- 一、入門
- 二、圖像分類
- 三、圖像檢索
- 四、對象檢測
- 五、語義分割
- 六、相似性學習
- 七、圖像字幕
- 八、生成模型
- 九、視頻分類
- 十、部署
- 深度學習快速參考
- 零、前言
- 一、深度學習的基礎
- 二、使用深度學習解決回歸問題
- 三、使用 TensorBoard 監控網絡訓練
- 四、使用深度學習解決二分類問題
- 五、使用 Keras 解決多分類問題
- 六、超參數優化
- 七、從頭開始訓練 CNN
- 八、將預訓練的 CNN 用于遷移學習
- 九、從頭開始訓練 RNN
- 十、使用詞嵌入從頭開始訓練 LSTM
- 十一、訓練 Seq2Seq 模型
- 十二、深度強化學習
- 十三、生成對抗網絡
- TensorFlow 2.0 快速入門指南
- 零、前言
- 第 1 部分:TensorFlow 2.00 Alpha 簡介
- 一、TensorFlow 2 簡介
- 二、Keras:TensorFlow 2 的高級 API
- 三、TensorFlow 2 和 ANN 技術
- 第 2 部分:TensorFlow 2.00 Alpha 中的監督和無監督學習
- 四、TensorFlow 2 和監督機器學習
- 五、TensorFlow 2 和無監督學習
- 第 3 部分:TensorFlow 2.00 Alpha 的神經網絡應用
- 六、使用 TensorFlow 2 識別圖像
- 七、TensorFlow 2 和神經風格遷移
- 八、TensorFlow 2 和循環神經網絡
- 九、TensorFlow 估計器和 TensorFlow HUB
- 十、從 tf1.12 轉換為 tf2
- TensorFlow 入門
- 零、前言
- 一、TensorFlow 基本概念
- 二、TensorFlow 數學運算
- 三、機器學習入門
- 四、神經網絡簡介
- 五、深度學習
- 六、TensorFlow GPU 編程和服務
- TensorFlow 卷積神經網絡實用指南
- 零、前言
- 一、TensorFlow 的設置和介紹
- 二、深度學習和卷積神經網絡
- 三、TensorFlow 中的圖像分類
- 四、目標檢測與分割
- 五、VGG,Inception,ResNet 和 MobileNets
- 六、自編碼器,變分自編碼器和生成對抗網絡
- 七、遷移學習
- 八、機器學習最佳實踐和故障排除
- 九、大規模訓練
- 十、參考文獻