寫在前面
被Adrian Rosebrock圈粉后,就一直期待他的更新,作者每周一更新,考慮到時差問題(作者在美國),一般北京時間周二才能看到。 作者根據(jù)讀者留言中的問題寫下了這篇博客,迫不及待的學(xué)習(xí)了一番,發(fā)現(xiàn)過一遍是無法完全理解的,還需要重復(fù)。 看來搞研究不是閉門造車,要有分享精神和必要的交流,成人成己。
Introduction
在本教程中,您將了解Keras .fit 和.fit_generator 函數(shù)的工作原理,包括它們之間的差異。為了幫助您獲得實踐經(jīng)驗,我已經(jīng)提供了一個完整的示例,向您展示如何從頭開始實現(xiàn)Keras數(shù)據(jù)生成器。
今天的博客文章的靈感來自PyImageSearch讀者——Shey。
Shey問道:
嗨!阿德里安,謝謝你的教程。我有條不紊地經(jīng)歷過每一個人。他們真的幫助我學(xué)習(xí)深度學(xué)習(xí)。 我對Keras“.fit_generator”函數(shù)有疑問。 我注意到你在博客文章中使用了很多,但是我不確定這個函數(shù)與Keras的標準“.fit”函數(shù)有什么不同。 它有什么不同?我怎么知道何時使用?以及如何為“.fit_generator”函數(shù)創(chuàng)建數(shù)據(jù)生成器?
Shey問了一個很好的問題。
Keras深度學(xué)習(xí)庫包括三個獨立的函數(shù),可用于訓(xùn)練您自己的模型:
.fit .fit_generator .train_on_batch
如果你是Keras和深度學(xué)習(xí)的新手,在試圖確定你應(yīng)該使用哪種函數(shù)時,你可能會覺得有點不知所措。如果你需要使用你自己的自定義數(shù)據(jù),這種混亂只會更加復(fù)雜。
為了幫助掀開關(guān)于Keras fit和fit_generator函數(shù)的迷云,我將花費本教程討論:
- Keras的
.fit ,.fit_generator 和.train_on_batch 函數(shù)之間的區(qū)別 - 在訓(xùn)練自己的深度學(xué)習(xí)模型時,何時使用每個函數(shù)
- 如何實現(xiàn)自己的Keras數(shù)據(jù)生成器,并在使用
.fit_generator 訓(xùn)練模型時使用它 - 在訓(xùn)練完成后評估網(wǎng)絡(luò)時,如何使用
.predict_generator 函數(shù)
如何使用Keras fit和fit_generator(動手教程)
在今天的教程的第一部分中,我們將討論Keras的.fit ,.fit_generator 和.train_on_batch 函數(shù)之間的差異。
我將向您展示一個“非標準”圖像數(shù)據(jù)集的示例,它根本不包含任何實際的PNG,JPEG等圖像!相反,整個圖像數(shù)據(jù)集由兩個CSV文件表示,一個用于訓(xùn)練,第二個用于評估。
我們的目標是實現(xiàn)能夠在此CSV圖像數(shù)據(jù)上訓(xùn)練網(wǎng)絡(luò)的Keras生成器(不用擔心,我將向您展示如何從頭開始實現(xiàn)這樣的生成器功能)。
最后,我們將訓(xùn)練和評估我們的網(wǎng)絡(luò)。
何時使用Keras的fit,fit_generator和train_on_batch函數(shù)?
這三個功能基本上可以完成相同的任務(wù),但他們?nèi)绾稳プ鲞@件事是非常不同的。
讓我們逐個探索這些函數(shù),查看函數(shù)調(diào)用的示例,然后討論它們彼此之間的差異。
Keras .fit函數(shù)
函數(shù)簽名:  調(diào)用.fit :
model.fit(trainX, trainY, batch_size=32, epochs=50)
在這里您可以看到我們提供的訓(xùn)練數(shù)據(jù)(trainX )和訓(xùn)練標簽(trainY )。
然后,我們指示Keras允許我們的模型訓(xùn)練50 個epoch,同時batch size為32 。
對.fit 的調(diào)用在這里做出兩個主要假設(shè):
- 我們的整個訓(xùn)練集可以放入RAM
- 沒有數(shù)據(jù)增強(即不需要Keras生成器)
相反,我們的網(wǎng)絡(luò)將在原始數(shù)據(jù)上訓(xùn)練。
原始數(shù)據(jù)本身將適合內(nèi)存,我們無需將舊批量數(shù)據(jù)從RAM中移出并將新批量數(shù)據(jù)移入RAM。
此外,我們不會使用數(shù)據(jù)增強動態(tài)操縱訓(xùn)練數(shù)據(jù)。
Keras fit_generator函數(shù)
 對于小型,簡單化的數(shù)據(jù)集,使用Keras的.fit 函數(shù)是完全可以接受的。
這些數(shù)據(jù)集通常不是很具有挑戰(zhàn)性,不需要任何數(shù)據(jù)增強。
但是,真實世界的數(shù)據(jù)集很少這么簡單:
- 真實世界的數(shù)據(jù)集通常太大而無法放入內(nèi)存中
- 它們也往往具有挑戰(zhàn)性,要求我們執(zhí)行數(shù)據(jù)增強以避免過擬合并增加我們的模型的泛化能力
在這些情況下,我們需要利用Keras的.fit_generator 函數(shù):
# initialize the number of epochs and batch size
EPOCHS = 100
BS = 32
# construct the training image generator for data augmentation
aug = ImageDataGenerator(rotation_range=20, zoom_range=0.15,
width_shift_range=0.2, height_shift_range=0.2, shear_range=0.15,
horizontal_flip=True, fill_mode="nearest")
# train the network
H = model.fit_generator(aug.flow(trainX, trainY, batch_size=BS),
validation_data=(testX, testY), steps_per_epoch=len(trainX) // BS,
epochs=EPOCHS)
我們首先初始化將要訓(xùn)練的網(wǎng)絡(luò)的epoch和batch size。
然后我們初始化aug ,這是一個Keras ImageDataGenerator 對象,用于圖像的數(shù)據(jù)增強,隨機平移,旋轉(zhuǎn),調(diào)整大小等。
執(zhí)行數(shù)據(jù)增強是正則化的一種形式,使我們的模型能夠更好的被泛化。
但是,應(yīng)用數(shù)據(jù)增強意味著我們的訓(xùn)練數(shù)據(jù)不再是“靜態(tài)的” ——數(shù)據(jù)不斷變化。
根據(jù)提供給ImageDataGenerator 的參數(shù)隨機調(diào)整每批新數(shù)據(jù)。
因此,我們現(xiàn)在需要利用Keras的.fit_generator 函數(shù)來訓(xùn)練我們的模型。
顧名思義,.fit_generator 函數(shù)假定存在一個為其生成數(shù)據(jù)的基礎(chǔ)函數(shù)。
該函數(shù)本身是一個Python生成器。
Keras在使用.fit_generator 訓(xùn)練模型時的過程:
- Keras調(diào)用提供給
.fit_generator 的生成器函數(shù)(在本例中為aug.flow ) - 生成器函數(shù)為
.fit_generator 函數(shù)生成一批大小為BS 的數(shù)據(jù) .fit_generator 函數(shù)接受批量數(shù)據(jù),執(zhí)行反向傳播,并更新模型中的權(quán)重- 重復(fù)該過程直到達到期望的epoch數(shù)量
您會注意到我們現(xiàn)在需要在調(diào)用.fit_generator 時提供steps_per_epoch 參數(shù)(.fit 方法沒有這樣的參數(shù))。
為什么我們需要steps_per_epoch ?
請記住,Keras數(shù)據(jù)生成器意味著無限循環(huán),它永遠不會返回或退出。
由于該函數(shù)旨在無限循環(huán),因此Keras無法確定一個epoch何時開始的,并且新的epoch何時開始。
因此,我們將訓(xùn)練數(shù)據(jù)的總數(shù)除以批量大小的結(jié)果作為steps_per_epoch 的值。一旦Keras到達這一步,它就會知道這是一個新的epoch。
Keras train_on_batch函數(shù)
 對于尋求對Keras模型進行精細控制( finest-grained control)的深度學(xué)習(xí)實踐者,您可能希望使用.train_on_batch 函數(shù):
model.train_on_batch(batchX, batchY)
train_on_batch 函數(shù)接受單批數(shù)據(jù),執(zhí)行反向傳播,然后更新模型參數(shù)。
該批數(shù)據(jù)可以是任意大小的(即,它不需要提供明確的批量大小)。
您也可以生成數(shù)據(jù)。此數(shù)據(jù)可以是磁盤上的原始圖像,也可以是以某種方式修改或擴充的數(shù)據(jù)。
當您有非常明確的理由想要維護自己的訓(xùn)練數(shù)據(jù)迭代器時,通常會使用.train_on_batch 函數(shù),例如數(shù)據(jù)迭代過程非常復(fù)雜并且需要自定義代碼。
如果你發(fā)現(xiàn)自己在詢問是否需要.train_on_batch 函數(shù),那么很有可能你可能不需要。
在99%的情況下,您不需要對訓(xùn)練深度學(xué)習(xí)模型進行如此精細的控制。相反,您可能只需要自定義Keras .fit_generator 函數(shù)。
也就是說,如果你需要它,知道存在這個函數(shù)是很好的。
如果您是一名高級深度學(xué)習(xí)從業(yè)者/工程師,并且您確切知道自己在做什么以及為什么這樣做,我通常只建議使用.train_on_batch 函數(shù)。
圖像數(shù)據(jù)集作為CSV文件?
 將在這里使用的數(shù)據(jù)集是Flowers-17數(shù)據(jù)集,它是17種不同花種的集合,每個類別有80個圖像。
我們的目標是培訓(xùn)Keras卷積神經(jīng)網(wǎng)絡(luò),以正確分類每種花卉。
但是,這個項目有點不同:
- 不是使用存儲在磁盤上的原始圖像文件
- 而是將整個圖像數(shù)據(jù)集序列化為兩個CSV文件(一個用于訓(xùn)練,一個用于評估)
要構(gòu)建每個CSV文件,我:
- 循環(huán)輸入數(shù)據(jù)集中的所有圖像
- 將它們調(diào)整為 64×64 像素
- 將 64x64x3 = 12,288 個RGB像素的強度展平為單個列表
- 在CSV文件中寫入12,288個像素值和類標簽(每行一個)
我們的目標是現(xiàn)在編寫一個自定義Keras生成器來解析CSV文件,并為.fit_generator 函數(shù)生成批量圖像和標簽。
等等,如果您已有圖像,為什么還要使用CSV文件呢?
今天的教程是一個如何為.fit_generator 函數(shù)實現(xiàn)自己的Keras生成器的示例。 在現(xiàn)實世界中,數(shù)據(jù)集并不適合您:
- 您可能有非結(jié)構(gòu)化的圖像目錄
- 您可以使用圖像和文本
- 您的圖像可以按特定格式序列化,無論是CSV文件,Caffe或TensorFlow記錄文件等
在這些情況下,您需要知道如何編寫自己的Keras生成器函數(shù)。
請記住,這不是特定的數(shù)據(jù)格式 - 這是編寫您自己需要學(xué)習(xí)的Keras生成器的實際過程(這正是教程其余部分所涵蓋的內(nèi)容)。
項目結(jié)構(gòu)
$ tree --dirsfirst
.
├── pyimagesearch
│ ├── __init__.py
│ └── minivggnet.py
├── flowers17_testing.csv
├── flowers17_training.csv
├── plot.png
└── train.py
1 directory, 6 files
今天我們將使用MiniVGGNet CNN。我們今天不會介紹其實現(xiàn),因為我假設(shè)你已經(jīng)知道如何實現(xiàn)CNN。如果沒有,不用擔心,只需參考我的Keras教程。
我們的序列化圖像數(shù)據(jù)集包含在flowers17_training.csv 和flowers17_testing.csv 中。
我們將在接下來的兩節(jié)中回顧訓(xùn)練腳本train.py 。
實現(xiàn)自定義Keras fit_generator函數(shù)
 我假設(shè)你的系統(tǒng)上安裝了以下庫:
- NumPy
- TensorFlow + Keras
- Scikit-learn
- Matplotlib
每個軟件包都可以通過pip安裝在虛擬環(huán)境中。如果安裝了virtualenvwrapper,則可以使用mkvirtualenv 創(chuàng)建環(huán)境并使用workon 命令激活環(huán)境。從那里你可以使用pip來設(shè)置你的環(huán)境:
$ mkvirtualenv cv -p python3
$ workon cv
$ pip install numpy
$ pip install tensorflow # or tensorflow-gpu
$ pip install keras
$ pip install scikit-learn
$ pip install matplotlib
打開train.py 文件并插入以下代碼:
# set the matplotlib backend so figures can be saved in the background
import matplotlib
matplotlib.use("Agg")
# import the necessary packages
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import SGD
from sklearn.preprocessing import LabelBinarizer
from sklearn.metrics import classification_report
from pyimagesearch.minivggnet import MiniVGGNet
import matplotlib.pyplot as plt
import numpy as np
第2-12行導(dǎo)入我們所需的包和模塊。由于我們將訓(xùn)練圖保存到磁盤,因此第 3行會適當?shù)卦O(shè)置matplotlib 的后端。
值得注意的是,導(dǎo)入包括ImageDataGenerator ,它包含數(shù)據(jù)增強和圖像生成器功能,以及我們將要訓(xùn)練的CNN MiniVGGNet。
讓我們定義csv_image_generator 函數(shù):
def csv_image_generator(inputPath, bs, lb, mode="train", aug=None):
# open the CSV file for reading
f = open(inputPath, "r")
在第1行,我們定義了csv_image_generator 。此功能負責讀取我們的CSV數(shù)據(jù)文件并將圖像加載到內(nèi)存中。它為我們的Keras .fit_generator 函數(shù)生成批量數(shù)據(jù)。
因此,該函數(shù)接受以下參數(shù):
inputPath :CSV數(shù)據(jù)集文件的路徑bs :批量大小,我們將使用32lb :包含我們的類標簽的標簽二進制文件對象mode :(默認為“train” )當且僅當mode ==“eval” 時,才會進行特殊調(diào)整以不通過aug 對象應(yīng)用數(shù)據(jù)擴充(如果提供了一個)aug :(默認為None)如果指定了擴充對象,那么我們將在生成圖像和標簽之前應(yīng)用它
在第3行,將打開CSV數(shù)據(jù)文件進行讀取。
讓我們開始循環(huán)遍歷數(shù)據(jù):
# loop indefinitely
while True:
# initialize our batches of images and labels
images = []
labels = []
CSV文件中的每行數(shù)據(jù)都包含一個序列化為文本字符串的圖像。我從Flowers-17數(shù)據(jù)集生成了文本字符串。此外,我知道這不是存儲圖像的最有效方式,但它對于此示例而言非常有用。
我們的Keras生成器必須無限循環(huán),如第2行所定義。每次需要一批新數(shù)據(jù)時,.fit_generator 函數(shù)將調(diào)用我們的csv_image_generator 函數(shù)。
此外,Keras維護數(shù)據(jù)的緩存/隊列,確保我們正在訓(xùn)練的模型始終具有要訓(xùn)練的數(shù)據(jù)。Keras不斷保持這個隊列的滿載,所以即使你已經(jīng)達到要訓(xùn)練的epoch總數(shù),請記住Keras仍在為數(shù)據(jù)生成器提供數(shù)據(jù),將數(shù)據(jù)保留在隊列中。
始終確保您的函數(shù)返回數(shù)據(jù),否則,Keras將錯誤地說它無法從您的生成器獲取更多的訓(xùn)練數(shù)據(jù)。
在循環(huán)的每次迭代中,我們將我們的圖像 和標簽 重新初始化為空列表(第4-5行)。
將圖像和標簽附加到這些列表中,直到達到我們的批量大?。?/p>
# keep looping until we reach our batch size
while len(images) < bs:
# attempt to read the next line of the CSV file
line = f.readline()
# check to see if the line is empty, indicating we have
# reached the end of the file
if line == "":
# reset the file pointer to the beginning of the file
# and re-read the line
f.seek(0)
line = f.readline()
# if we are evaluating we should now break from our
# loop to ensure we don't continue to fill up the
# batch from samples at the beginning of the file
if mode == "eval":
break
# extract the label and construct the image
line = line.strip().split(",")
label = line[0]
image = np.array([int(x) for x in line[1:]], dtype="uint8")
image = image.reshape((64, 64, 3))
# update our corresponding batches lists
images.append(image)
labels.append(label)
讓我們來看看這個循環(huán):
- 首先,我們從文本文件對象中讀取一行(第4行)
- 如果
line 為空:
- 重置文件指針并嘗試讀取一行(第11和12行)
- 如果處于評估模式,就從循環(huán)中退出(第17和18行)。
- 從CSV文件中解析圖像和標簽(第21-23行)。
- 調(diào)用
.reshape 將的1維數(shù)組重塑為圖像,該圖像是64×64像素,帶有3個顏色通道(第24行)。 - 最后,我們將圖像和標簽附加到各自的列表中,重復(fù)此過程,直到我們的一批圖像已滿(第27和28行)。
注意:在此處進行評估的關(guān)鍵是我們提供model.predict_generator 的steps ,確保測試集中的每個圖像僅預(yù)測一次。我將在本教程后面介紹如何執(zhí)行此過程。
準備好一批圖像和對應(yīng)的標簽后,可以在產(chǎn)生批次之前采取兩個步驟:
# one-hot encode the labels
labels = lb.transform(np.array(labels))
# if the data augmentation object is not None, apply it
if aug is not None:
(images, labels) = next(aug.flow(np.array(images),
labels, batch_size=bs))
# yield the batch to the calling function
yield (np.array(images), labels)
最后步驟包括:
- One-hot encoding
labels (第2行) - 必要時應(yīng)用數(shù)據(jù)增強(第5-7行)
最后,我們的生成器根據(jù)請求“生成”圖像數(shù)組和調(diào)用函數(shù)標簽列表(第62行)。如果您不熟悉yield 關(guān)鍵字,它將用作Python Generator函數(shù),作為一種方便的快捷方式,而不是構(gòu)建具有較少內(nèi)存消耗的迭代器類。您可以在[此處[(https://wiki./moin/Generators)閱讀有關(guān)Python生成器的更多信息。
初始化訓(xùn)練參數(shù):
# initialize the paths to our training and testing CSV files
TRAIN_CSV = "flowers17_training.csv"
TEST_CSV = "flowers17_testing.csv"
# initialize the number of epochs to train for and batch size
NUM_EPOCHS = 75
BS = 32
# initialize the total number of training and testing image
NUM_TRAIN_IMAGES = 0
NUM_TEST_IMAGES = 0
在此示例訓(xùn)練腳本中,許多初始化都是硬編碼的:
- 訓(xùn)練和測試的CSV文件路徑(第2和3行)。
- 訓(xùn)練的epoch數(shù)量和batch size(第6和7行)。
- 兩個變量將保存訓(xùn)練和測試圖像的數(shù)量(第10和11行)。
下一個代碼塊:
# open the training CSV file, then initialize the unique set of class
# labels in the dataset along with the testing labels
f = open(TRAIN_CSV, "r")
labels = set()
testLabels = []
# loop over all rows of the CSV file
for line in f:
# extract the class label, update the labels list, and increment
# the total number of training images
label = line.strip().split(",")[0]
labels.add(label)
NUM_TRAIN_IMAGES += 1
# close the training CSV file and open the testing CSV file
f.close()
f = open(TEST_CSV, "r")
# loop over the lines in the testing file
for line in f:
# extract the class label, update the test labels list, and
# increment the total number of testing images
label = line.strip().split(",")[0]
testLabels.append(label)
NUM_TEST_IMAGES += 1
# close the testing CSV file
f.close()
這段代碼很長,但有三個目的:
- 從訓(xùn)練數(shù)據(jù)集中提取所有標簽,以便隨后確定唯一標簽。請注意,
labels 是一個只允許唯一條目的集合(set )。 - 封裝
testLabels 列表。 - 計算
NUM_TRAIN_IMAGES 和NUM_TEST_IMAGES 。
構(gòu)建LabelBinarizer 對象并構(gòu)造數(shù)據(jù)增強對象:
# create the label binarizer for one-hot encoding labels, then encode
# the testing labels
lb = LabelBinarizer()
lb.fit(list(labels))
testLabels = lb.transform(testLabels)
# construct the training image generator for data augmentation
aug = ImageDataGenerator(rotation_range=20, zoom_range=0.15,
width_shift_range=0.2, height_shift_range=0.2, shear_range=0.15,
horizontal_flip=True, fill_mode="nearest")
初始化訓(xùn)練和測試圖像生成器:
# initialize both the training and testing image generators
trainGen = csv_image_generator(TRAIN_CSV, BS, lb,
mode="train", aug=aug)
testGen = csv_image_generator(TEST_CSV, BS, lb,
mode="train", aug=None)
注意細微的相似點和不同點:
- 對兩個生成器都使用
mode =“train” - 只有
trainGen 會執(zhí)行數(shù)據(jù)增強
讓我們用Keras初始化+編譯我們的MiniVGGNet模型并開始訓(xùn)練:
# initialize our Keras model and compile it
model = MiniVGGNet.build(64, 64, 3, len(lb.classes_))
opt = SGD(lr=1e-2, momentum=0.9, decay=1e-2 / NUM_EPOCHS)
model.compile(loss="categorical_crossentropy", optimizer=opt,
metrics=["accuracy"])
# train the network
print("[INFO] training w/ generator...")
H = model.fit_generator(
trainGen,
steps_per_epoch=NUM_TRAIN_IMAGES // BS,
validation_data=testGen,
validation_steps=NUM_TEST_IMAGES // BS,
epochs=NUM_EPOCHS)
第4行,使用分類交叉熵(categorical_crossentropy),因為我們有超過2個類別,否則將使用二進制交叉熵(binary crossentropy )。 第9-14行,調(diào)用.fit_generator 開始訓(xùn)練。 trainGen 生成器對象負責向.fit_generator 函數(shù)生成批量數(shù)據(jù)和標簽。
評估訓(xùn)練結(jié)果:
# re-initialize our testing data generator, this time for evaluating
testGen = csv_image_generator(TEST_CSV, BS, lb,
mode="eval", aug=None)
# make predictions on the testing images, finding the index of the
# label with the corresponding largest predicted probability
predIdxs = model.predict_generator(testGen,
steps=(NUM_TEST_IMAGES // BS) + 1)
predIdxs = np.argmax(predIdxs, axis=1)
# show a nicely formatted classification report
print("[INFO] evaluating network...")
print(classification_report(testLabels.argmax(axis=1), predIdxs,
target_names=lb.classes_))
繼續(xù)并重新初始化testGen ,這次將模式mode 更改為“eval” 以進行評估。
重新初始化后,我們使用.predict_generator 函數(shù)和testGen 進行預(yù)測。在此過程結(jié)束時,將繼續(xù)獲取最大預(yù)測索引。
使用testLabels 和predIdxs ,通過scikit-learn 生成classification_report 。分類報告很好地打印在終端上,以便在訓(xùn)練和評估結(jié)束時進行檢查。
最后一步,使用訓(xùn)練歷史字典H 和matplotlib來生成圖:
# plot the training loss and accuracy
N = NUM_EPOCHS
plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0, N), H.history["loss"], label="train_loss")
plt.plot(np.arange(0, N), H.history["val_loss"], label="val_loss")
plt.plot(np.arange(0, N), H.history["acc"], label="train_acc")
plt.plot(np.arange(0, N), H.history["val_acc"], label="val_acc")
plt.title("Training Loss and Accuracy on Dataset")
plt.xlabel("Epoch #")
plt.ylabel("Loss/Accuracy")
plt.legend(loc="lower left")
plt.savefig("plot.png")
使用fit_generator訓(xùn)練Keras模型并使用predict_generator進行評估
打開終端,導(dǎo)航到源代碼和數(shù)據(jù)集的路徑下,然后執(zhí)行以下命令:
$ python train.py
Using TensorFlow backend.
[INFO] training w/ generator...
Epoch 1/75
31/31 [==============================] - 5s - loss: 3.5171 - acc: 0.1381 - val_loss: 14.5745 - val_acc: 0.0906
Epoch 2/75
31/31 [==============================] - 4s - loss: 3.0275 - acc: 0.2258 - val_loss: 14.1294 - val_acc: 0.1187
Epoch 3/75
31/31 [==============================] - 4s - loss: 2.6691 - acc: 0.2823 - val_loss: 14.4892 - val_acc: 0.0781
...
Epoch 73/75
31/31 [==============================] - 4s - loss: 0.3604 - acc: 0.8720 - val_loss: 0.7640 - val_acc: 0.7656
Epoch 74/75
31/31 [==============================] - 4s - loss: 0.3185 - acc: 0.8851 - val_loss: 0.7459 - val_acc: 0.7812
Epoch 75/75
31/31 [==============================] - 4s - loss: 0.3346 - acc: 0.8821 - val_loss: 0.8337 - val_acc: 0.7719
[INFO] evaluating network...
precision recall f1-score support
bluebell 0.95 0.86 0.90 21
buttercup 0.50 0.93 0.65 15
coltsfoot 0.71 0.71 0.71 21
cowslip 0.71 0.75 0.73 20
crocus 0.78 0.58 0.67 24
daffodil 0.81 0.63 0.71 27
daisy 0.93 0.78 0.85 18
dandelion 0.71 0.94 0.81 18
fritillary 0.90 0.86 0.88 22
iris 1.00 0.79 0.88 24
lilyvalley 0.80 0.73 0.76 22
pansy 0.83 0.83 0.83 18
snowdrop 0.71 0.68 0.70 22
sunflower 1.00 0.94 0.97 18
tigerlily 1.00 0.93 0.96 14
tulip 0.50 0.31 0.38 16
windflower 0.59 1.00 0.74 20
avg / total 0.80 0.77 0.77 340
 在這里,您可以看到我們的網(wǎng)絡(luò)在評估集上獲得了80%的準確度,這對于所使用的相對較淺的CNN非常可觀。
最重要的是,您學(xué)會了如何利用:
- Data generators
.fit_generator .predict_generator
總結(jié)
在本教程中,您了解了Keras用于訓(xùn)練深度神經(jīng)網(wǎng)絡(luò)的三個主要函數(shù)之間的差異。
在自己的項目中實現(xiàn)自己的Keras生成器時,可以使用今天的示例代碼作為模板。
我希望你喜歡今天的博文!
|