I'm a novice in machine learning. I was following this Keras blog to train image classifier using Keras. Though this blog only demonstrates how to train only two classes using binary_crossentropy, I was hoping to train a model using my own custom multi-class(6) image datasets using categorial_crossentropy along with one hot encoded vector. So, here is what I tried so far:
import os
import numpy as np
from keras import applications
from keras import Model
from keras.models import Sequential
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.layers import Input
from keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img
from keras import optimizers
import cv2
img_width, img_height = 150, 150
class_indics = 'class_indices.npy'
bottleneck_train_path = 'bottleneck_features_train.npy'
bottleneck_validation_path = 'bottleneck_features_validation.npy'
top_model_weights_path = 'bottleneck_fc_model.h5'
train_data_dir = 'data/train'
validation_data_dir = 'data/validation/'
nb_train_samples = 4800
nb_validation_samples = 1200
epochs = 50
batch_size = 15
def generate_class_indics():
datagen = ImageDataGenerator(rescale=1. / 255)
generator_top = datagen.flow_from_directory(train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='categorical',
shuffle=False)
# save the class indices to use later in predictions
np.save(class_indics, generator_top.class_indices)
def save_bottleneck_features():
print('Using of bottleneck feature on pretrained model started.')
datagen = ImageDataGenerator(rescale=1. / 255)
# build the VGG16 network
model = applications.VGG16(include_top=False, weights='imagenet')
generator = datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='categorical',
shuffle=False)
bottleneck_features_train = model.predict_generator(
generator, nb_train_samples // batch_size)
np.save(open(bottleneck_train_path, 'wb'),
bottleneck_features_train)
generator = datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode='categorical',
shuffle=False)
bottleneck_features_validation = model.predict_generator(
generator, nb_validation_samples // batch_size)
np.save(open(bottleneck_validation_path, 'wb'),
bottleneck_features_validation)
print('Using of bottleneck feature on pretrained model finished.')
def train_top_model():
print('Training of top model started.')
train_data = np.load(open(bottleneck_train_path, 'rb'))
train_labels = np.array(
[0] * (nb_train_samples // 2) + [1] * (nb_train_samples // 2))
validation_data = np.load(open(bottleneck_validation_path, 'rb'))
validation_labels = np.array(
[0] * (nb_validation_samples // 2) + [1] * (nb_validation_samples // 2))
class_dictionary = np.load('class_indices.npy').item()
num_classes = len(class_dictionary)
model = Sequential()
model.add(Flatten(input_shape=train_data.shape[1:]))
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.7))
model.add(Dense(num_classes, activation='softmax')) #sigmoid
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy', metrics=['categorical_accuracy'])
model.fit(train_data, train_labels,
epochs=epochs,
batch_size=batch_size,
validation_data=(validation_data, validation_labels))
model.save_weights(top_model_weights_path)
print('Training of top model completed & saved as: ',top_model_weights_path)
def fine_tune_pretrained_model():
print('Fine tuning of pretrain model started.')
# build the VGG16 network
input_tensor = Input(shape=(150, 150, 3))
base_model = applications.VGG16(weights='imagenet', include_top=False, input_tensor=input_tensor)
class_dictionary = np.load('class_indices.npy').item()
num_classes = len(class_dictionary)
# build a classifier model to put on top of the convolutional model
top_model = Sequential()
top_model.add(Flatten(input_shape=base_model.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.7))
top_model.add(Dense(num_classes, activation='softmax')) #sigmoid
# note that it is necessary to start with a fully-trained
# classifier, including the top classifier,
# in order to successfully do fine-tuning
top_model.load_weights(top_model_weights_path)
# add the model on top of the convolutional base
model = Model(inputs=base_model.input, outputs=top_model(base_model.output))
# set the first 25 layers (up to the last conv block)
# to non-trainable (weights will not be updated)
for layer in model.layers[:25]:
layer.trainable = False
# compile the model with a SGD/momentum optimizer
# and a very slow learning rate.
model.compile(loss='categorical_crossentropy',
optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
metrics=['categorical_accuracy'])
# prepare data augmentation configuration
train_datagen = ImageDataGenerator(
rescale=1. / 255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_height, img_width),
batch_size=batch_size,
class_mode='categorical')
# fine-tune the model
model.fit_generator(
train_generator,
steps_per_epoch=nb_train_samples // batch_size, # samples_per_epoch=nb_train_samples,
epochs=epochs,
validation_data=validation_generator,
validation_steps=nb_validation_samples)
print('Fine tuning of pretrain model completed.')
if __name__ == '__main__':
if not os.path.exists(class_indics):
generate_class_indics()
if not os.path.exists(bottleneck_train_path):
save_bottleneck_features()
if not os.path.exists(top_model_weights_path):
train_top_model()
fine_tune_pretrained_model()
When I ran this code, save_bottleneck_features()
& train_top_model()
executed correctly, but when I tried to run fine_tune_pretrained_model()
it gives me this error:
Traceback (most recent call last): File "/home/appsbee/PycharmProjects/fruit-classification-master/fruit-classification-master/fruit_classification_new.py", line 266, in fine_tune_pretrained_model() File "/home/appsbee/PycharmProjects/fruit-classification-master/fruit-classification-master/fruit_classification_new.py", line 159, in fine_tune_pretrained_model top_model.load_weights(top_model_weights_path) File "/usr/local/lib/python3.6/dist-packages/keras/engine/network.py", line 1166, in load_weights f, self.layers, reshape=reshape) File "/usr/local/lib/python3.6/dist-packages/keras/engine/saving.py", line 1036, in load_weights_from_hdf5_group str(len(filtered_layers)) + ' layers.') ValueError: You are trying to load a weight file containing 3 layers into a model with 2 layers.
But I can see no extra layer was added on fine_tune_pretrained_model()
.
So, why I am getting this error?
Any help will be appreciated.