-
-
Save fchollet/7eb39b44eb9e16e59632d25fb3119975 to your computer and use it in GitHub Desktop.
'''This script goes along the blog post | |
"Building powerful image classification models using very little data" | |
from blog.keras.io. | |
It uses data that can be downloaded at: | |
https://www.kaggle.com/c/dogs-vs-cats/data | |
In our setup, we: | |
- created a data/ folder | |
- created train/ and validation/ subfolders inside data/ | |
- created cats/ and dogs/ subfolders inside train/ and validation/ | |
- put the cat pictures index 0-999 in data/train/cats | |
- put the cat pictures index 1000-1400 in data/validation/cats | |
- put the dogs pictures index 12500-13499 in data/train/dogs | |
- put the dog pictures index 13500-13900 in data/validation/dogs | |
So that we have 1000 training examples for each class, and 400 validation examples for each class. | |
In summary, this is our directory structure: | |
``` | |
data/ | |
train/ | |
dogs/ | |
dog001.jpg | |
dog002.jpg | |
... | |
cats/ | |
cat001.jpg | |
cat002.jpg | |
... | |
validation/ | |
dogs/ | |
dog001.jpg | |
dog002.jpg | |
... | |
cats/ | |
cat001.jpg | |
cat002.jpg | |
... | |
``` | |
''' | |
from keras import applications | |
from keras.preprocessing.image import ImageDataGenerator | |
from keras import optimizers | |
from keras.models import Sequential | |
from keras.layers import Dropout, Flatten, Dense | |
# path to the model weights files. | |
weights_path = '../keras/examples/vgg16_weights.h5' | |
top_model_weights_path = 'fc_model.h5' | |
# dimensions of our images. | |
img_width, img_height = 150, 150 | |
train_data_dir = 'cats_and_dogs_small/train' | |
validation_data_dir = 'cats_and_dogs_small/validation' | |
nb_train_samples = 2000 | |
nb_validation_samples = 800 | |
epochs = 50 | |
batch_size = 16 | |
# build the VGG16 network | |
model = applications.VGG16(weights='imagenet', include_top=False) | |
print('Model loaded.') | |
# build a classifier model to put on top of the convolutional model | |
top_model = Sequential() | |
top_model.add(Flatten(input_shape=model.output_shape[1:])) | |
top_model.add(Dense(256, activation='relu')) | |
top_model.add(Dropout(0.5)) | |
top_model.add(Dense(1, activation='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.add(top_model) | |
# 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='binary_crossentropy', | |
optimizer=optimizers.SGD(lr=1e-4, momentum=0.9), | |
metrics=['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='binary') | |
validation_generator = test_datagen.flow_from_directory( | |
validation_data_dir, | |
target_size=(img_height, img_width), | |
batch_size=batch_size, | |
class_mode='binary') | |
# fine-tune the model | |
model.fit_generator( | |
train_generator, | |
samples_per_epoch=nb_train_samples, | |
epochs=epochs, | |
validation_data=validation_generator, | |
nb_val_samples=nb_validation_samples) |
Fine tuned models' Prediction code
This codes were checked by myself. They all worked fine.
- If someone want to predict image classes in same model script where model were trained, here is the code :
img_width, img_height = 224, 224
batch_size = 1
datagen = ImageDataGenerator(rescale=1. / 255)
test_generator = datagen.flow_from_directory(
test_dir,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode=None,
shuffle=False)
test_generator.reset()
pred= model.predict_generator(test_generator, steps = no_of_images/batch_size)
predicted_class_indices=np.argmax(pred, axis =1 )
labels = (train_generator.class_indices)
labels = dict((v, k) for k, v in labels.items())
predictions = [labels[k] for k in predicted_class_indices]
print(predicted_class_indices)
print (labels)
print (predictions)
This code is inspired by stack overflow answer. click here
- If someone want to predict image classes in different script (separate from training script file), here is the code :
from tensorflow.python.keras.preprocessing.image import ImageDataGenerator
import json
import os
from tensorflow.keras.models import model_from_json
#Just give below lines parameters
best_weights = 'path to .h5 weight file'
model_json = 'path to saved model json file'
test_dir = 'path to test images'
img_width, img_height = 224, 224
batch_size = 1
nb_img_samples = #no of testing images
with open(model_json, 'r') as json_file:
json_savedModel= json_file.read()
model = tf.keras.models.model_from_json(json_savedModel)
model.summary()
model.load_weights(best_weights)
datagen = ImageDataGenerator(rescale=1. / 255)
test_generator = datagen.flow_from_directory(
folder_path,
target_size=(img_width, img_height),
batch_size=batch_size,
class_mode=None,
shuffle=False)
test_generator.reset()
pred= model.predict_generator(test_generator, steps = nb_img_samples/batch_size)
predicted_class_indices=np.argmax(pred,axis=1)
labels = {'cats': 0, 'dogs': 1} #if you have more classes, just add like this in correct order where your training folder order.
labels = dict((v,k) for k,v in labels.items())
predictions = [labels[k] for k in predicted_class_indices]
print(predicted_class_indices)
print (labels)
print (predictions)
@allanchua101 only you have to edit this directorys path according to your drive file paths.
@lokoprof09 you are welcome
Hi, I get the following error when fine tuning with classifier_from_little_data_script_3.py . Any idea anyone please help.
Traceback (most recent call last):
File "classifier3.py", line 35, in
top_model.add(Dense(256, activation='relu'))
File "/home/zhang/ENTER/lib/python3.8/site-packages/tensorflow/python/training/tracking/base.py", line 456, in _method_wrapper
result = method(self, *args, **kwargs)
File "/home/zhang/ENTER/lib/python3.8/site-packages/tensorflow/python/keras/engine/sequential.py", line 213, in add
output_tensor = layer(self.outputs[0])
File "/home/zhang/ENTER/lib/python3.8/site-packages/tensorflow/python/keras/engine/base_layer.py", line 897, in call
self._maybe_build(inputs)
File "/home/zhang/ENTER/lib/python3.8/site-packages/tensorflow/python/keras/engine/base_layer.py", line 2416, in _maybe_build
self.build(input_shapes) # pylint:disable=not-callable
File "/home/zhang/ENTER/lib/python3.8/site-packages/tensorflow/python/keras/layers/core.py", line 1154, in build
raise ValueError('The last dimension of the inputs to Dense
'
ValueError: The last dimension of the inputs to Dense
should be defined. Found None
.
@fchollet I would really appreciate it if you can help me,
I got the same problem, the following line causes this error:
flatten = Flatten(name='flatten')(vgg16_output)
I changed this line with using GlobalAveragePooling2D(), then it worked.
flatten = GlobalAveragePooling2D()(vgg16_output)
ValueError: The last dimension of the inputs to Dense should be defined. Found None.
Sorry, I got a error like that The shape of the input to "Flatten" is not fully defined (got (None, None, 512). Make sure to pass a complete "input_shape" or "batch_input_shape" argument to the first layer in your model.
I cannot find the weight file to download, '../keras/examples/vgg16_weights.h5' Thanks
@KennethYCK Hi! I am unable to understand how to get the input shape for my first layer. Can you help?
Hello sir,
I have 60 images for three classes (20 images for each class), can you please help me modify your code to suite my data. I will be very grateful.
my email is [email protected]
Thanks