Image_classification using resnet50 model with imagenet db with my custom labels - python-3.x

I am working on image_classification problem(multi-class).
i am using resnet50 model( https://keras.io/applications/#classify-imagenet-classes-with-resnet50 ) along with pretrained db "imagenet" using keras
I am getting the the output labels for which the images i passed to the model.
But now,
i have image data and label data with me of my own dataset.
When i pass the images to the resnet50 model it gives back the imagenet labels that are already trained. Now, here, i want the output as my own labels which is already in dataset instead of getting imagenet labels.
How to to fine tune labels in resnet50 model with imagenet db in keras
I have tried the resnet50 model alone and it works fine. but, how to change the output to my own labels instead of imagenet pre-trained labels.
from keras.applications.resnet50 import ResNet50
from keras.preprocessing import image
from keras.applications.resnet50 import preprocess_input, decode_predictions
import numpy as np
import os
model = ResNet50(weights='imagenet')
path='/Users/resnet-sample/'
img_path=os.listdir(path)
count=0
for i in img_path:
img = image.load_img(path+i, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
preds = model.predict(x)
print('Predicted:', decode_predictions(preds, top=1)[0], i)
count=count+1
print(preds)
example:
i have an elephant image in jpg format and label its as an 'elephant' in my dataset.
when i pass this image to resnet50 model which uses imagenet pre-trained db the output i received is 'African-Elephant'(imagenet-label).
So instead of getting imagenet label as output, i want to tune this as 'elephant' as label which is in my dataset.
So, not sure how to fine tune the last layers that gives output as my labels instead of imagenet labels.
Pelase help me on this.
Thanks,
Srknt73

The weights argument should be either None (random initialization), imagenet (pre-training on ImageNet), or the path to the weights file to be loaded. So you give the path to the file containing the labels of your dataset

Related

SVM classification - Bad input shape Error

Im having an error bad input shape I tried searching but I can't understand yet since im new in SVM.
train.csv
testing.csv
# importing required libraries
import numpy as np
# import support vector classifier
from sklearn.svm import SVC
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)
X = pd.read_csv("train.csv")
y = pd.read_csv("testing.csv")
clf = SVC()
clf.fit(X, y)
clf.decision_function(X)
print(clf.predict(X))
raise ValueError("bad input shape {0}".format(shape))
ValueError: bad input shape (1, 6)
The problem here is that you are just inserting your entire table with the training data (plus labels) as the input for just the training data and then try to predict the table of the testing data (data and labels) with the SVM.
This does not work that way.
What you need to do, is to train the SVM with your training data (so data points + label for each data point) and then test it against your testing data (testing data points + labels).
Your code should look like this instead:
# Load training and testing dataset from .csv files
training_dataset = pd.read_csv("train.csv")
testing_dataset = pd.read_csv("testing.csv")
# Load training data points with all relevant features
X_train = training_dataset[['feature1','feature2','feature3','feature4']]
# Load training labels from dataset
y_train = training_dataset['label']
# Load testing data points with all relevant features
X_test = testing_dataset[['feature1','feature2','feature3','feature4']]
# Load testing labels from dataset
y_test = testing_dataset['label']
clf = SVC()
# Train the SVC with the training data (data points and labels)
clf.fit(X_train, y_train)
# Evaluate the decision function with test samples
clf.decision_function(X_test)
# Predict the test samples
print(clf.predict(X_test))
I hope that helps and that this code runs for you. Let me know if I misunderstood something or you have more questions. :)

I want all the output of the pretrained VGG16 model as well as the new classes it is trained on

I have tried transfer learning using VGG16 but only getting a result for those classes which are trained.I want that the output consists of both the VGG16 classes+ my new trained classes. Is it possible?
I have attached my whole code.
import matplotlib.pyplot as plt
import os, PIL
import tensorflow as tf
import numpy as np
import keras
from keras.models import Sequential, Model
from keras.layers.core import Dense, Dropout, Flatten, Reshape, Activation
from keras.layers import Embedding, Input, merge, ELU
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.optimizers import SGD, Adam, RMSprop
from keras.regularizers import l2
from keras.utils.np_utils import to_categorical
import sklearn.metrics as metrics
from PIL import Image, ImageDraw
from keras.applications import VGG16
from keras.applications.vgg16 import preprocess_input, decode_predictions
from keras.preprocessing.image import ImageDataGenerator
def load_images(image_paths):
# Load the images from disk.
images = [plt.imread(path) for path in image_paths]
# Convert to a numpy array and return it.
return np.asarray(images)
def path_join(dirname, filenames):
return [os.path.join(dirname, filename) for filename in filenames]
train_dir = "/home/priyank/Jupyter_notebook/plant_leaves_train_set"
test_dir = "/home/priyank/Jupyter_notebook/val_data_plant"
# # Pre-Trained Model: VGG16
# Downloading the pretrained model of imagenet dataset.
model = VGG16(include_top=True, weights='imagenet')
# # Input Pipeline
# First we need to know the shape of the tensors expected as input by the pre-trained VGG16 model. In this case it is images of shape 224 x 224 x 3.
input_shape = model.layers[0].output_shape[1:3] # the input shape of the vgg16 model
input_shape
# # ImageDataGenerator
# It will pick the image one-by-one and transform all the data each time the image is loaded in the training set.
datagen_train = ImageDataGenerator(
rescale=1./255,
rotation_range=180,
width_shift_range=0.1,
height_shift_range=0.1,
shear_range=0.1,
zoom_range=[0.9, 1.5],
horizontal_flip=True,
vertical_flip=True,
fill_mode='nearest')
datagen_test = ImageDataGenerator(rescale=1./255)
#
# The datagenerator will return the batches of the images. VGG16 model is too large so we can't create the batches too large otherwise we will run out of the RAM and GPU.
# Taking small batch size
batch_size = 20
#
# We can save the randomly transformed images during training, so as to inspect whether they have been overly distorted, so we have to adjust the parameters for the data-generator above.
if True:
save_to_dir = None
else:
save_to_dir='augmented_images/'
generator_train = datagen_train.flow_from_directory(directory=train_dir,
target_size=input_shape,
batch_size=batch_size,
shuffle=True,
save_to_dir=save_to_dir)
generator_test = datagen_test.flow_from_directory(directory=test_dir,
target_size=input_shape,
batch_size=batch_size,
shuffle=False)
steps_test = generator_test.n / batch_size
steps_test
image_paths_train = path_join(train_dir, generator_train.filenames)
image_paths_test = path_join(test_dir, generator_test.filenames)
cls_train = generator_train.classes
cls_test = generator_test.classes
class_names = list(generator_train.class_indices.keys())
class_names
num_classes = generator_train.num_classes
num_classes
# The dataset we have is imbalanced so the gradients for 9.01192 will remain higher adn the gradients of 0.8080 will reamin lower so that model can learn from higher gradient more than the lower gradient.
#
from sklearn.utils.class_weight import compute_class_weight
class_weight = compute_class_weight(class_weight='balanced',
classes=np.unique(cls_train),
y=cls_train)
class_weight
#
# Predicting the our data image with the already trained VGG16 model. Using a helper function which can resize the image so it can be the input to VGG16 model
def predict(image_path):
# Load and resize the image using PIL.
img = PIL.Image.open(image_path)
img_resized = img.resize(input_shape, PIL.Image.LANCZOS)
# Plot the image.
plt.imshow(img_resized)
plt.show()
# Convert the PIL image to a numpy-array with the proper shape.
img_array = np.expand_dims(np.array(img_resized), axis=0)
# Use the VGG16 model to make a prediction.
# This outputs an array with 1000 numbers corresponding to
# the classes of the ImageNet-dataset.
print(img_array.shape)
pred = model.predict(img_array)
# Decode the output of the VGG16 model.
print(pred)
print(pred.shape)
pred_decoded = decode_predictions(pred)[0]
# Print the predictions.
for code, name, score in pred_decoded:
print("{0:>6.2%} : {1}".format(score, name))
predict(image_path='/home/priyank/Pictures/people.jpg')
predict(image_path=image_paths_train[0])
# The pre-trained VGG16 model was unable to classify images from the plant disease dataset. The reason is perhaps that the VGG16 model was trained on the so-called ImageNet dataset which may not have contained many images of plant diseases.
#
# The lower layers of a Convolutional Neural Network can recognize many different shapes or features in an image. It is the last few fully-connected layers that combine these featuers into classification of a whole image. So we can try and re-route the output of the last convolutional layer of the VGG16 model to a new fully-connected neural network that we create for doing classification
# summary of VGG16 model.
model.summary()
# We can see that the last convolutional layer is called 'block5_pool' so we use Keras to get a reference to that layer.
transfer_layer = model.get_layer('block5_pool')
#
#
# We refer to this layer as the Transfer Layer because its output will be re-routed to our new fully-connected neural network which will do the classification for the Knifey-Spoony dataset.
#
# The output of the transfer layer has the following shape:
#
transfer_layer.output
# we take the part of the VGG16 model from its input-layer to the output of the transfer-layer. We may call this the convolutional model, because it consists of all the convolutional layers from the VGG16 model.
conv_model = Model(inputs=model.input,
outputs=transfer_layer.output)
# Start a new Keras Sequential model.
new_model = Sequential()
# Add the convolutional part of the VGG16 model from above.
new_model.add(conv_model)
# Flatten the output of the VGG16 model because it is from a
# convolutional layer.
new_model.add(Flatten())
# Add a dense (aka. fully-connected) layer.
# This is for combining features that the VGG16 model has
# recognized in the image.
new_model.add(Dense(1024, activation='relu'))
# Add a dropout-layer which may prevent overfitting and
# improve generalization ability to unseen data e.g. the test-set.
new_model.add(Dropout(0.5))
# Add the final layer for the actual classification.
new_model.add(Dense(num_classes, activation='softmax'))
optimizer = Adam(lr=1e-5)
loss = 'categorical_crossentropy'
metrics = ['categorical_accuracy']
# Helper-function for printing whether a layer in the VGG16 model should be trained.
def print_layer_trainable():
for layer in conv_model.layers:
print("{0}:\t{1}".format(layer.trainable, layer.name))
print_layer_trainable()
#
#
# In Transfer Learning we are initially only interested in reusing the pre-trained VGG16 model as it is, so we will disable training for all its layers.
#
conv_model.trainable = False
for layer in conv_model.layers:
layer.trainable = False
print_layer_trainable()
new_model.compile(optimizer=optimizer, loss=loss, metrics=metrics)
epochs = 15
steps_per_epoch = 100
# Steps per epochs are multiplied with the epoch here 100*20 = 2000 means 2000 random images will be selected.
history = new_model.fit_generator(generator=generator_train,
epochs=epochs,
steps_per_epoch=steps_per_epoch,
class_weight=class_weight,
validation_data=generator_test,
validation_steps=steps_test)
new_model.save("trained_new.h5")
predict(image_path = "/home/priyank/Jupyter_notebook/pp.jpg")
**IT is only predicting the 38 classes it is trained on I want, if the new image is not belongs to these 38 classes then the model should return the VGG16 class or no match found. please help **
Thanks in advance.
use functional api instead of Sequential,
offical guide is here: https://keras.io/getting-started/functional-api-guide/
You can find a multi input & multi output model example there. What you want is very similar but uses only one input instead of multiple.

data augmentation in Keras for large datasets

I'm using Keras to train a model for image classification and 'am working with ~50k images. Each image has three channels and size of each image is 150x150. I have to use floats to store the images because of the minute differences in image intensities between the three channels. I'm using a GPU for training but I do not have a lot of memory on my graphics card and neither do I have the monies to upgrade my GPU. I also have to augment my dataset because my training images do not cover all the possible rotations and translations in my testing dataset.
I have written my own generator that splits the input images and labels into chunks before feeding it to Keras' data augmentation routine and model.fit(). Below is my code:
from __future__ import print_function
from keras.preprocessing.image import ImageDataGenerator
from keras.utils import np_utils
from keras.callbacks import Callback
from keras.callbacks import ModelCheckpoint
from keras.callbacks import ReduceLROnPlateau
from keras.callbacks import CSVLogger
from keras.callbacks import EarlyStopping, TensorBoard, LearningRateScheduler
from keras.optimizers import SGD, Adam, RMSprop
from keras import backend as K
import tensorflow as tf
from sklearn.model_selection import train_test_split
import numpy as np
import math
import myCNN # my own convolutional neural network
def myBatchGenerator(X_train_large, y_train_large, chunk_size):
number_of_images = len(y_train_large)
while True:
batch_start = 0
batch_end = chunk_size
while batch_start < number_of_images:
limit = min(batch_end, number_of_images)
X = X_train_large[batch_start:limit,:,:,:]
y = y_train_large[batch_start:limit,:]
yield(X,y)
batch_start += chunk_size
batch_end += chunk_size
if __name__ == '__main__':
input_image_shape = (150,150,3)
# read input images and labels
# X_train_large is an array of type float16
# y_train_large is an array of size number of images x number of classes
X_train_large, y_train_large = myFunctionToReadTrainingImagesAndLabels()
# validation images: about 5000 images
X_validation_large, y_validation_large =
myFunctionToReadValidationImagesAndLabels()
# create a stratified sample from the large training set. use 100 samples from each class
y_train_large_vectors = [np.where(r == 1)[0][0] for r in y_train_large]
unique, counts = np.unique(y_train_large_vectors, return_counts=True)
X_train_sample = np.empty((12000, 150, 150, 3))
y_train_sample = np.empty((12000, 12))
for idx in range(num_classes):
start_idx_for_sample = 100*idx
end_idx_for_sample = start_idx_for_sample+99
start_idx_for_large = np.max(counts)*idx
end_idx_for_large = start_idx_for_large+99
X_train_sample[start_idx_for_sample:end_idx_for_sample,:,:,:] = X_train_large[start_idx_for_large:end_idx_for_large,:,:,:]
y_train_sample[start_idx_for_sample:end_idx_for_sample,:] = y_train_large[start_idx_for_large:end_idx_for_large,:]
# define augmentation needed for image data generator
train_datagen = ImageDataGenerator(featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization=False,
samplewise_std_normalization=False,
zca_whitening=False,
rotation_range=90,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=True,
vertical_flip=True)
train_datagen.fit(X_train_sample)
# load my model
model = myCNN.build_model(input_image_shape)
sgd = SGD(lr=0.05,decay=10e-4,momentum=0.9)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'
for e in range(number_of_epochs):
print('*********************epoch',e)
# get 1000 images at a time from the input image set
for X_train, y_train in myBatchGenerator(X_train_large, y_train_large,chunk_size=1000):
# split it into batches of 32 images/labels and augment on the fly
for X_batch, y_batch in train_datagen.flow(X_train_large,y_train_large,batch_size=32):
# train
model.fit(X_batch,y_batch,validation_data=(X_validation_large,y_validation_large))
model.save('myCNN_trained_on_largedataset.h5')
In short,
1. I create a stratified sample of my input images to use for the image data generator.
2. I split my input images into chunks of 1000 images and feed those 1000 images to the model in batches of 32.
So, I'm training my model on 32 images at a time, augmenting it on the fly and 'am validating the model on ~5000 images.
I'm still running my model but each batch of 32 images is currently taking 30 seconds to solve. This translates to a lot of hours to solve just one epoch. I'm missing something here.
I've tested my CNN code on a smaller dataset and it works. So I know the problem is not my function to read input images nor my CNN. I think it is how am splitting my data into chunks and batching it. But I cannot figure out where I went wrong. Can you please guide me?
Thanks in advance for your time
Why don't you use flow_from_directory() from ImageDataGenerator class? It is a built-in in keras and is very good to handle problem like yours easily!
Flow_from_directory, specificly, draws your batches directly from your directory and you can perform a data augmentation on the fly.
There are also a couple of example I can suggest you:
Building powerful image classification models using very little data. It is a Keras blog post about a problem like yours, very easy to read.
cifar10_cnn_tfaugment2d.py. A more advanced ad-hoc solution on Tensorflow, defining a specific augmenting layer. Very Interesting though!
I think it's enough to make your network run ;).
I hope it can be helpful, good luck!

Keras predict_generator and Image generator

How to use ImageDataGenerator and predict_generator on a single JPEG file in Keras?
I am having a single jpeg and i want to predict the probability using model trained using model.fita-generator function.
If you just have a single .jpeg, you don't need to use the ImageDataGenerator. In the code below I'm assuming you trained your model with RGB images sized 150px x 150px.
img = image.load_img(img_path, target_size=(150, 150))
img_tensor = image.img_to_array(img)
img_tensor = np.expand_dims(img_tensor, axis=0)
img_tensor /= 255.
model.predict(img_tensor)
For more info, check out Francois Chollet's excellent Ipython Notebooks. Specifically, Line (In [2]) of https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/5.4-visualizing-what-convnets-learn.ipynb
In this section, he looks at the intermediate activation layers for an image that wasn't in his train_generator. He loads in a model he created in another Ipython notebook: https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/5.2-using-convnets-with-small-datasets.ipynb

keras ImageDataGenerator flow_from_directory generated data

I'm trying to see the result of using ImageDataGenerator for data augmentation.
Keras reads the data but it seems that it doesn't perform any generation on them. I get as output:
Found 32 images belonging to 1 classes.
but no generated images are saved in the directory I mentioned in save_to_dir parameter of flow_from_directory method.
Here my code:
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
from keras import backend as K
K.set_image_dim_ordering('th')
#the path of images to apply augmentation on them
images_path='train'
#create an instance of ImageDataGenerator
datagen = ImageDataGenerator(width_shift_range=0.2,
height_shift_range=0.2)
datagen.flow_from_directory(directory=images_path, target_size=(480,752),color_mode='grayscale', class_mode=None, save_to_dir='saved',save_prefix='keras_')
img = load_img('train/images/photon10.png')
x = img_to_array(img)
x = x.reshape((1,) + x.shape)
datagen.flow(x,batch_size=1,save_to_dir='saved',save_format='png')
I even tried to perform augmentation on one image and it wasn't saved.
What could be the reason? I'm a starter with Keras.
Note: class mode is None because I don't have a specific category.
flow_from_directory() returns a DirectoryIterator. The files are not saved until you iterate over this iterator.
For example,
iterator = datagen.flow_from_directory(...)
next(iterator)
will save a batch of augmented images to save_to_dir. You can also use a for loop over the iterator to control how many images will be generated.
Its only a declaration, you must use that generator, for example, .next()
datagen.next()
then you will see images in saved

Resources