在R中使用TensorFlow構建一個用於圖像分類的卷積神經網絡

在本章中,我們將介紹以下主題:

  • 下載並配置圖像數據集;
  • 學習CNN分類器的架構;
  • 使用函數初始化權重和偏差;
  • 使用函數創建一個新的卷積層;
  • 使用函數扁平化密集連接層;
  • 定義佔位符變量;
  • 創建第一個卷積層;
  • 創建第二個卷積層;
  • 扁平化第二個卷積層;
  • 創建第一個完全連接的層;
  • 將dropout應用於第一個完全連接層;
  • 創建第二個帶有dropout的完全連接層;
  • 應用Softmax激活以獲得預測類;
  • 定義用於優化的成本函數;
  • 執行梯度下降成本優化;
  • 在TensorFlow會話中執行圖;
  • 評估測試數據的性能。

3.1 介紹

卷積神經網絡(Convolution Neural Network,CNN)是一類深度學習神經網絡,在建立基於圖像識別和自然語言處理的分類模型方面發揮著重要作用。

 CNN遵循類似於LeNet的架構(LeNet主要用於識別數字、郵政編碼等字符)。和人工神經網絡相比,CNN有以三維空間(寬度、深度和高度)排列的神經元層。每層將二維圖像轉換成三維輸入體積,然後使用神經元激活函數將其轉換為三維輸出體積。

從根本上,CNN是使用3種主要激活層類型構建的:卷積層ReLU、池化層和完全連接層。卷積層用於從(圖像的)輸入向量中提取特徵(像素之間的空間關係),並在帶有權重(和偏差)的點積運算後將它們存儲以供進一步處理。

然後,在卷積之後,在操作中應用ReLU以引入非線性。

這是應用於每個卷積特徵映射的逐個元素操作(例如閾值函數、Sigmoid和tanh)。然後,池化層(諸如求最大值、求均值和求總和之類的操作)是用來降低每個特徵映射的維度,以確保信息損失最小。這種減小空間大小的操作被用於控制過度擬合,並增加網絡對小的失真或變換的魯棒性。然後將池化層的輸出連接到傳統的多層感知器(也稱為完全連接層)。該感知器使用例如Softmax或SVM的激活函數來建立基於分類器的CNN模型。

本章將著重於在R中使用TensorFlow構建一個用於圖像分類的卷積神經網絡。雖然本章將為你提供一個典型的CNN概覽,但是我們鼓勵你根據自己的需要調整並修改參數。

3.2 下載並配置圖像數據集

在本章中,我們將使用CIFAR-10數據集來構建用於圖像分類的卷積神經網絡。CIFAR-10數據集由60,000個32×32彩色的10個種類的圖像組成,每個種類有6,000個圖像。這些進一步被分為5個訓練批次和1個測試批次,每個批次有10,000個圖像。

測試批次剛好包含1,000個從每個種類隨機選擇的圖像。訓練批次包含隨機順序的剩餘圖像,但是某些訓練批次可能包含來自一個類的圖像多餘另一個類的圖像。在它們之間,訓練批次剛好包含5,000個來自每個種類的圖像。10個結果類為飛機、汽車、鳥、貓、鹿、狗、青蛙、馬、船和卡車。這些種類是完全互斥的。另外,數據集的格式如下。

  • 第一列,10個類的標籤:飛機、汽車、鳥、貓、鹿、狗、青蛙、馬、船和卡車。
  • 接下來的1024列:範圍在0~255的紅色像素。
  • 接下來的1024列:範圍在0~255的綠色像素。
  • 接下來的1024列:範圍在0~255的藍色像素。

3.2.1 做好準備

首先,你需要在R中安裝一些軟件包,比如data.table和imager。

3.2.2 怎麼做

1.啟動R(使用Rstudio或Docker)並加載所需的軟件包。

2.從http://www.cs.toronto.edu/~kriz/cifar.html手動下載數據集(二進制版本)或在R環境中使用以下函數下載數據。該函數將工作目錄或下載的數據集的位置路徑作為輸入參數(data_dir):

<code># 下載二進制文件的函數
download.cifar.data dir.create(data_dir, showWarnings = FALSE)
setwd(data_dir)
if (!file.exists('cifar-10-binary.tar.gz')){
download.file(url='http://www.cs.toronto.edu/~kriz/cifar-10-binary.
tar.gz', destfile='cifar-10-binary.tar.gz', method='wget')
untar("cifar-10-binary.tar.gz") # 解壓縮文件
file.remove("cifar-10-binary.tar.gz") # 刪除壓縮文件
}
setwd("..")
}
# 下載數據
download.cifar.data(data_dir="Cifar_10/")/<code>

3.一旦下載並解壓數據集,就在R環境中讀取數據集作為訓練和測試數據集。該函數將訓練和測試批數據集的文件名(filenames)以及每批文件檢索的圖像數(num.images)作為輸入參數。

<code>#讀取cifar數據的函數 
read.cifar.data images.rgb images.lab for (f in 1:length(filenames)) {
to.read for(i in 1:num.images) {
l r endian="big"))
g endian="big"))
b endian="big"))
index images.rgb[[index]] = data.frame(r, g, b)
images.lab[[index]] = l+1
}
close(to.read)
cat("completed :", filenames[f], "\\n")
remove(l,r,g,b,f,i,index, to.read)
}
return(list("images.rgb"=images.rgb,"images.lab"=images.lab))
}
# 訓練數據集
cifar_train c("data_batch_1.bin","data_batch_2.bin","data_batch_3.bin","data_ba
tch_4.bin", "data_batch_5.bin"))
images.rgb.train images.lab.train rm(cifar_train)
# 測試數據集
cifar_test images.rgb.test images.lab.test rm(cifar_test)/<code>

4.之前函數的結果是每張圖及其標籤的紅色、綠色和藍色像素數據框列表。然後,使用以下函數將數據扁平化為兩個數據框列表(一個用於輸入,另一個用於輸出)。該函數有兩個參數:輸入變量列表(x_listdata)和輸出變量列表(y_listdata)。

<code># 扁平化數據的函數
flat_data # 扁平化輸入變量x
x_listdata x_listdata # 扁平化輸出變量y
y_listdata return(a)})
y_listdata # 返回扁平化的x和y變量
return(list("images"=x_listdata, "labels"=y_listdata))
}
# 生成扁平化的訓練和測試數據集
train_data images.lab.train)

test_data images.lab.test)/<code>

5.一旦輸入和輸出列表以及訓練和測試數據框列表準備就緒,就通過繪製具有標籤的圖像來執行完整性檢查。該函數需要兩個必需的參數(index,圖像的行編號;images.rgb,扁平化的輸入數據集)和一個可選參數(images.lab,扁平化的輸出數據集)。

<code>labels # 對照片和標籤輸入執行完整性檢查的函數
drawImage require(imager)
# 測試解析:將每個顏色層轉換為矩陣
# 組合成一個rgb對象,並展示為一張圖
img img.r.mat img.g.mat img.b.mat img.col.mat # 將三個通道綁定到一張圖
# 提取標籤
if(!is.null(images.lab)){
lab = labels[[1]][images.lab[[index]]]
}
# 繪圖並輸出標籤
plot(img.col.mat,main=paste0(lab,":32x32 size",sep=" "),xaxt="n")
axis(side=1, xaxp=c(10, 50, 4), las=1)
return(list("Image label" =lab,"Image description" =img.col.mat))
}
#從訓練數據集中,隨機繪製一張帶標籤和描述的圖像
drawImage(sample(1:50000, size=1), images.rgb.train,
images.lab.train)/<code>

6.現在使用最小-最大標準化(Min-Max Standardization)技術來轉換輸入數據。包中的preProcess函數可用於歸一化。該方法的“range”選項執行最小-最大歸一化(Min-Max Normalization),如下所示:

<code># 歸一化數據的函數 

Require(caret)
normalizeObjtrain_data$imagestest_data$images /<code>

3.2.3 工作原理

我們來看看在上一小節中做了什麼。在3.2.2小節的步驟2中,我們從提到的鏈接中下載了CIFAR-10數據集,以防其不存在於給定的鏈接或工作目錄中。在步驟3中,將解壓縮的文件作為訓練和測試數據集加載到R環境中。訓練數據集有一個50,000張圖像的列表,測試數據集有一個10,000張帶標籤的圖像列表。然後,在步驟4中,訓練和測試數據集被扁平化為兩個數據框列表:一個長度為3,072(紅色1,024、綠色1,024、藍色1,024)的輸入變量(或圖像),一個長度為10(每個類的二進制)的輸出變量(或標籤)。在步驟5中,我們通過生成圖對創建的訓練和測試數據集進行完整性檢查。圖3-1(CIFAR-10數據集中的類別示列)顯示了一組6個訓練圖像及其標籤。最後,在步驟6中,使用最小-最大標準化技術來轉換輸入數據。

在R中使用TensorFlow構建一個用於圖像分類的卷積神經網絡

圖3-1

3.3 學習CNN分類器的架構

本節介紹的CNN分類器有兩個卷積層,最後兩個為完全連接層,其中最後一層使用Softmax激活函數作為分類器。

3.3.1 做好準備

首先我們需要CIFAR-10數據集。因此,應該下載CIFAR-10數據集,並將其加載到R環境中。此外,圖像的大小為32×32像素。

3.3.2 怎麼做

我們來定義CNN分類器的配置,如下所示。

1.每個輸入圖像(CIFAR-10)的大小為32×32像素,可以標記為10個類別之一:

<code># CIFAR圖像為32×32像素
img_width = 32L
img_height = 32L

# 使用圖像高度和寬度的元組重新生成數組
img_shape = c(img_width, img_height)
# 類數量,每10個圖像為一個類別
num_classes = 10L/<code>

2.CIFAR-10數據集的圖像有3個通道(紅色,綠色和藍色):

<code># 圖像顏色通道的數量:紅色、藍色和綠色3個通道 

num_channels = 3L/<code>

3.圖像存儲在以下長度(img_size_flat)的一維數組中:

<code># 圖像存儲在一維數組中的長度
img_size_flat = img_width * img_height * num_channels/<code>

4.在第一個卷積層中,卷積濾波器的大小(filter_size1)(寬×高)為5×5像素,卷積濾波器的深度(或數量,num_filters1)為64:

<code># 卷積層1
filter_size1 = 5L
num_filters1 = 64L/<code>

5.在第二卷積層中,卷積濾波器的大小和深度與第一卷積層相同:

<code># 卷積層2
filter_size2 = 5L
num_filters2 = 64L/<code>

6.類似地,第一完全連接層的輸出與第二完全連接層的輸入相同:

<code># 完全連接層
fc_size = 1024L/<code>

3.3.3 工作原理

輸入圖像的尺寸和特徵分別顯示在3.3.2小節的步驟1和步驟2中。如3.3.2節中的步驟4和步驟5所定義的,每個輸入圖像在卷積層中使用一組濾波器進一步處理。第一個卷積層產生一組64張圖像(每組濾波器一個)。 此外,這些圖像的分辨率也減少到了一半(由於2×2最大池),即從32×32像素減少到16×16像素。

第二個卷積層將輸入這64張圖像,並提供進一步降低分辨率的新 64張圖像的輸出。更新後的分辨率現在是8×8像素(同樣是由於2×2的最大池)。在第二卷積層中,總共創建了64×64=4,096個濾波器,然後將其進一步卷積成64個輸出圖像(或通道)。請記住,這64張8×8分辨率的圖像對應單個輸入圖像。

進一步,如3.3.2小節中的步驟3所定義的,這些64張8×8像素的輸出圖像被扁平化為長度為4,096(8×8×64)的單向量,並被用作3.3.2小節的步驟6中所定義的給定的一組神經元的完全連接層的輸入。然後將4,096個元素的向量反饋到1,024個神經元的第一完全連接層。輸出神經元再次被反饋到10個神經元的第二完全連接層(等於num_classes)。這10個神經元代表每個類別標籤,然後用於確定圖像的最終類別。

首先,卷積和完全連接的層的權重被隨機地進行初始化,直到分類階段(CNN圖的結尾)。此處,根據真實類別和預測類別(也稱為交叉熵)來計算分類錯誤。

然後,優化器使用微分鏈式法則在卷積網絡反向傳播誤差,之後更新層(或濾波器)的權重,使誤差最小化。一個向前和向後傳播的整個循環被稱為一次迭代。執行數千次這樣的迭代直到分類錯誤被降低到足夠低的值。

 通常,使用一批圖像而不是單個圖像來執行這些迭代,以提高計算的效率。

圖3-2描繪了本章設計的卷積網絡。

在R中使用TensorFlow構建一個用於圖像分類的卷積神經網絡

圖3-2

3.4 使用函數初始化權重和偏差

權重和偏差是任何深度神經網絡優化必不可少的組成部分,此處我們定義一些函數來自動執行這些初始化。以小噪聲初始化權重來打破對稱性並防止零梯度是很好的做法。此外,小的初始化正偏差將避免神經元失活,適合於ReLU激活神經元。

3.4.1 做好準備

權重和偏差是在模型編譯之前需要初始化的模型係數。此步驟要求根據輸入數據集確定shape參數。

3.4.2 怎麼做

1.以下函數用於隨機返回初始化權重:

<code># 權重初始化
weight_variable initial tf$Variable(initial)
}/<code>

2.以下函數用於返回常量偏差:

<code>bias_variable initial tf$Variable(initial)
}/<code>

3.4.3 工作原理

這些函數返回TensorFlow變量,稍後變量被用作TensorFlow圖形的一部分。shape被定義為在卷積層中規定過濾器的屬性列表,在下一節中將會介紹。權重隨機初始化,標準偏差等於0.1,且偏差初始化為定值0.1。

3.5 使用函數創建一個新的卷積層

創建卷積層是CNN TensorFlow計算圖中的主要步驟。該函數主要用於定義TensorFlow圖形中的數學公式,之後在優化過程中用於實際計算。

3.5.1 做好準備

定義並加載輸入數據集。本節中出現的create_conv_layer函數有以下5個輸入參數,並需要在配置卷積層時定義。

1.input:這是四維張量(或者列表),包括多個(輸入)圖像、每張圖的高度(此處為32L)、每張圖的寬度(此處為32L)以及每張圖通道的數量(此處為3L:紅色、藍色和綠色)。

2.num_input_channels:這被定義為在第一卷積層的情況下的顏色通道的數量或在隨後的卷積層的情況下的過濾器通道的數量。

3.filter_size:這被定義為卷積層中每個過濾器的寬度和高度。此處,假定過濾器為正方形。

4.num_filters:這被定義為給定卷積層中過濾器的數量。

5.use_pooling:這是一個二進制變量,用於執行2×2最大池化。

3.5.2 怎麼做

1.執行以下函數以創建一個新的卷積層:

<code># 創建一個新的卷積層
create_conv_layer num_input_channels,
filter_size,
num_filters,
use_pooling=True)
{
# 卷積過濾器權重的形狀
shape1 = shape(filter_size, filter_size, num_input_channels,
num_filters)
# 創建新的權重
weights = weight_variable(shape=shape1)
# 創建新的偏差
biases = bias_variable(shape=shape(num_filters))
# 為卷積創建TensorFlow操作
layer = tf$nn$conv2d(input=input,
filter=weights,
strides=shape(1L, 1L, 1L ,1L),
padding="SAME")
# 將偏差添加到卷積的結果中
layer = layer + biases
# 使用池化(二進制標誌)來減少圖像分辨率
if(use_pooling){
layer = tf$nn$max_pool(value=layer,
ksize=shape(1L, 2L, 2L, 1L),
strides=shape(1L, 2L, 2L, 1L),
padding='SAME')
}
# 使用ReLU添加非線性
layer = tf$nn$relu(layer)
# 返回結果層和更新的權重
return(list("layer" = layer, "weights" = weights))
}/<code>

2.運行以下函數以生成卷積層圖:

<code>drawImage_conv images.lab=NULL,par_imgs=8) { 

require(imager)
img n_images par(mfrow=c(par_imgs,par_imgs), oma=c(0,0,0,0),
mai=c(0.05,0.05,0.05,0.05),ann=FALSE,ask=FALSE)
for(i in 1:n_images){
img.bwmat # 提取標籤
if(!is.null(images.lab)){
lab = labels[[1]][images.lab[[index]]]
}
# 繪圖並輸出標籤
plot(img.bwmat,axes=FALSE,ann=FALSE)
}
par(mfrow=c(1,1))
}/<code>

3.運行以下函數以生成卷積層權重圖:

<code>drawImage_conv_weights require(imager)
n_images par(mfrow=c(par_imgs,par_imgs), oma=c(0,0,0,0),
mai=c(0.05,0.05,0.05,0.05),ann=FALSE,ask=FALSE)
for(i in 1:n_images){
img.r.mat img.g.mat img.b.mat img.col.mat # 將3個通道綁定到一個圖像中
# 繪圖並輸出標籤
plot(img.col.mat,axes=FALSE,ann=FALSE)
}
par(mfrow=c(1,1))
}/<code>

3.5.3 工作原理

函數從創建形狀張量開始,即過濾器的寬度、過濾器的高度、輸入通道的數量和給定過濾器的數量這4個整數的列表。使用這種形狀張量,用所定義的形狀初始化一個新的權重張量,併為每個過濾器創建一個新的(常數)偏差。

一旦需要的權重和偏差被初始化,就使用tf$nn$conv2d函數為卷積創建一個TensorFlow操作。 在我們當前的配置中,所有4個維度的步長都設置為1,並且邊距設置為相同(SAME)。第一個和最後一個默認設置為1,但中間的兩個可以考慮更高的步長。步長是我們允許過濾器矩陣在輸入(圖像)矩陣上滑動的像素數量。

步長為3,將意味著每個過濾器片在x或y軸上有3個像素跳躍。較小的步長會產生較大的特徵映射,因此需要較高的收斂計算。當內邊距設置為SAME時,輸入(圖像)矩陣在邊框周圍填充零,以便我們可以將過濾器應用於輸入矩陣的邊框元素。使用此特徵,我們可以控制輸出矩陣(或特徵映射)的大小與輸入矩陣相同。

在卷積中,為每個跟隨著池化的過濾器通道添加偏差數值,以防止過度擬合。在當前設置中,執行2×2最大池化(使用tf$nn$max_pool)來縮小圖像分辨率。此處,我們考慮2×2(ksize)大小的窗口並選擇每個窗口中的最大值。這些窗口在x或y方向上跨兩個像素(步長)。

池化時,我們使用ReLU激活函數(tf$nn$relu)為層添加非線性。在ReLU中,在過濾器中觸發每個像素,並且使用max(x,0)函數將所有負像素值替換為零,其中x是像素值。通常,在池化之前執行ReLU激活。但是,由於我們使用的是最大池化(Max-Pooling),因此它不一定會像這樣影響結果,因為relu(max_pool(x))等同於max_pool(relu(x))。因此,通過在池化之後應用ReLU,我們可以節省大量的ReLU操作(~75%)。

最後,該函數返回一個卷積層及其相應權重的列表。卷積層是具有以下屬性的4維張量:

  • (輸入)圖像的數量,同輸入(input)一樣;
  • 每張圖的高度(在2×2最大池化的情況下減少到一半);
  • 每張圖像的寬度(在2×2最大池化的情況下減少到一半);
  • 產生的通道數量,每個卷積過濾器一個。

3.6 使用函數創建一個扁平化的卷積層

新創建卷積層的四維結果被扁平化為二維層,以便它可以用作完全連接的多層感知器的輸入。

3.6.1 做好準備

本小節解釋如何在構建深度學習模型之前將卷積層扁平化。給定函數(flatten_conv_layer)的輸入基於前一層定義的4維卷積層。

3.6.2 怎麼做

運行以下函數以扁平化卷積層:

<code>flatten_conv_layer #提取輸入層的形狀
layer_shape = layer$get_shape()
#計算特徵的數量,如 img_height * img_width *
num_channels
num_features =

prod(c(layer_shape$as_list()[[2]],layer_shape$as_list()[[3]],layer_
shape$as_list()[[4]]))
# 將層重塑為 [num_images, num_features]
layer_flat = tf$reshape(layer, shape(-1, num_features))
#返回扁平化的層和特徵的數量
return(list("layer_flat"=layer_flat, "num_features"=num_features))
}/<code>

3.6.3 工作原理

該函數從提取給定輸入層的形狀開始。如前面的章節中所述,輸入層的形狀由4個整數組成:圖像編號,圖像高度,圖像寬度和圖像中顏色通道的數量。然後使用圖像高度、圖像權重和顏色通道數量的點積來評估特徵的數量(num_features)。

接著,將該層被扁平化或重塑為二維張量(使用tf$reshape):第一個維度設置為-1(等於圖像總數),第二個維度是特徵的數量。

最後,該函數返回一個扁平化的層列表以及特徵(輸入)總數量。

3.7 使用函數扁平化密集連接層

CNN通常以在輸出層中使用Softmax激活的完全連接的多層感知器結束。此處,前一個卷積扁平化層中的每個神經元連接到下一個層(完全連接的)中的每個神經元。

 完全卷積層的關鍵目的是使用卷積和池化階段生成的特徵將給定的輸入圖像分類為各種結果類別(此處為10L)。它還有助於學習這些特徵的非線性組合來定義結果類別。

在本章中,我們使用兩個完全連接層進行優化。該函數主要用於定義TensorFlow圖形中的數學公式,稍後在優化過程中用於實際計算。

3.7.1 做好準備

create_fc_layer函數有4個輸入參數,如下所示。

  • input:與新的卷積層函數的輸入類似。
  • num_inputs:扁平化卷積層後生成的輸入特徵的數量。
  • num_outputs:與輸入神經元完全連接的輸出神經元的數量。
  • use_relu:只有在最終完全連接層的情況下,才採用設置為錯誤(FALSE)的二進制標誌。

3.7.2 怎麼做

運行以下函數以創建一個新的完全連接層:

<code># 創建一個新的完全連接層
create_fc_layer num_inputs,
num_outputs,
use_relu=True)
{
# 創建新的權重和偏差
weights = weight_variable(shape=shape(num_inputs, num_outputs))
biases = bias_variable(shape=shape(num_outputs))
# 執行輸入層與權重的矩陣乘法,然後添加偏差

layer = tf$matmul(input, weights) + biases
# 是否使用ReLU
if(use_relu){
layer = tf$nn$relu(layer)
}
return(layer)
}/<code>

3.7.3 工作原理

函數create_fc_layer從初始化新的權重和偏差開始。然後,執行輸入層與初始化權重的矩陣乘法,並添加相關的偏差。

如果完全連接層不是CNN TensorFlow圖的最後一層,就可以執行ReLU非線性激活。最後,返回完全連接層。

3.8 定義佔位符變量

在本節中,我們定義一個佔位符變量,作為TensorFlow計算圖中模塊的輸入。這些通常是張量形式的多維數組或矩陣。

3.8.1 做好準備

佔位符變量的數據類型被設置為float32(tf$float32),並將形狀設置為二維張量。

3.8.2 怎麼做

1.創建一個輸入佔位符變量:

<code>x = tf$placeholder(tf$float32, shape=shape(NULL, img_size_flat),
name='x')/<code>

佔位符中的NULL值允許我們傳遞不確定的數組大小。

2.將輸入佔位符x重塑為4維張量:

<code>x_image = tf$reshape(x, shape(-1L, img_size, img_size,
num_channels))/<code>

3.創建一個輸出佔位符變量:

<code>y_true = tf$placeholder(tf$float32, shape=shape(NULL, num_classes),
name='y_true')/<code>

4.使用argmax獲取輸出的類(true):

<code>y_true_cls = tf$argmax(y_true, dimension=1L)/<code>

3.8.3 工作原理

在3.8.2小節的步驟1中,我們定義了一個輸入佔位符變量。形狀張量的維度為NULL和img_size_flat。 將前者設置成可保存任意數量圖像(作為行),後者定義每張圖像輸入特徵的長度(作為列)。 在3.8.2小節的步驟2中,輸入的二維張量被重塑為一個4維張量,可以作為輸入卷積層。4個維度如下:

  • 第一個定義了輸入圖像的數量(當前設置為-1);
  • 第二個定義每張圖的高度(相當於圖像大小32L);
  • 第三個定義每張圖的寬度(相當於圖像大小,同樣是32L);
  • 第四個定義每張圖中的顏色通道數量(此處為3L)。

在3.8.2小節的步驟3中,我們定義一個輸出佔位符變量來保存x中圖像的真實類或標籤。形狀張量的維度為NULL和num_classes。前者被設置為保存任意數量的圖像(作為行),後者將每張圖的真實類別定義為長度為num_classes的二進制向量(作為列)。在我們的場景中,有10類。在3.8.2小節的步驟4中,我們將二維輸出佔位符壓縮為類別號從1到10的一維張量。

3.9 創建第一個卷積層

在本節中,我們來創建第一個卷積層。

3.9.1 做好準備

在“使用函數創建一個新的卷積層”一節(見3.5節)中定義了函數create_conv_layer,以下是其輸入。

  • input:一個4維重塑的輸入佔位符變量,即x_image。
  • num_input_channels:彩色通道的數量,即num_channels。
  • filter_size:過濾器層的高度和寬度,即filter_size1。
  • num_filters:過濾層的深度,即num_filters1。
  • use_pooling:設置為正確(TRUE)的二進制標誌。

3.9.2 怎麼做

1.使用前面的輸入參數運行create_conv_layer函數:

<code>#  卷積層1
conv1 num_input_channels=num_channels,
filter_size=filter_size1,
num_filters=num_filters1,
use_pooling=TRUE)/<code>

2.提取第一個卷積層的層(layers):

<code>layer_conv1 conv1_images train_data$images, y_true = train_data$labels))/<code>

3.提取第一個卷積層的最終權重(weights):

<code>weights_conv1 weights_conv1 /<code>

4.生成第一個卷積層繪圖:

<code>drawImage_conv(sample(1:50000, size=1), images.bw = conv1_images,
images.lab=images.lab.train)/<code>

5.生成第一個卷積層的權重圖:

<code>drawImage_conv_weights(weights_conv1)/<code>

3.9.3 工作原理

在3.9.2小節的步驟1和步驟2中,我們創建了第一個4維的卷積層:第一維度表示任意數量的輸入圖像;第二維度和第三維度表示每個卷積圖像的高度(16個像素)和寬度(16個像素);第4個維度表示生成的通道(64), 每個卷積過濾器一個。在3.9.2小節的步驟3和步驟5中,我們提取卷積層的最終權重並繪圖,如圖3-3所示。在3.9.2小節的步驟4中,我們繪製第一個卷積層的輸出,如圖3-4所示。

在R中使用TensorFlow構建一個用於圖像分類的卷積神經網絡

圖3-3

在R中使用TensorFlow構建一個用於圖像分類的卷積神經網絡

圖3-4

3.10 創建第二個卷積層

在本節中,我們來創建第二個卷積層。

3.10.1 做好準備

在“使用函數創建一個新的卷積層”一節(見3.5節)中定義了函數create_conv_layer,以下是其輸入。

  • input:第一個卷積層的四維輸出,即layer_conv1。
  • num_input_channels:第一個卷積層中過濾器的數目(或深度),即num_filters1。
  • filter_size:過濾器層的高度和寬度,即filter_size2。
  • num_filters:過濾器層的深度,即num_filters2。
  • use_pooling:設置為正確(TRUE)的二進制標誌。

3.10.2 怎麼做

1.使用前面的輸入參數運行create_conv_layer函數:

<code>#  卷積層2
conv2 num_input_channels=num_filters1,
filter_size=filter_size2,
num_filters=num_filters2,
use_pooling=TRUE)/<code>

2.提取第二個卷積層的層(layers):

<code>layer_conv2 conv2_images train_data$images, y_true = train_data$labels))/<code>

3.提取第二個卷積層的最終權重(weights):

<code>weights_conv2 weights_conv2 /<code>

4.生成第二個卷積層繪圖:

<code>drawImage_conv(sample(1:50000, size=1), images.bw = conv2_images,
images.lab=images.lab.train)/<code>

5.生成第二個卷積層的權重圖:

<code>drawImage_conv_weights(weights_conv2)/<code>

3.10.3 工作原理

在3.10.2小節的步驟1和步驟2中,我們創建了第二個4維卷積層:第一維度表示任意數量的輸入圖像;第二維度和第三維度表示每張卷積圖像的高度(8個像素)和寬度(8個像素);第四維度表示產生的通道數量(64),每個卷積過濾器一個。

在3.10.2小節的步驟3和步驟5中,我們提取卷積層的最終權重並繪圖,如圖3-5所示。

在R中使用TensorFlow構建一個用於圖像分類的卷積神經網絡

圖3-5

在3.10.2小節的步驟4中,我們繪製第二個卷積層的輸出,如圖3-6所示。

在R中使用TensorFlow構建一個用於圖像分類的卷積神經網絡

圖3-6

3.11 扁平化第二個卷積層

在本節中,我們扁平化創建的第二個卷積層。

3.11.1 做好準備

以下是在“創建第二個卷積層”一節(見3.10節)中定義的函數flatten_conv_layer的輸入。

  • Layer:第二個卷積層的輸出,即layer_conv2。

3.11.2 怎麼做

1.使用前面的輸入參數運行flatten_conv_layer函數:

<code>flatten_lay /<code>

2.提取扁平化層:

<code>layer_flat /<code>

3.提取為每張圖生成的特徵(輸入)的數量:

<code>num_features /<code>

3.11.3 工作原理

在將第二卷積層的輸出與完全連接網絡連接之前,在3.11.2小節的步驟1中,我們將4維卷積層重塑為二維張量;第一維表示任意數量的輸入圖像(作為行);第二維表示為每個長度為4,096的圖像生成的特徵的扁平化向量,即8×8×64(作為列)。3.11.2小節的步驟2和步驟3驗證了重塑層的維度和輸入特徵。

3.12 創建第一個完全連接的層

在本節中,我們來創建第一個完全連接的層。

3.12.1 做好準備

以下是在“使用函數扁平化密集連接層”一節(見3.7節)中定義的函數create_fc_layer的輸入。

  • input:扁平的卷積層,即layer_flat。
  • num_inputs:扁平後創建的特徵的數量,即num_features。
  • num_outputs:完全連接的神經元輸出的數量,即fc_size。
  • use_relu:設置為正確(TRUE)的二進制標誌,以便在張量中引入非線性。

3.12.2 怎麼做

使用前面的輸入參數運行create_fc_layer函數:

<code>layer_fc1 = create_fc_layer(input=layer_flat,
num_inputs=num_features,
num_outputs=fc_size,
use_relu=TRUE)/<code>

3.12.3 工作原理

此處,我們創建一個返回二維張量的完全連接層:第一維表示任意數量的圖像(輸入);第二維表示輸出神經元的數量(此處為1,024)。

3.13 將dropout應用於第一個完全連接的層

在本節中,我們將dropout應用到完全連接層的輸出,以降低過度擬合的可能性。dropout步驟包括在學習過程中隨機移除一些神經元。

3.13.1 做好準備

將dropout連接到層的輸出。因此,建立並加載模型初始結構。例如,在dropout當前層中定義layer_fc1,在其上應用dropout。

3.13.2 怎麼做

1.為dropout創建一個可以將概率作為輸入的佔位符:

<code>keep_prob /<code>

2.使用TensorFlow的dropout函數來處理神經元輸出的縮放(scaling)和遮蔽(masking):

<code>layer_fc1_drop /<code>

3.13.3 工作原理

在3.13.2小節的步驟1和步驟2中,我們可以根據輸入概率(或百分比)丟棄(或遮蔽)輸出神經元。訓練期間通常允許dropout,並且可以在測試期間關閉(通過將概率設定為1或NULL)。

本文截選自:《深度學習實戰手冊》(R語言版)第三章部分內容。

在R中使用TensorFlow構建一個用於圖像分類的卷積神經網絡

  • 深度學習與R語言強強聯手
  • 使用TensorFlow、H2O和MXNet解決複雜的神經網絡問題
  • 全綵印刷,在異步社區免費下載源代碼和彩圖文件

本書將深度學習和R語言兩者結合起來,幫助你解決深度學習實戰中所遇到的各種問題,並且教會你掌握深度學習、神經網絡和機器學習的高級技巧。本書從R語言中的各種深度學習軟件包和軟件庫入手,帶領你學習複雜的深度學習算法。首先,從構建各種神經網絡模型開始,而後逐步過渡到深度學習在文本挖掘和信號處理中的應用,同時還比較了CPU和GPU的性能。
閱讀完本書,你將對深度學習的架構和不同的深度學習包有一個比較深入的理解,能夠為你今後碰到的項目或問題找到合適的解決方案。


分享到:


相關文章: