R語言基于Keras的小數(shù)據(jù)集深度學(xué)習(xí)圖像分類
?原文鏈接:http://tecdat.cn/?p=6714
?
必須使用非常少的數(shù)據(jù)訓(xùn)練圖像分類模型是一種常見情況,如果您在專業(yè)環(huán)境中進(jìn)行計(jì)算機(jī)視覺,則在實(shí)踐中可能會遇到這種情況?!吧贁?shù)”樣本可以表示從幾百到幾萬個圖像的任何地方。作為一個實(shí)際例子,我們將重點(diǎn)放在將圖像分類為狗或貓的數(shù)據(jù)集中,其中包含4,000張貓狗圖片(2,000只貓,2,000只狗)。我們將使用2,000張圖片進(jìn)行訓(xùn)練- 1,000張用于驗(yàn)證,1,000張用于測試。
?
深度學(xué)習(xí)與小數(shù)據(jù)問題的相關(guān)性
您有時會聽到深度學(xué)習(xí)僅在有大量數(shù)據(jù)可用時才有效。這部分是有效的:深度學(xué)習(xí)的一個基本特征是它可以自己在訓(xùn)練數(shù)據(jù)中找到有趣的特征,而不需要手動特征工程,這只有在有大量訓(xùn)練樣例可用時才能實(shí)現(xiàn)。對于輸入樣本非常高維的問題(如圖像)尤其如此。
?讓我們從數(shù)據(jù)開始吧。
下載數(shù)據(jù)
?使用 Dogs vs. Cats數(shù)據(jù)集 。? ?
這里有些例子:
?
?
該數(shù)據(jù)集包含25,000張狗和貓的圖像(每類12,500張),543 MB? 。下載并解壓縮后,您將創(chuàng)建一個包含三個子集的新數(shù)據(jù)集:每個類包含1,000個樣本的訓(xùn)練集,每個類500個樣本的驗(yàn)證集,以及每個類500個樣本的測試集。
以下是執(zhí)行此操作的代碼:
original_dataset_dir < - “?/ Downloads / kaggle_original_data”
base_dir < - “?/ Downloads / cats_and_dogs_small”dir.create(base_dir)
train_dir < - ?file.path(base_dir,“train”)
dir.create(train_dir)
validation_dir < - ?file。 path(base_dir,“validation”)
使用預(yù)訓(xùn)練的convnet
在小圖像數(shù)據(jù)集上深入學(xué)習(xí)的一種常見且高效的方法是使用預(yù)訓(xùn)練網(wǎng)絡(luò)。一個預(yù)訓(xùn)練的網(wǎng)絡(luò)是一個先前在大型數(shù)據(jù)集上訓(xùn)練的已保存網(wǎng)絡(luò),通常是在大規(guī)模圖像分類任務(wù)上。如果這個原始數(shù)據(jù)集足夠大且足夠通用,則預(yù)訓(xùn)練網(wǎng)絡(luò)學(xué)習(xí)的特征的空間層次結(jié)構(gòu)可以有效地充當(dāng)視覺世界的通用模型,因此其特征可以證明對許多不同的計(jì)算機(jī)視覺問題有用,甚至雖然這些新問題可能涉及與原始任務(wù)完全不同的類。?
有兩種方法可以使用預(yù)訓(xùn)練網(wǎng)絡(luò):特征提取和微調(diào)。 讓我們從特征提取開始。
特征提取
特征提取包括使用先前網(wǎng)絡(luò)學(xué)習(xí)的表示來從新樣本中提取感興趣的特征。然后,這些功能將通過一個新的分類器運(yùn)行,該分類器從頭開始訓(xùn)練。
? 為什么只重用卷積基數(shù)?您是否可以重復(fù)使用密集連接的分類器?一般來說,應(yīng)該避免這樣做。原因是卷積基礎(chǔ)學(xué)習(xí)的表示可能更通用,因此更具可重用性 。
注意,由特定卷積層提取的表示的一般性(以及因此可重用性)的級別取決于模型中的層的深度。模型中較早出現(xiàn)的圖層會提取局部的,高度通用的特征貼圖(例如可視邊緣,顏色和紋理),而較高層的圖層會提取更抽象的概念(例如“貓耳朵”或“狗眼”) 。因此,如果您的新數(shù)據(jù)集與訓(xùn)練原始模型的數(shù)據(jù)集有很大不同,那么最好只使用模型的前幾層來進(jìn)行特征提取,而不是使用整個卷積基礎(chǔ)。
?
讓我們通過使用在ImageNet上訓(xùn)練的VGG16網(wǎng)絡(luò)的卷積基礎(chǔ)來實(shí)現(xiàn)這一點(diǎn),從貓和狗圖像中提取有趣的特征,然后在這些特征之上訓(xùn)練狗與貓的分類器。
?
讓我們實(shí)例化VGG16模型。
conv_base < - ?application_vgg16(weights =“imagenet”,include_top = FALSE,input_shape = c(150,150,3))
將三個參數(shù)傳遞給函數(shù):
weights 指定從中初始化模型的權(quán)重。
include_top“密集連接”是指在網(wǎng)絡(luò)頂部包括(或不包括)密集連接的分類器。默認(rèn)情況下,此密集連接的分類器對應(yīng)于ImageNet的1,000個類。
input_shape是您將提供給網(wǎng)絡(luò)的圖像張量的形狀。這個參數(shù)是可選的:如果你不傳遞它,網(wǎng)絡(luò)將能夠處理任何大小的輸入。
?它類似于你已經(jīng)熟悉的簡單的網(wǎng)絡(luò):?
summary(conv_base)
Layer (type) ? ? ? ? ? ? ? ? ? ? Output Shape ? ? ? ? ?Param #
================================================================
input_1 (InputLayer) ? ? ? ? ? ? (None, 150, 150, 3) ? 0
________________________________________________________________
block1_conv1 (Convolution2D) ? ? (None, 150, 150, 64) ?1792
________________________________________________________________
block1_conv2 (Convolution2D) ? ? (None, 150, 150, 64) ?36928
________________________________________________________________
block1_pool (MaxPooling2D) ? ? ? (None, 75, 75, 64) ? ?0
________________________________________________________________
block2_conv1 (Convolution2D) ? ? (None, 75, 75, 128) ? 73856
________________________________________________________________
block2_conv2 (Convolution2D) ? ? (None, 75, 75, 128) ? 147584
________________________________________________________________
block2_pool (MaxPooling2D) ? ? ? (None, 37, 37, 128) ? 0
________________________________________________________________
block3_conv1 (Convolution2D) ? ? (None, 37, 37, 256) ? 295168
________________________________________________________________
block3_conv2 (Convolution2D) ? ? (None, 37, 37, 256) ? 590080
________________________________________________________________
block3_conv3 (Convolution2D) ? ? (None, 37, 37, 256) ? 590080
________________________________________________________________
block3_pool (MaxPooling2D) ? ? ? (None, 18, 18, 256) ? 0
________________________________________________________________
block4_conv1 (Convolution2D) ? ? (None, 18, 18, 512) ? 1180160
________________________________________________________________
block4_conv2 (Convolution2D) ? ? (None, 18, 18, 512) ? 2359808
________________________________________________________________
block4_conv3 (Convolution2D) ? ? (None, 18, 18, 512) ? 2359808
________________________________________________________________
block4_pool (MaxPooling2D) ? ? ? (None, 9, 9, 512) ? ? 0
________________________________________________________________
block5_conv1 (Convolution2D) ? ? (None, 9, 9, 512) ? ? 2359808
________________________________________________________________
block5_conv2 (Convolution2D) ? ? (None, 9, 9, 512) ? ? 2359808
________________________________________________________________
block5_conv3 (Convolution2D) ? ? (None, 9, 9, 512) ? ? 2359808
________________________________________________________________
block5_pool (MaxPooling2D) ? ? ? (None, 4, 4, 512) ? ? 0
================================================================
Total params: 14,714,688
Trainable params: 14,714,688
Non-trainable params: 0
?此時,有兩種方法可以繼續(xù):
在數(shù)據(jù)集上運(yùn)行卷積 。
conv_base通過在頂部添加密集層來擴(kuò)展您的模型() 。
在這篇文章中,我們將詳細(xì)介紹第二種技術(shù) 。請注意, 只有在您可以訪問GPU時才應(yīng)該嘗試 。
?特征提取
由于模型的行為與圖層類似,因此您可以像添加圖層一樣將模型(如conv_base)添加到順序模型中。
model < - ?keras_model_sequential()%>%conv_base%>%layer_flatten()%>%layer_dense( = 256,activation =“relu”)%>%layer_dense(u its = ?, ? “sigmoid”)
這就是模型現(xiàn)在的樣子:?
summary(model)
Layer (type) ? ? ? ? ? ? ? ? ? ? Output Shape ? ? ? ? ?Param #
================================================================
vgg16 (Model) ? ? ? ? ? ? ? ? ? ?(None, 4, 4, 512) ? ? 14714688
________________________________________________________________
flatten_1 (Flatten) ? ? ? ? ? ? ?(None, 8192) ? ? ? ? ?0
________________________________________________________________
dense_1 (Dense) ? ? ? ? ? ? ? ? ?(None, 256) ? ? ? ? ? 2097408
________________________________________________________________
dense_2 (Dense) ? ? ? ? ? ? ? ? ?(None, 1) ? ? ? ? ? ? 257
================================================================
Total params: 16,812,353
Trainable params: 16,812,353
Non-trainable params: 0
如您所見,VGG16的卷積基數(shù)有14,714,688個參數(shù),非常大。?
在Keras中, 使用以下freeze_weights()函數(shù)凍結(jié)網(wǎng)絡(luò):
?
freeze_weights(conv_base)
length(model $ trainable_weights)
?使用數(shù)據(jù)擴(kuò)充
過度擬合是由于過多的樣本需要學(xué)習(xí),導(dǎo)致無法訓(xùn)練可以推廣到新數(shù)據(jù)的模型。?
在Keras中,這可以通過配置對讀取的圖像執(zhí)行的多個隨機(jī)變換來完成,image_data_generator()。例如:
train_datagen = image_data_generator(rescale = 1/255,? = 40,width_shift_range = 0.2,height_shift_range = 0.2,? = 0.2,zoom_range = 0.2,horizo? = TRUE,fill_mode =“nearest”)
?瀏覽一下這段代碼:
rotation_range 是一個度數(shù)(0-180)的值,一個隨機(jī)旋轉(zhuǎn)圖片的范圍。
width_shift并且height_shift是在垂直或水平方向上隨機(jī)平移圖片的范圍。
shear_range 用于隨機(jī)應(yīng)用剪切變換。
zoom_range 用于隨機(jī)縮放圖片內(nèi)部。
horizontal_flip 用于水平地隨機(jī)翻轉(zhuǎn)一半圖像 - 當(dāng)沒有水平不對稱假設(shè)時相關(guān)(例如,真實(shí)世界的圖片)。
fill_mode 是用于填充新創(chuàng)建的像素的策略,可以在旋轉(zhuǎn)或?qū)挾?高度偏移后出現(xiàn)。
現(xiàn)在我們可以使用圖像數(shù)據(jù)生成器訓(xùn)練我們的模型:
model%>%compile(loss =“binary_crossentropy”,optimizer = optimizer_rmsprop(lr = 2e-5),metrics = c(“accuracy”))
history < - ?model%>%fit_generator(train_generator,steps_per_epoch = 100,
繪制結(jié)果。 準(zhǔn)確率達(dá)到約90%。
微調(diào)
另一種廣泛使用的模型重用技術(shù),是對特征提取的補(bǔ)充,是微調(diào) ,微調(diào)網(wǎng)絡(luò)的步驟如下:
在已經(jīng)訓(xùn)練過的基礎(chǔ)網(wǎng)絡(luò)上添加自定義網(wǎng)絡(luò)。
凍結(jié)基礎(chǔ)網(wǎng)絡(luò)。
訓(xùn)練你添加的部分。
解凍基礎(chǔ)網(wǎng)絡(luò)中的某些層。
聯(lián)合訓(xùn)練這些層和您添加的部分。
在進(jìn)行特征提取時,您已經(jīng)完成了前三個步驟。讓我們繼續(xù)第4步:您將解凍您的內(nèi)容conv_base,然后凍結(jié)其中的各個圖層。
現(xiàn)在您可以開始微調(diào)網(wǎng)絡(luò)了。
model%>%compile(lo ropy”,optimizer = opt imizer_rmsprop(lr = 1e-5),metrics = c(“accuracy”))
his el%>%fit_generator(train_ g steps_per_epoch = 100,epochs = 100 ,validation_data = validation_genera tor,validation_steps = 50)
讓我們繪制結(jié)果:
·
你可以看到準(zhǔn)確度有6%的提升,從大約90%到高于96%。
?您現(xiàn)在可以最終在測試數(shù)據(jù)上評估此模型:
test_generator < - ? (test_dir,test_datagen,target_size = c(150,150),batch_size = 20, ?=“binary”)
model%>%evaluate_generator( ,steps = 50)
?
$ loss
[1] 0.2158171
$ acc
[1] 0.965
在這里,您可以獲得96.5%的測試精度。?
?