Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Updated to the Keras 2.0 API.
'''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.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
# dimensions of our images.
img_width, img_height = 150, 150
train_data_dir = 'data/train'
validation_data_dir = 'data/validation'
nb_train_samples = 2000
nb_validation_samples = 800
nb_epoch = 50
model = Sequential()
model.add(Convolution2D(32, 3, 3, input_shape=(3, img_width, img_height)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(64, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=32,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=32,
class_mode='binary')
model.fit_generator(
train_generator,
samples_per_epoch=nb_train_samples,
nb_epoch=nb_epoch,
validation_data=validation_generator,
nb_val_samples=nb_validation_samples)
model.load_weights('first_try.h5')

utonesm commented Jun 20, 2016

thanks for great tutorial! I think the last line of code should be model_save_weights('first_try.h5').

jdelange commented Jun 21, 2016 edited

@utonesm: indeed. The code in the blog is correct.

I agree, excellent tutorial!

randhawp commented Jul 8, 2016

Good learning example.
I am greenhorn with Keras, figuring my way through.

How does one add :
a) K-fold cross validation
b) checkpoint
with the generators
and
c) change the example to more than 2 classes
I tried
model.add(Dense(3)) # 3 classes
model.add(Activation('softmax')) not sure if this is the only change. Will the class_mode change ?

randhawp commented Jul 8, 2016

Answering my own, Thx to Jason Brownlee

Checkpointing is as follows

filepath="weights-improvement-{epoch:02d}-{accuracy:.2f}.hdf5"
checkpoint = ModelCheckpoint(filepath, monitor='accuracy', verbose=1, save_best_only=True,mode='max')
callbacks_list = [checkpoint]

model.fit_generator(
train_generator,
samples_per_epoch=nb_train_samples,
nb_epoch=nb_epoch,
validation_data=validation_generator,
nb_val_samples=nb_validation_samples,callbacks=callbacks_list)

mphuget commented Aug 18, 2016

Thanks for this Gist, using it, I got a strange behaviour, every epoch has a loss set to NAN and an accuracy of 0.0. I suppose this is wrong but I don't find where the bug is. I have to run it once again, I did not notice this was a save_weights and not a load_weights as a consequence it crashed at the end...

mphuget commented Aug 20, 2016

In case somebody encounters the same issue than me (see previous comment), I found the reason: I did not copy the correct number of files in the directories, for unknown reason it bugs on accuracy and loss

Thank you for your codes, I think in the last line, it should be model.save_weights('first_try.h5') rather than model.load_weights('first_try.h5')

I just used the model and my model magically increased its accuracy from 96 to 99 . I have no idea what happened ! But this is a very good tutorial .

@fchollet
Hi everyone,
I followed this tutorial step by step for 5-classes problem. I am getting this error: WindowsError: [Error 123] The filename, directory name, or volume label syntax is incorrect: 'imageNet_data\train/.'. I don't know exactly what the problem of the directory is.

The main changes I made in the tutorial's code to fit my problem are as follow:

  1. For data preparation, I have 5 sub-folders in train & validation folders.
  2. nb_train_samples = 800*5 , nb_validation_samples = 400*5 as each class has 800 images for train, and 400 images for test.
  3. In the output of fully connected layer, model.add(Dense(5))
  4. model.compile(loss='categorical_crossentropy',
    optimizer='adam',
    metrics=['accuracy'])
  5. class_mode='categorical' in both trian_generator & validation_generator

I really appreciate your help.
Thanks
Kamal

Hi,
I solved the problem by adding r'' before the directory for both train and validation. like this:
train_data_dir = r'imageNet_data\train'
validation_data_dir = r'imageNet_data\validation'

Thanks
Kamal

@KamalOthman,Thank You very much!
I refer to your answer, get a better accuracy.

Hello Everyone,

When i used my own dataset. I am getting below error.

OverflowError: Range exceeds valid bounds

Can some one please advise.

Thanks,
Pranith

u0m3 commented Sep 21, 2016

@prapo550: can you specify where you encountered the error? The traceback? Also can you paste your ~/.keras/keras.json config file? When I ran into this issue it was caused by invalid interpretation of input_shape (depending on some config values it's interpreted as (num_channels, size_x, size_y) or as (size_x, size_y, num_channels); see Input shape - below the arguments)

@uom3: Thanks for the response. I am getting below error

Error:
Using Theano backend.
Traceback (most recent call last):
File "test.py", line 31, in
model.add(Dense(64))
File "/Users/prapo/anaconda/lib/python2.7/site-packages/keras/models.py", line 308, in add
output_tensor = layer(self.outputs[0])
File "/Users/prapo/anaconda/lib/python2.7/site-packages/keras/engine/topology.py", line 488, in call
self.build(input_shapes[0])
File "/Users/prapo/anaconda/lib/python2.7/site-packages/keras/layers/core.py", line 703, in build
name='{}_W'.format(self.name))
File "/Users/prapo/anaconda/lib/python2.7/site-packages/keras/initializations.py", line 59, in glorot_uniform
return uniform(shape, s, name=name)
File "/Users/prapo/anaconda/lib/python2.7/site-packages/keras/initializations.py", line 32, in uniform
return K.random_uniform_variable(shape, -scale, scale, name=name)
File "/Users/prapo/anaconda/lib/python2.7/site-packages/keras/backend/theano_backend.py", line 110, in random_uniform_variable
return variable(np.random.uniform(low=low, high=high, size=shape),
File "mtrand.pyx", line 1565, in mtrand.RandomState.uniform (numpy/random/mtrand/mtrand.c:17303)
OverflowError: Range exceeds valid bounds

Here is my ~/.keras/keras.json
{
"image_dim_ordering": "tf",
"epsilon": 1e-07,
"floatx": "float32",
"backend": "theano"
}

@u0m3:

Now i am getting this error. I am using .tif images as input.
Found 0 images belonging to 0 classes.
Found 0 images belonging to 0 classes.
Epoch 1/5
Traceback (most recent call last):
File "CNN_images_2.py", line 107, in
nb_val_samples=nb_validation_samples)
File "/Users/prapo/anaconda/lib/python2.7/site-packages/keras/models.py", line 874, in fit_generator
pickle_safe=pickle_safe)
File "/Users/prapo/anaconda/lib/python2.7/site-packages/keras/engine/training.py", line 1415, in fit_generator
'or (x, y). Found: ' + str(generator_output))
Exception: output of generator should be a tuple (x, y, sample_weight) or (x, y). Found: None
Exception in thread Thread-1:
Traceback (most recent call last):
File "/Users/prapo/anaconda/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/Users/prapo/anaconda/lib/python2.7/threading.py", line 754, in run
self.__target(_self.__args, *_self.__kwargs)
File "/Users/prapo/anaconda/lib/python2.7/site-packages/keras/engine/training.py", line 425, in data_generator_task
generator_output = next(generator)
File "/Users/prapo/anaconda/lib/python2.7/site-packages/keras/preprocessing/image.py", line 585, in next
index_array, current_index, current_batch_size = next(self.index_generator)
File "/Users/prapo/anaconda/lib/python2.7/site-packages/keras/preprocessing/image.py", line 433, in _flow_index
current_index = (self.batch_index * batch_size) % N
ZeroDivisionError: integer division or modulo by zero

I carefully followed the given procedure given both at blog and here. Unfortunately, I am getting the following error which I couldn't find a way to solve:
Traceback (most recent call last):
File "", line 1, in
File "/usr/lib/python2.7/dist-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 540, in runfile
execfile(filename, namespace)
File "/home/santez/Desktop/DL Examples/KERAS/Object Recognition/Classifier From Little Data KeraBlog/classifierfromlittledata1.py", line 80, in
model.add(Dense(64))
File "/usr/local/lib/python2.7/dist-packages/keras/models.py", line 308, in add
output_tensor = layer(self.outputs[0])
File "/usr/local/lib/python2.7/dist-packages/keras/engine/topology.py", line 487, in call
self.build(input_shapes[0])
File "/usr/local/lib/python2.7/dist-packages/keras/layers/core.py", line 695, in build
name='{}_W'.format(self.name))
File "/usr/local/lib/python2.7/dist-packages/keras/initializations.py", line 59, in glorot_uniform
return uniform(shape, s, name=name)
File "/usr/local/lib/python2.7/dist-packages/keras/initializations.py", line 32, in uniform
return K.random_uniform_variable(shape, -scale, scale, name=name)
File "/usr/local/lib/python2.7/dist-packages/keras/backend/theano_backend.py", line 140, in random_uniform_variable
return variable(np.random.uniform(low=low, high=high, size=shape),
File "mtrand.pyx", line 1177, in mtrand.RandomState.uniform (numpy/random/mtrand/mtrand.c:9148)
File "mtrand.pyx", line 203, in mtrand.cont2_array_sc (numpy/random/mtrand/mtrand.c:2371)
ValueError: negative dimensions are not allowed

vutsalsinghal commented Oct 17, 2016 edited

@fchollet first of all thank you very much for the tutorial!

My doubt is:

  1. why is there only 1 output neuron(line 76 of the code) when we want to predict either it is a cat or a dog? Shouldn't there be 2 neurons so that while predicting class it can be something like [0 1] for cat(say) and [1 0] for dog?
    I've tried with 2 neurons but I'm getting dimension error...
  2. since you have used only 1 neuron, how would I predict class of a new(or unknown to network) image?
    I used print(model.predict_classes(feature, verbose=1)) (feature is my input) to find the class but output is randomly either [[0]] or [[1]]. So I don't know what to make of it...

Please help

import keras
from keras.models import *
model = load_model('first.h5')

I am getting an error:

Traceback (most recent call last):
  File "detect.py", line 7, in <module>
    model = load_model('first.h5')
  File "/usr/local/lib/python2.7/dist-packages/keras/models.py", line 126, in load_model
    raise ValueError('No model found in config file.')
ValueError: No model found in config file.

How can I load the model for the prediction of new image.

vutsalsinghal commented Oct 20, 2016 edited

@aquibjaved
Dude you first have to save the compiled and trained model to you disk(or download a pre-compiled from some site for your purpose). Only then you can load and work with it.

MrXu commented Oct 23, 2016 edited

Thanks for the great tutorial.

I am getting the following error while running the model:

Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/Users/mrxu/PythonEnv/tf_env/lib/python2.7/site-packages/keras/engine/training.py", line 425, in data_generator_task
    generator_output = next(generator)
  File "/Users/mrxu/PythonEnv/tf_env/lib/python2.7/site-packages/keras/preprocessing/image.py", line 601, in next
    x = img_to_array(img, dim_ordering=self.dim_ordering)
TypeError: 'NoneType' object is not callable

There are 2000 images in training folder and 800 in validation folder.
If I reduce the samples_per_epoch in model.fit_generator, this error will disappear, but come with a warning.

model.fit_generator(
        train_generator,
        samples_per_epoch=1800,
        nb_epoch=1,
        validation_data=validation_generator,
        nb_val_samples=600)

UserWarning: Epoch comprised more thansamples_per_epochsamples, which might affect learning results.
However, when I set the size to be the same size as the number of images in training folder, the same error occurs.

trancept commented Nov 10, 2016 edited

Hello,
Following the tutorial with the same dataset, I got the error:
ValueError: Negative dimension size caused by subtracting 2 from 1
The mnist_mlp.py demo script run well.

$ cat ~/.keras/keras.json 
{
    "image_dim_ordering": "tf",
    "backend": "tensorflow",
    "floatx": "float32",
    "epsilon": 1e-07
}

EDIT : Solved by replacing "tf" by "th" in keras.json !

I get this error:

The model needs to be compiled before being used.

"
model.fit_generator(
... train_generator,
... samples_per_epoch=12,
... nb_epoch=1,
... validation_data=validation_generator,
... nb_val_samples=4)
Traceback (most recent call last):
File "", line 6, in
File "/Users/Zahra/anaconda/envs/tensorflowTwo/lib/python2.7/site-packages/keras/models.py", line 823, in fit_generator
raise Exception('The model needs to be compiled before being used.')
Exception: The model needs to be compiled before being used.

"

how can i use this to show a confusion matrix of the validation generator thanks for the help

Hey,

Is there a way to make the data generators process and provide the images faster? I suspect that every epoch the program re-loads the images and has to resize and process them because it has already "forgotten" that it has processed them before (because for a large image set you wouldn't have enough RAM memory to contain the resized images indefinitely). This is slowing my network training down to a very, very slow pace.

I have an NVIDIA graphics card I use to train networks and usually it is very fast, however when executing this code the training is at least 10x slower than using an already formatted dataset like MNIST data.

Any help is appreciated! Thanks!

Hi @fchollet, First of all thanks to you, for all great contributions to the AI. I have been learning a lot from here. Yesterday I was working with classifier_from_little_data_script_1.py, I got an error at the end, then I look into the code and found that the code is using model.load_weights('first_try.h5') instead of model.save_weights('first_try.h5'). Or is there any specific reason for using model.load_weights('first_try.h5').

aquibjaved commented Nov 23, 2016 edited

I've save the model firstmodel.h5
I want to make prediction for the new images, so for that In the new file, I loaded the saved model and passing the Image through the classifier but I am getting an error:

import keras
from keras.models import load_model
from keras.models import Sequential
import cv2
import numpy as np 
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
model = Sequential()

model =load_model('firstmodel.h5')
model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

img = cv2.imread('cat.jpg')
img = cv2.resize(img,(150,150))
img = np.reshape(img,[1,150,150,3])
classes = model.predict_classes(img)
print classes

Error: Exception: Error when checking : expected convolution2d_input_1 to have 4 dimensions, but got array with shape (150, 150)

I am missing some pre-processing any one please help me out of this?

yinniyu commented Dec 6, 2016

@fchollet, I followed your example of this code, but my training and validation loss values are stuck. I arranged the files into train and validation folders, each contains subfolders for cat and dog images. The code I have is shown below. I've tried the newest version of keras (1.1.2) and the same thing happened. So I tried another version because some other kagglers said it worked for them (didn't work for me). Any suggestions would be appreciated.

`In [1]:
import theano
Using gpu device 0: GRID K520 (CNMeM is enabled)
In [28]:
import keras
keras.version
Out[28]:
'1.0.8'
In [2]:
import os, cv2, random
import numpy as np
import pandas as pd
import shutil
In [3]:
import matplotlib.pyplot as plt
from matplotlib import ticker
import seaborn as sns
%matplotlib inline
In [4]:
from keras import backend as K
#keras 1.1
#check the image dimension spec, I prefer th, so it's depth, row, col
K.image_dim_ordering()
Using Theano backend.
Out[4]:
'th'
In [5]:
K.set_image_dim_ordering('th')
K.image_dim_ordering()
Out[5]:
'th'
In [18]:
from keras.models import Sequential
from keras.layers import Input, Dropout, Flatten, Convolution2D, MaxPooling2D, Dense, Activation
from keras.optimizers import RMSprop, SGD, Adam, adadelta
from keras.callbacks import ModelCheckpoint, Callback, EarlyStopping
from keras.utils import np_utils
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
Preparing the Data
This function resizes the images to 64x64 and samples 4000 images (8%) of the data to run efficiently as a Kaggle Kernel. I also separated cats and dogs for exploratory analysis.
In [14]:
model = Sequential()
model.add(Convolution2D(32, 3, 3, input_shape=(3, 150, 150)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Convolution2D(64, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

the model so far outputs 3D feature maps (height, width, features)

model.add(Flatten()) # this converts our 3D feature maps to 1D feature vectors
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',
optimizer='RMSprop',
metrics=['accuracy'])
In [17]:

In [19]:

this is the augmentation configuration we will use for training

train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
In [20]:
test_datagen = ImageDataGenerator(rescale=1./255)
In [22]:

this is a generator that will read pictures found in

subfolers of 'data/train', and indefinitely generate

batches of augmented image data

train_generator = train_datagen.flow_from_directory(
'train2', # this is the target directory
target_size=(150, 150), # all images will be resized to 150x150
batch_size=32,
class_mode='binary') # since we use binary_crossentropy loss, we need binary labels
Found 2000 images belonging to 3 classes.
In [24]:

this is a similar generator, for validation data

validation_generator = test_datagen.flow_from_directory(
'validation',
target_size=(150, 150),
batch_size=32,
class_mode='binary')
Found 800 images belonging to 3 classes.
In [25]:
from keras.callbacks import History
history = History()
early_stopping=EarlyStopping(monitor='val_loss', patience=5)
In [27]:
model.fit_generator(
train_generator,
samples_per_epoch=2000,
nb_epoch=50,
validation_data=validation_generator,
verbose=1,
nb_val_samples=800)
INFO (theano.gof.compilelock): Refreshing lock /home/ubuntu/.theano/compiledir_Linux-3.13--generic-x86_64-with-debian-jessie-sid-x86_64-2.7.12-64/lock_dir/lock
INFO:theano.gof.compilelock:Refreshing lock /home/ubuntu/.theano/compiledir_Linux-3.13--generic-x86_64-with-debian-jessie-sid-x86_64-2.7.12-64/lock_dir/lock
INFO (theano.gof.compilelock): Refreshing lock /home/ubuntu/.theano/compiledir_Linux-3.13--generic-x86_64-with-debian-jessie-sid-x86_64-2.7.12-64/lock_dir/lock
INFO:theano.gof.compilelock:Refreshing lock /home/ubuntu/.theano/compiledir_Linux-3.13--generic-x86_64-with-debian-jessie-sid-x86_64-2.7.12-64/lock_dir/lock
INFO (theano.gof.compilelock): Refreshing lock /home/ubuntu/.theano/compiledir_Linux-3.13--generic-x86_64-with-debian-jessie-sid-x86_64-2.7.12-64/lock_dir/lock
INFO:theano.gof.compilelock:Refreshing lock /home/ubuntu/.theano/compiledir_Linux-3.13--generic-x86_64-with-debian-jessie-sid-x86_64-2.7.12-64/lock_dir/lock
INFO (theano.gof.compilelock): Refreshing lock /home/ubuntu/.theano/compiledir_Linux-3.13--generic-x86_64-with-debian-jessie-sid-x86_64-2.7.12-64/lock_dir/lock
INFO:theano.gof.compilelock:Refreshing lock /home/ubuntu/.theano/compiledir_Linux-3.13--generic-x86_64-with-debian-jessie-sid-x86_64-2.7.12-64/lock_dir/lock
Epoch 1/50
2000/2000 [==============================] - 21s - loss: -7.7037 - acc: 0.4930 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 2/50
2000/2000 [==============================] - 19s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 3/50
2000/2000 [==============================] - 18s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 4/50
2000/2000 [==============================] - 18s - loss: -7.9693 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 5/50
2000/2000 [==============================] - 18s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 6/50
2000/2000 [==============================] - 18s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 7/50
2000/2000 [==============================] - 18s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 8/50
2000/2000 [==============================] - 18s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 9/50
2000/2000 [==============================] - 18s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 10/50
2000/2000 [==============================] - 18s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 11/50
2000/2000 [==============================] - 18s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 12/50
2000/2000 [==============================] - 18s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 13/50
2000/2000 [==============================] - 19s - loss: -7.9712 - acc: 0.5000 - val_loss: -7.9712 - val_acc: 0.5000
Epoch 14/50
800/2000 [===========>..................] - ETA: 5s - loss: -8.1107 - acc: 0.4913`

running this code without changes.
Output:

Using TensorFlow backend.
Found 22998 images belonging to 2 classes.
Found 2002 images belonging to 2 classes.
Epoch 1/50
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/usr/local/Cellar/python/2.7.12/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "/Users/luca/playground/keras/keras/engine/training.py", line 404, in data_generator_task
generator_output = next(generator)
File "/Users/luca/playground/keras/keras/preprocessing/image.py", line 677, in next
target_size=self.target_size)
File "/Users/luca/playground/keras/keras/preprocessing/image.py", line 186, in load_img
from PIL import Image
ImportError: No module named PIL

Traceback (most recent call last):
File "/Users/luca/playground/keras/kaggle/dog_vs_cat_cnn.py", line 76, in
nb_val_samples=nb_validation_samples)
File "/Users/luca/playground/keras/keras/models.py", line 907, in fit_generator
pickle_safe=pickle_safe)
File "/Users/luca/playground/keras/keras/engine/training.py", line 1425, in fit_generator
'or (x, y). Found: ' + str(generator_output))
Exception: output of generator should be a tuple (x, y, sample_weight) or (x, y). Found: None

motiur commented Dec 19, 2016

Does anyone knows how to do k fold cross-validation using the code sample given above?

tiff image cannot load!

UTTAM2311 commented Dec 30, 2016 edited

Question: Want to do a binary classification.I do have a dataset for it.But my classes are not among the 1000 classes that the Imagenet model has.Will the Transfer learning and fine-tuning still works ??

eunjoa commented Jan 4, 2017

@UTTAM2311 features learned from training a deep network on ImageNet are relevant to other unsean images/classes so tranfer learning and fine tuning would still work on new datasets

anasb commented Jan 12, 2017

@lucastanziano Have you tried pip install Pillow? That worked for me.

How to give custom input and validate

rk-ka commented Jan 22, 2017 edited

OverflowError: Range exceeds valid bound with Dense layer

to solve this error put this in the beginning of the code

from keras import backend as K
K.set_image_dim_ordering('th')

@KamalOthman
Hey, did you get a high accuracy with 5 classes? I got only like 50% accuracy, I think we need to use one-hot encoding and I am figuring out how to

@austinchencym
Hi
Actually I got not more than 70% when I increased number of dataset. However, It looks not stable.
Any new with you? How can you use one-hot encoding based on the example?

Hi Everyone
Now I am trying to train this model on GRAYSCALE images, which I converted from color scale using PIL package. I expected the input_shape should be (1, w, h), but I got this error:
Exception: Error when checking model input: expected convolution2d_input_1 to have shape (None, 1, 150, 150) but got array with shape (32, 3, 150, 150)

When I checked the shape of the image, I got (w, h), Strangely, I do not get error when I keep the input_shape (3, w, h). Is not it strange?

How can I expand the images dimension within flow_from_directory?

Anyone can help please?

Thanks
Kamal

ynngliu commented Jan 29, 2017

Thanks for the excellent tutorial. One issue:

For the data downloaded from Kaggle directly, the code won't run through.
On line 60, the input dimension should be:
input_shape=(img_width, img_height, 3) instead. Referring to: K.image_dim_ordering() == 'th'

Also, the validation sets should include cats labeled from 1000 to 1399, and dogs similarly, if the size is set to 400.

Hi Everyone
Now I am trying to train this model on GRAYSCALE images, which I converted from color scale using PIL package. I expected the input_shape should be (1, w, h), but I got this error:
Exception: Error when checking model input: expected convolution2d_input_1 to have shape (None, 1, 150, 150) but got array with shape (32, 3, 150, 150)
When I checked the shape of the image, I got (w, h), Strangely, I do not get error when I keep the input_shape (3, w, h). Is not it strange?
How can I expand the images dimension within flow_from_directory?
Anyone can help please?
Thanks
Kamal

Hi
I found a solution of my previous question. This can be done by adding an argument of color_mode='grayscale' in the method of flow_from_directory().

Thanks

Meghajit commented Feb 2, 2017

I executed the classifier_from_little_data_script_1.py program. However, I don't know how to make a prediction after we have build and trained the model.. How to do it?

@KamalOthman

tks for sharing ur experience :)

@ynngliu Thanks! That worked.

shilsen commented Feb 22, 2017

Great blog and code. It explains the CNN implementation using Keras and Theano very clearly and straight forward way.

Hi,
I am quite new to deep learning and in keras.
Thanks for the great tutorial, I have successfully run the code and save the weights of the model.

Now how can I load the model and test it on the test images ?

If anyone can help me with some code snippets it will be helpful.

Thanks

@ynngliu Thanks, that works.

embanner commented Mar 5, 2017 edited

See this notebook for an example of fine-tuning a keras.applications.vgg16.VGG16. As a bonus, I was even able to get keras.preprocessing.image.ImageDataGenerator to use keras.applications.vgg16.preprocess_input() for image preprocessing!

Note, I'm using the theano backend.

You can find the original gist at https://gist.github.com/embanner/6149bba89c174af3bfd69537b72bca74.

Is target_size a necessary parameter? I'm using SPP layer thus there is no need to resize input shape, but it doesn't seem to work with flow_from_directory. Can somebody help?

rama100 commented Mar 20, 2017

I was getting an ''TypeError: sigmoid_cross_entropy_with_logits() got an unexpected keyword argument" error at the model.compile(...) line. Turns out you need to be using Tensorflow 1.0 or later. Problem disappeared when I upgraded TF.

GertjanBrouwer commented Mar 21, 2017 edited

Hello,

I copied this code to convnet.py and I added the images to the data folder, but when I run by saying 'python convnet.py' i get this error
Using TensorFlow backend. Traceback (most recent call last): File "convnet.py", line 6, in <module> model.add(Conv2D(32, (3, 3), input_shape=(3, 150, 150))) TypeError: __init__() missing 1 required positional argument: 'nb_col'

What can I do to fix this?

SamuelMarks commented Mar 23, 2017 edited

Data prep helper to go from Kaggle to the layout he has:

for f in *.jpg; do n=${f#*.}; n=${n%%.*}; n=$((10#$n)); if (( n >= $GE && n <= $LE )); then if [[ "$f" == *"cat"* ]]; then ln -s "$PWD/$f" "$D/cat/$f"; else ln -s "$PWD/$f" "$D/dog/$f"; fi; fi; done

Just set different values for each run:

D=validation GE=10#1001 LE=10#2000;
D=train GE=10#0 LE=10#1000;

PS: Script can be made simpler!

YasserMustafa commented Mar 28, 2017 edited

Hi,
This is a very good tutorial, thanks.
In the following, I added some code lines in the beginning of the code that could help you to use a (dialog box) to import the test and validation SubDirectories, I use (tkinter) package to implement this. Meanwhile, I added a Random Seed to obtain same results each time you run the code. I hope that
could help you! The modified Script is:

from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
**import tkinter as tk
from tkinter import filedialog
import os.path
import numpy as np

#fix random seed for reproducibility
seed = 2017
np.random.seed(seed)

root = tk.Tk()
root.withdraw()
train_data_dir = filedialog.askdirectory(parent=root,initialdir="//",title='Pick a directory')
validation_data_dir  = filedialog.askdirectory(parent=root,initialdir="//",title='Pick a directory')
#file_path = filedialog.askopenfilename()
nb_train_samples = sum([len(files) for r, d, files in os.walk(train_data_dir)])
nb_validation_samples = sum([len(files) for r, d, files in os.walk(validation_data_dir)])

print('no. of trained samples = ', nb_train_samples, ' no. of validation samples= ',nb_validation_samples)**


#dimensions of our images.
img_width, img_height = 150, 150

#train_data_dir = r'C:\Users\yasser\Desktop\Caltec_101_Database\101_ObjectCategories_2C\train_images'
#validation_data_dir = r'C:\Users\yasser\Desktop\Caltec_101_Database\101_ObjectCategories_2C\test_images'
#nb_train_samples = 60
#nb_validation_samples = 30

epochs = 20
batch_size = 3

if K.image_data_format() == 'channels_first':
    input_shape = (3, img_width, img_height)
else:
    input_shape = (img_width, img_height, 3)

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

#this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

#this is the augmentation configuration we will use for testing:
#only rescaling
test_datagen = ImageDataGenerator(rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

model.fit_generator(
    train_generator,
    steps_per_epoch=nb_train_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=nb_validation_samples // batch_size)

model.save_weights('first_try.h5')

Hello,
I am trying to use your code for classification of 6 different ball types. I prepared the database of 6 balls (soccer ball, cricket ball, volleyball, golf ball, basketball and tennis ball). I assigned 1500 images per class for training and 200 images per class for validation. I modified the code and made it suitable for categorical classification. The code ran well for some times but later the loss became NAN and accuracy dropped drastically. What could be the possible reason? I have attached the code and result.
Thanks in advance!!!

`### import keras
import tensorflow as tf
import time
import tensorflow as tf
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
K.set_image_dim_ordering('th')

dimensions of our images.

img_width, img_height = 150, 150

train_data_dir = 'all_ball_database/train/'
validation_data_dir = 'all_ball_database/validation'
nb_train_samples = 9000 #1000 #2000
nb_validation_samples = 1200 #60 #800
nb_epoch = 50

model = Sequential()
model.add(Convolution2D(32, 3, 3, input_shape=(3, img_width, img_height)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Convolution2D(64, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(6)) ####### previously it was 1
model.add(Activation('sigmoid'))

model.summary()

model.compile(loss='categorical_crossentropy', ########
optimizer='rmsprop',
metrics=['accuracy'])

this is the augmentation configuration we will use for training

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_width, img_height),
batch_size=32,
class_mode='categorical') ########

validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=32,
class_mode='categorical') ########

model.fit_generator(
train_generator,
samples_per_epoch=nb_train_samples,
nb_epoch=nb_epoch,
validation_data=validation_generator,
nb_val_samples=nb_validation_samples)

model.save_weights('first_try_all_ball_test1.h5')

Result obtained

Found 9000 images belonging to 6 classes.
Found 1200 images belonging to 6 classes.
Epoch 1/50
9000/9000 [==============================] - 523s - loss: 1.4792 - acc: 0.4217 - val_loss: 1.2620 - val_acc: 0.5542
Epoch 2/50
9000/9000 [==============================] - 521s - loss: 1.2138 - acc: 0.5541 - val_loss: 0.9671 - val_acc: 0.6575
Epoch 3/50
9000/9000 [==============================] - 519s - loss: 1.0934 - acc: 0.6099 - val_loss: 1.0787 - val_acc: 0.5942
Epoch 4/50
9000/9000 [==============================] - 519s - loss: 1.0165 - acc: 0.6460 - val_loss: 0.8799 - val_acc: 0.6950
Epoch 5/50
9000/9000 [==============================] - 519s - loss: 0.9509 - acc: 0.6652 - val_loss: 1.2915 - val_acc: 0.5783
Epoch 6/50
9000/9000 [==============================] - 519s - loss: 0.9290 - acc: 0.6788 - val_loss: 0.8560 - val_acc: 0.7075
Epoch 7/50
9000/9000 [==============================] - 519s - loss: 0.9069 - acc: 0.6844 - val_loss: 1.2917 - val_acc: 0.5950
Epoch 8/50
9000/9000 [==============================] - 518s - loss: 0.8866 - acc: 0.7017 - val_loss: 0.8058 - val_acc: 0.7258
Epoch 9/50
9000/9000 [==============================] - 519s - loss: 0.8681 - acc: 0.7058 - val_loss: 0.9180 - val_acc: 0.6842
Epoch 10/50
9000/9000 [==============================] - 520s - loss: 0.8601 - acc: 0.7106 - val_loss: 0.8591 - val_acc: 0.7150
Epoch 11/50
9000/9000 [==============================] - 542s - loss: 0.8413 - acc: 0.7213 - val_loss: 0.9051 - val_acc: 0.6733
Epoch 12/50
9000/9000 [==============================] - 544s - loss: 0.8492 - acc: 0.7127 - val_loss: 1.1429 - val_acc: 0.6733
Epoch 13/50
9000/9000 [==============================] - 535s - loss: 0.8448 - acc: 0.7211 - val_loss: 0.8757 - val_acc: 0.7308
Epoch 14/50
9000/9000 [==============================] - 553s - loss: 0.8413 - acc: 0.7236 - val_loss: 1.2695 - val_acc: 0.6450
Epoch 15/50
9000/9000 [==============================] - 541s - loss: 0.8307 - acc: 0.7234 - val_loss: 0.7614 - val_acc: 0.7667
Epoch 16/50
9000/9000 [==============================] - 554s - loss: 0.8416 - acc: 0.7202 - val_loss: 0.7297 - val_acc: 0.7792
Epoch 17/50
9000/9000 [==============================] - 531s - loss: 0.8552 - acc: 0.7166 - val_loss: 1.0337 - val_acc: 0.6958
Epoch 18/50
9000/9000 [==============================] - 524s - loss: 0.8412 - acc: 0.7224 - val_loss: 0.8860 - val_acc: 0.7133
Epoch 19/50
9000/9000 [==============================] - 525s - loss: 0.8539 - acc: 0.7139 - val_loss: 0.8433 - val_acc: 0.7367
Epoch 20/50
9000/9000 [==============================] - 546s - loss: 0.8703 - acc: 0.7079 - val_loss: 1.0196 - val_acc: 0.7317
Epoch 21/50
9000/9000 [==============================] - 556s - loss: 0.8604 - acc: 0.7127 - val_loss: 1.6799 - val_acc: 0.6750
Epoch 22/50
9000/9000 [==============================] - 537s - loss: nan - acc: 0.1682 - val_loss: nan - val_acc: 0.1800
Epoch 23/50
9000/9000 [==============================] - 535s - loss: nan - acc: 0.1667 - val_loss: nan - val_acc: 0.1750
Epoch 24/50
9000/9000 [==============================] - 529s - loss: nan - acc: 0.1667 - val_loss: nan - val_acc: 0.1658
Epoch 25/50
96/9000 [..............................] - ETA: 485s - loss: nan - acc: 0.1250
`

@PareshKamble
Have you tried 'softmax' Activation for your final/output layer instead of 'sigmoid'?

ShastriRam commented Apr 22, 2017 edited

I have a dataset of 10000 shoeprint images, 5000 left and 5000 right. The images are grayscale and of different sizes. I tried running this code but on every epoch, the accuracy and loss remains approximately the same, 50% and 0.69 respectively. The only difference in the code that I have is that I do not have labelled validation data so I removed that option from model.fit_generator. Can you suggest what I may be doing wrong?

@durgeshm
No i didn't try that. However, reducing the learning rate further helped me solve the problem.

rmsprop = keras.optimizers.RMSprop(lr=0.0001, rho=0.9, epsilon=1e-8, decay=0.0) model.compile(loss='categorical_crossentropy', optimizer=rmsprop, metrics=['accuracy'])

I will try with 'softmax' as well.
Thank you! :)

HsuTzuJen commented May 3, 2017 edited

Excuse me, what is rescale, shear_range, zoom_range and forizontal_filp actually doing respectively? I am a DNN newbie.

mrgloom commented May 5, 2017 edited

Why sigmoid used instead of softmax, can anyone elaborate on this?

Also is there any example of L1\L2 regularization?

Hello there @fchollet and everyone else :)

Lovely tutorial!!

I am pretty new to Keras and to the deep learning realm. I have several questions to ask about the script written above:

1- I have taken a look at the different images within the provided dataset and realized that they are not all the same size. So the question is "does the code resizes them when we specify the input_size?"

2- Does this program actually generate new images from the ones we have saved in the data folder? (because after running the script i did not get anything new except the 'first_try.h5' weights file.

3_ Is the sequential model in the first part of the code made to classify or just to generate the new images? Or in another way, could i use a VGG_Net or GoogleNet instead of it?

Thank you for your time.

@mrgloom i think sigmoid was used because we only have 2 classes and using a binary classification :)

bramton commented May 9, 2017

Thanks a lot for this nice tutorial.
I think there is one small error though, the width and the height should be swapped when setting the target_size.

For doing predictions this worked for me:

from keras.models import load_model
from keras.preprocessing.image import img_to_array, load_img

test_model = load_model('my_model_name.h5')
img = load_img('image_to_predict.jpg',False,target_size=(img_width,img_height))
x = img_to_array(img)
x = np.expand_dims(x, axis=0)
preds = test_model.predict_classes(x)
prob = test_model.predict_proba(x)
print(preds, probs)

if it is not the directory structure and all the images are in a same directory, how to deal with this?
Is there any easy way except for "flow_from_directory" in keras?

edmhs commented May 18, 2017

Thanks @AurelianTactics prediction worked for me too!

blouss commented May 24, 2017

@AurelianTactics, I've tried your code but my error message is : "No model found in config file. Could anyone, help me please ? :)

_from keras.models import load_model
from keras.preprocessing.image import img_to_array, load_img

test_model = load_model('my_model_name.h5')
img = load_img('image_to_predict.jpg',False,target_size=(img_width,img_height))
x = img_to_array(img)
x = np.expand_dims(x, axis=0)
preds = test_model.predict_classes(x)
prob = test_model.predict_proba(x)
print(preds, probs)`_

Asgu95 commented May 31, 2017

Hi @AurelianTactics, your code it works
Output:
1/1 [==============================] - 0s

1/1 [==============================] - 0s
(array([[0]]), array([[ 0.]], dtype=float32))
or
1/1 [==============================] - 0s

1/1 [==============================] - 0s
(array([[1]]), array([[ 1.]], dtype=float32))

How do I determine if it is a dog or a cat?
I do not understand the output data
Help me, please
Sorry for my English

ritazh commented Jun 2, 2017

Confirming preds = model.predict_classes(x) and probs = model.predict_proba(x) work as intended.

The output (array([[1]]), array([[ 1.]], dtype=float32)) means the class predicted is 1 and the probability is 1. In general, all we need is the probability, which is an array of probability of predicting each class as returned by the probs = model.predict_proba(x) . e.g. If we have 3 classes and the probability returned is [0.01, 0.988, 0.022], then the predicted class is the second class. In this particular example, since we only have 2 classes, probability is between 0 and 1, 0 is the first class, 1 is the second class.

Here is my update for this script and for prediction.

For this first script, I have 20 test images, 10 cats, 10 dogs (not part of the training or validation set). Predicted results: 6 images out of 20 were predicted incorrectly.

Asgu95 commented Jun 2, 2017

How do I make a difference if it is not a dog or a cat?
For example: I put as a banana input image and the output is
1/1 [===============================] - 0s
(Array [[1]]), an array ([[1.]], dtype = float32))

achainan commented Jun 9, 2017 edited

Is anyone able to explain @vutsalsinghal and @Asgu95's question? I am getting the same result when making predictions. Thank you.

1/1 [==============================] - 0s
[[ 1.]]

I have 3 different folders in data/train and data/validation so I was expecting a array of 3 different probabilities.

achainan commented Jun 9, 2017 edited

Figured it out. @vutsalsinghal and @Asgu95. I believe the result is of type [[1]] or [[0]] because it is a binary result. It is either a dog or a cat. Cheers. I was trying to get a categorical result rather than a binary result.

Hello everyone! can we use the training data from '.npy' file instead of jpeg/png for ImageDataGenerator?

muthiyanbhushan commented Jun 17, 2017 edited

Hello Everyone,

I tried to follow the tutorial as it is with my own datasets of Cats and Dogs on CPU. I am getting error " Segmnentation fault after I train the model".

Enclosed here is the output. For testing I have used only 5 epochs with a batch size of 4.
I tried changing different batch sizes as 4,8,16,32. Still, I am getting same error.

$ python classifier_from_little_data_script_1.py
Using TensorFlow backend.
Found 1025 images belonging to 2 classes.
Found 219 images belonging to 2 classes.
Epoch 1/5
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE3 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX2 instructions, but these are available on your machine and could speed up CPU computations.
W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use FMA instructions, but these are available on your machine and could speed up CPU computations.
256/256 [==============================] - 43s - loss: 0.7126 - acc: 0.5586 - val_loss: 0.6393 - val_acc: 0.6944
Epoch 2/5
256/256 [==============================] - 52s - loss: 0.6513 - acc: 0.6611 - val_loss: 0.6121 - val_acc: 0.6930
Epoch 3/5
256/256 [==============================] - 52s - loss: 0.5870 - acc: 0.7109 - val_loss: 0.7209 - val_acc: 0.7116
Epoch 4/5
256/256 [==============================] - 53s - loss: 0.5454 - acc: 0.7432 - val_loss: 0.5740 - val_acc: 0.7442
Epoch 5/5
256/256 [==============================] - 56s - loss: 0.5127 - acc: 0.7627 - val_loss: 0.6189 - val_acc: 0.7256
Segmentation fault (core dumped)

Can someone help me with this?

Thank you.

Hello guys :)

I would like to know how to set-up a callback function in order to evaluate my testing set of data at each epoch after the training is being done between the Training set and validation set.

I got 90% validation accuracy while performing the code above (modified to 5 classes), but when i also try to evaluate the testing data, i get only 30% accuracy. Here is how i coded the evaluation at the end of all the training:

#def test_the_model():

bottleneck_features_testing = np.load(open('bottleneck_features_testing_5_classes.npy', "rb"))

model2 = load_model('my_model_5_classes.h5')

model2.compile(optimizer='adam',

loss='categorical_crossentropy', metrics=['accuracy'])

testing_labels = np.array([1,0,0,0,0] * 1523 + [0,1,0,0,0] * 1343 + [0,0,1,0,0] * 1557 + [0,0,0,1,0] * 1365 + [0,0,0,0,1] * 5492)

testing_labels = testing_labels.reshape(11280,5)

bottleneck_features_testing_ev = model2.evaluate(bottleneck_features_testing, testing_labels, verbose=0)

print(bottleneck_features_testing_ev)

Hence, i would like to check the evaluation accuracy (testing accuracy) at each epoch in order to visualize at which epoch the over-fitting starts to take place.
@fchollet could you be of any assistance in this matter?

You may find below my code (which is definitely not perfected yet :) ):

NOTE: here the TestCallback() has been taken from fchollet/keras#2548, but here we need to adapt it i guess, because the input to the model.evaluate() function is not the raw image.

import h5py
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dropout, Flatten, Dense
from keras import applications
from keras import callbacks
from keras.callbacks import ModelCheckpoint, TensorBoard, Callback

dimensions of our images.

img_width, img_height = 150, 150

weights_path = 'vgg16_weights.h5'
top_model_weights_path = 'bottleneck_fc_model_5_classes.h5'

train_data_dir = 'training2'
validation_data_dir = 'validation2'
testing_data_dir = 'testing2'

nb_train_samples = 50000
nb_validation_samples = 10000
nb_testing_samples = 11280

epochs = 50
batch_size = 20

class TestCallback(Callback):
def init(self, test_data):
self.test_data = test_data

def on_epoch_end(self, epoch, logs={}):
    x, y = self.test_data
    loss, acc = self.model.evaluate(x, y, verbose=0)
    print('\nTesting loss: {}, acc: {}\n'.format(loss, acc))

def save_bottlebeck_features():
datagen = ImageDataGenerator(rescale=1. / 255)

#The following line includes rescaling and preprocessing mean (the values here are only an example) as well

#datagen = ImageDataGenerator(rescale=1., featurewise_center=True) #(rescale=1./255)
#datagen.mean=np.array([103.939, 116.779, 123.68],dtype=np.float32).reshape(3,1,1)

# build the VGG16 network
model = applications.VGG16(include_top=False, weights='imagenet')
print('Model loaded.')

#generating the training data

generator = datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode=None,  # this means our generator will only yield batches of data, no labels
    shuffle=False)    # our data will be in order, so all first 10000 images will be BBC, then 10000 BCA,

THEN BCA_A, THEN BDD, THEN NONE; the predict_generator method returns the output of a model, given

a generator that yields batches of numpy data

bottleneck_features_train = model.predict_generator(
    generator, nb_train_samples // batch_size)
np.save(open('bottleneck_features_train_5_classes.npy', 'wb'),
        bottleneck_features_train)

# # generating the validation data
generator = datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode=None,
    shuffle=False)
bottleneck_features_validation = model.predict_generator(
    generator, nb_validation_samples // batch_size)
np.save(open('bottleneck_features_validation_5_classes.npy', 'wb'),
        bottleneck_features_validation)

# # generating the testing data
generator = datagen.flow_from_directory(
    testing_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode=None,
    shuffle=False)
bottleneck_features_testing = model.predict_generator(
    generator, nb_testing_samples // batch_size)
np.save(open('bottleneck_features_testing_5_classes.npy', 'wb'),
        bottleneck_features_testing)

def train_top_model():
print("train_top_model...")
train_data = np.load(open('bottleneck_features_train_5_classes.npy', "rb"))
train_labels = np.array([1,0,0,0,0] * (nb_train_samples // 5) + [0,1,0,0,0] * (nb_train_samples // 5) + [0,0,1,0,0] * (nb_train_samples // 5) + [0,0,0,1,0] * (nb_train_samples // 5)+ [0,0,0,0,1] * (nb_train_samples // 5))
train_labels = train_labels.reshape(nb_train_samples,5)

validation_data = np.load(open('bottleneck_features_validation_5_classes.npy', "rb"))
validation_labels = np.array([1,0,0,0,0] * (nb_validation_samples // 5) + [0,1,0,0,0] * (nb_validation_samples // 5) + [0,0,1,0,0] * (nb_validation_samples // 5)+ [0,0,0,1,0] * (nb_validation_samples // 5)+ [0,0,0,0,1] * (nb_validation_samples // 5))
validation_labels = validation_labels.reshape(nb_validation_samples,5)

model = Sequential()
model.add(Flatten(input_shape=train_data.shape[1:]))
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(5, activation='softmax'))

model.compile(optimizer='adam',
              loss='categorical_crossentropy', metrics=['accuracy'])

Callbacks definition: 1st saves weights at the end of every epoch; 2nd creates the TensorBoard data

checkpointer = ModelCheckpoint(filepath = 'weights.{epoch:02d}-{val_loss:.2f}.hdf5')
tensorboard = TensorBoard(log_dir = './logs', histogram_freq=2,batch_size=batch_size, write_graph=True)#, write_images=True)

!#! If you want to visualize the files created during training, run in your terminal:

tensorboard --logdir path_to_current_dir/Graph

model.fit(train_data, train_labels,
          epochs=epochs,
          batch_size=batch_size,
          validation_data=(validation_data, validation_labels),
          callbacks=[checkpointer, tensorboard, TestCallback()])

elvisun commented Jul 7, 2017

This tutorial literally saved me days of researches, really hope there's more like this!

For this code:

model = Sequential()
  | model.add(Conv2D(32, (3, 3), input_shape=input_shape))
  | model.add(Activation('relu'))
  | model.add(MaxPooling2D(pool_size=(2, 2)))
  |  
  | model.add(Conv2D(32, (3, 3)))
  | model.add(Activation('relu'))
  | model.add(MaxPooling2D(pool_size=(2, 2)))
  |  
  | model.add(Conv2D(64, (3, 3)))
  | model.add(Activation('relu'))
  | model.add(MaxPooling2D(pool_size=(2, 2)))

I am getting

Negative dimension size caused by subtracting 2 from 1 for 'max_pooling2d_2/MaxPool' (op: 'MaxPool') with input shapes: [?,1,75,32].

This makes sense to me, because the first dimension is initially 3, then after the first convolution layer, it becomes 1(because of valid padding), then MaxPool of size (2, 2) wouldn't work, because the first dimension is 1.

Am I getting something wrong?

DeepStillWater commented Jul 11, 2017 edited

Hi,I am trying to trained 100 classes,but I got following things when I train it.
233/400 [================>.............] - ETA: 55s - loss: -745.7780 - acc: 0.0
234/400 [================>.............] - ETA: 55s - loss: -745.5954 - acc: 0.0
235/400 [================>.............] - ETA: 54s - loss: -745.2482 - acc: 0.0
236/400 [================>.............] - ETA: 54s - loss: -745.9713 - acc: 0.0
400/400 [==============================] - 158s - loss: -742.8521 - acc: 0.0125 - val_loss: -729.5145 - val_acc: 0.0144
Epoch 2/1000
400/400 [==============================] - 132s - loss: -744.1944 - acc: 0.0118 - val_loss: -729.2362 - val_acc: 0.0143
Epoch 3/1000
400/400 [==============================] - 131s - loss: -745.6803 - acc: 0.0128 - val_loss: -728.2948 - val_acc: 0.0145

I changed like this:

nb_train_samples = 8153
nb_validation_samples = 10500
epochs = 1000
batch_size = 20

always got negative number and it did not trands to 0,how can I do?Thanks!

@octaviantuchila14

I was getting a similar error about negative dimensions on the MaxPool layer. After looking at the cat ~/.keras/keras.json file, I see that there is a parameter "image_data_format": "channels_last". The code we are given has the channels (3) first, so change the input shape to be (150,150,3).

TannerS commented Jul 28, 2017

dumb question but is there no targets? like the pics are dogs and cats, but what tells it which image is which during the classification

jayz5 commented Jul 29, 2017 edited

While running this script (thanks to all the feedback and suggestions posted above) I got two warnings:

UserWarning: Update your Model call to the Keras 2 API: Model(outputs=Tensor("se..., inputs=Tensor("in...)
model = Model(input=model.input, output=top_model(model.output))

UserWarning: The semantics of the Keras 2 argument steps_per_epoch is not the same as the Keras 1 argument samples_per_epoch. steps_per_epoch is the number of batches to draw from the generator at each epoch. Basically steps_per_epoch = samples_per_epoch/batch_size. Similarly nb_val_samples->validation_steps and val_samples->steps arguments have changed. Update your method calls accordingly.

UserWarning: Update your fit_generator call to the Keras 2 API: fit_generator(<keras.pre..., validation_data=<keras.pre..., steps_per_epoch=125, epochs=3, validation_steps=208)
nb_val_samples=nb_validation_samples)

But otherwise the code finished without problem and a model is generated. Should I be concerned about the above warnings?

jayz5 commented Jul 29, 2017

@TannerS I think that is determined by your train data folder structure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment