[英]Why do I need to compile and fit a pretrained model in Keras?
我想加載預訓練的模型並開始在圖像上進行測試。
這是我認為可行的代碼:
from keras.applications.inception_v3 import InceptionV3
from keras.preprocessing import image
from keras.models import Model
from keras.layers import Dense, GlobalAveragePooling2D
from keras import backend as K
base_model = InceptionV3(weights='imagenet', include_top=False)
from __future__ import absolute_import, division, print_function
import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
#Preprocessing
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
train_images = train_images / 255.0
test_images = test_images / 255.0
#Preprocessing
test_loss, test_acc = base_model.evaluate(test_images, test_labels)
print('Test accuracy:', test_acc)
而是說:“您必須在訓練/測試之前編譯模型”
在InceptionV3的https://keras.io/applications/處查看:導入后,它們似乎正在編譯和擬合模型。 他們為什么這樣做呢?
大多數經過預訓練的圖像分類模型都已在ImageNet數據集上進行了預訓練,因此,當您調用base_model = InceptionV3(weights='imagenet', include_top=False)
時,將從該訓練中加載參數權重。 include_top=False
參數實際上從模型中截取了預測層,您需要將其添加並在自己的數據集(在這種情況下為Fashion MNIST)上訓練。
遷移學習方法並不能完全擺脫所有培訓,但是可以做到,因此您只需要根據數據集的特定數據對模型進行微調即可。 由於該模型已經學會了如何通過ImageNet進行訓練來識別基本的甚至有些復雜的形狀,因此現在只需要對其進行訓練即可識別出某些形狀組合在數據上下文中意味着什么。
話雖如此,但我相信即使將include_top=False
更改為include_top=True
,您也仍然可以在某些預處理圖像model.predict(x)
上調用model.predict(x)
,盡管該模型將嘗試將圖像分類為ImageNet的圖像之一1000個班級,不屬於Fashion MNIST的班級之一。
與Fashion MNIST相比,InceptionV3模型在非常不同的圖像上進行了訓練。 您在本教程中看到的是轉移學習的實例。 大致在遷移學習中,您可以將模型分為特征提取模塊和分類模塊。 卷積層和池化層的目標是使特征提取自動化,以便我們可以實現從原始圖像像素到能夠很好描述圖像的一組代表性特征的理想轉換。
這些圖像然后被饋送到分類模塊,其中目標是采用這些特征並實際進行分類。 這就是在卷積和合並之后附加的密集層的目標。 還要注意,InceptionV3模型是在ImageNet圖像上訓練的,該圖像具有1000個類。 為了將ImageNet成功應用於Fashion MNIST數據集,您將需要重新訓練Dense層,以便轉換層和合並層可以提取從圖像中提取的特征並對其進行分類。 因此,將include_top=False
設置為已完成的操作,但是您還必須附加一些Dense層並對其進行重新訓練。 另外,由於Fashion MNIST數據集,還要確保指定最后一層具有10個類。
但是,有些陷阱是InceptionV3可以拍攝299 x 299尺寸的圖像,而Fashion MNIST可以拍攝28 x 28的圖像。您需要調整圖像的大小,並人為地填充圖像的三維尺寸,使其成為RGB。 因為從28 x 28到299 x 299的尺寸要求兩個尺寸都增加10倍,所以以這種分辨率調整圖像大小可能在感覺上不會很好。 InceptionV3可以加載到可以更改預期輸入圖像大小的模型中。 最小的圖像尺寸不幸的是,75×75 InceptionV3,所以我們必須要使用然后調整高達75×75調整圖像大小,你可以使用Scikit圖像resize
的方法skimage.transform
。 另外,如果您打算使用InceptionV3,則需要像訓練之前一樣在網絡中對輸入圖像進行預處理。
因此:
from __future__ import absolute_import, division, print_function
from keras.applications.inception_v3 import InceptionV3
from keras.preprocessing import image
from keras.applications.inception_v3 import preprocess_input # New
from keras.models import Model
from keras.layers import Dense, GlobalAveragePooling2D
from keras import backend as K
import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
base_model = InceptionV3(weights='imagenet', include_top=False, input_shape=(75, 75, 3))
# Now add some Dense Layers - let's also add in a Global Average Pooling layer too
# as a better way to "flatten"
x = base_model.output
x = GlobalAveragePooling2D()(x)
# let's add a fully-connected layer
x = Dense(1024, activation='relu')(x)
# and a softmax layer -- 10 classes
predictions = Dense(10, activation='softmax')(x)
# Create new model
model = Model(inputs=base_model.input, outputs=predictions)
# Make sure we set the convolutional layers and pooling layers so that they're not trainable
for layer in base_model.layers:
layer.trainable = False
#Preprocessing
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
train_images = train_images.astype(np.float) / 255.0 # Change
test_images = test_images.astype(np.float) / 255.0 # Change
# Preprocessing the images
from skimage.transform import resize
train_images_preprocess = np.zeros((train_images.shape[0], 75, 75, 3), dtype=np.float32)
for i, img in enumerate(train_images):
img_resize = resize(img, (75, 75), anti_aliasing=True)
img_resize = preprocess_input(img_resize).astype(np.float32)
train_images_preprocess[i] = np.dstack([img_resize, img_resize, img_resize])
del train_images
test_images_preprocess = np.zeros((test_images.shape[0], 75, 75, 3), dtype=np.float32)
for i, img in enumerate(test_images):
img_resize = resize(img, (75, 75), anti_aliasing=True)
img_resize = preprocess_input(img_resize).astype(np.float32)
test_images_preprocess[i] = np.dstack([img_resize, img_resize, img_resize])
del test_images
# Compile the model
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# Train it
model.fit(train_images_preprocess, train_labels, epochs=15)
# Now evaluate the model - note that we're evaluating on the new model, not the old one
test_loss, test_acc = model.evaluate(test_images_preprocess, test_labels)
print('Test accuracy:', test_acc)
請注意,我必須更改來自InceptionV3基本模型的數據的預期輸入形狀,使其為75 x 75 x 3,其中3表示期望的彩色圖像。 另外,我必須在將數據除以255之前將其轉換為浮點數,否則數據仍將是無符號的8位整數,因此唯一的值將為0或1,從而大大降低了准確性。 另外,我創建了存儲圖像的RGB版本的新數組,這些數組不僅調整為75 x 75,而且還使用了InceptionV3在訓練圖像之前使用的相同方法進行了預處理。 我應該提到的另一件事是,我們需要在Dense圖層之前設置圖層,以免在它們上進行訓練。 我們想使用這些層來提供圖像的特征描述符,這些圖像被抽入Dense層進行分類。 最后,請注意,用於訓練和測試數據的標簽是從0到9枚舉的。因此,您需要的損失函數將是稀疏分類交叉熵,該標簽旨在容納單值標簽。 分類交叉熵損失函數期望一熱編碼。
我們最終編譯了模型,以便我們可以對其進行設置以進行訓練,然后進行訓練。 最后,我們評估測試數據的准確性。 當然,這需要進行一些調整,尤其是所需的密集層數以及要選擇訓練的時期數。
調整圖像的大小並為其創建新的數組將花費一些時間,因為我們分別循環遍歷60000個訓練圖像和10000個測試圖像。 您需要在這里耐心等待。 為了節省內存,我從內存中刪除了原始訓練和測試圖像,以補償預處理后的圖像。
因為Fashion MNIST數據集的自由度比ImageNet的自由度小得多,所以您可以擺脫使用比正常情況少的圖層而獲得高精度模型的麻煩。 ImageNet數據庫由失真度,對象方向,位置和大小各不相同的圖像組成。 如果您構建的模型僅由幾個conv和pool層組成,再加上平整度和幾個致密層,則不僅需要花費更少的時間進行訓練,而且您將獲得性能不錯的模型。
您在Keras文檔中顯示的示例與您要執行的示例不同。 他們適合模型以執行轉移學習。
您似乎只想加載經過預訓練的模型,然后在某些數據集上評估其損失/准確性。 問題在於,要調用model.evaluate
,首先需要定義損失和指標(包括准確性),為此,需要調用model.compile(loss = ..., metrics = ..., optimizer = ...)
,因為這是唯一設置模型損失和指標的Keras調用。
如果由於某種原因您不想這樣做,則可以僅對數據集調用y_pred = model.predict
,並在y_true
和y_pred
上使用y_true
的損耗和度量的任何python實現。 外部化評估時,這不需要編譯模型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.