I've successfully distinguish dog and cat by using CNN, now I am trying to train model for (ASL) American Sign Language, I made some changes but not worked and now I've no idea what to change in code and which way and also I google for this but unfortunately didn't worked, this is my FYP- (Final Year Project) and I am stuck, please help me.
I changed loss = binary_crossentropy to loss = sparse_categorical_crossentropy and but still showing label error.
1 class Data_preprocessing:
'Data preprocessing before goes to ML'
# Train by data list initilization
training_data = []
def __init__(self, datadir, categories, img_size):
Data_preprocessing.img_size = img_size
Data_preprocessing.datadir = datadir
Data_preprocessing.categories = categories
def Create_training_data(self):
for category in Data_preprocessing.categories:
# path to cats or dogs dir
path = os.path.join(Data_preprocessing.datadir, category)
class_num = Data_preprocessing.categories.index(category)
# After having the directory for images
# Started to read image by using OpenCv and directly convert it to GRAYSCALE
for img in os.listdir(path):
try:
img_array = cv2.imread(os.path.join(path, img), cv2.IMREAD_GRAYSCALE)
new_array = cv2.resize(img_array, (Data_preprocessing.img_size, Data_preprocessing.img_size))
Data_preprocessing.training_data.append([new_array, class_num])
except Exception as e:
pass
self.Saving_processed_data()
def Saving_processed_data(self):
random.shuffle(Data_preprocessing.training_data)
x = []
y = []
for features, label in Data_preprocessing.training_data:
x.append(features)
y.append(label)
x = np.array(x).reshape(-1, Data_preprocessing.img_size, Data_preprocessing.img_size, 1)
# Saving data by using "pickle"
pickle_out = open("x.pickle", "wb")
pickle.dump(x, pickle_out)
pickle_out.close()
pickle_out = open("y.pickle", "wb")
pickle.dump(y, pickle_out)
pickle_out.close()
categories = ["Dog","Cat"]
categories = ["A","B","C","D","del","E","F","G","H","I","J","K","L","M","N","nothing","O","P","Q","R","S","space","T","U","V","W","X","Y","Z"]
data_preprocessing = Data_preprocessing("ASLDS\\ASLDS",categories, 50)
data_preprocessing.Create_training_data()
2 class Learning_model:
def __init__(self):
pass
def TrainModel(self):
self.x = pickle.load(open("x.pickle", "rb"))
self.y = pickle.load(open("y.pickle", "rb"))
self.x = self.x/255.0
self.model = Sequential()
self.model.add(Conv2D(64, (3,3), input_shape = self.x.shape[1:]))
self.model.add(Activation("relu"))
self.model.add(MaxPooling2D(pool_size=(2,2)))
self.model.add(Conv2D(64, (3,3)))
self.model.add(Activation("relu"))
self.model.add(MaxPooling2D(pool_size=(2,2)))
self.model.add(Flatten())
self.model.add(Dense(64))
self.model.add(Dense(1))
self.model.add(Activation('sigmoid'))
self.model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
self.model.fit(self.x, self.y, batch_size = 32, epochs=10, validation_split = 0.1)
self.model.save("64x3-CNN-ASL.model")
trained_model = Learning_model()
trained_model.TrainModel()
I am expecting that if I input an image of any alphabet so it is supposed to show me corresponding name of that alphabet.
You should change loss to categorical cross entropy. Even I built a similar CNN with Keras.
This CNN is built to recognize 3 different types of images, but you can change input_shape to detect any number of categories.
# Importing the Keras libraries and packages
from keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense
# Initialising the CNN
classifier = Sequential()
classifier.add(Conv2D(32, (3, 3), input_shape = (64, 64, 3), activation = 'relu'))
classifier.add(MaxPooling2D(pool_size = (2, 2)))
classifier.add(Conv2D(32, (3, 3), activation = 'relu'))
classifier.add(MaxPooling2D(pool_size = (2, 2)))
classifier.add(Flatten())
classifier.add(Dense(units = 128, activation = 'relu'))
classifier.add(Dense(units = 3, activation = 'softmax')) # output layer
# Compiling the CNN
classifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])
# Using the CNN on the images
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale = 1./255,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = True)
test_datagen = ImageDataGenerator(rescale = 1./255)
training_set = train_datagen.flow_from_directory('dataset/training_set',
target_size = (64, 64),
batch_size = 32,
class_mode = 'categorical')
test_set = test_datagen.flow_from_directory('dataset/test_set',
target_size = (64, 64),
batch_size = 32,
class_mode = 'categorical')
classifier.fit_generator(training_set,
steps_per_epoch = (8000/32),
epochs = 25,
validation_data = test_set,
validation_steps = (2000/32))
# Fetching Predictions
import numpy as np
from skimage.io import imread
from skimage.transform import resize
class_labels = {v: k for k, v in training_set.class_indices.items()}
img = imread('dataset/single_prediction/random.jpg')
img = resize(img,(64,64))
img = np.expand_dims(img,axis=0)
if(np.max(img)>1):
img = img/255.0
prediction = classifier.predict_classes(img)
print ("\n\n")
print (class_labels[prediction[0]])
Related
I made a Tensorflow pipeline for loading numpy arrays (video data shape (40,160,160,3)). However, it stops working after loading the first x batches.
The problem is solved when removing num_parallel_calls=AUTOTUNE. However, if I do this, the training becomes significantly slower (ETA/epoch ~30 min -> ETA/epoch ~ 4 hours) . Is there a way to load the numpy arrays in parallel (or apply num_parallel_calls=AUTOTUNE) without any problems?
def get_label(file_path):
import os
parts = tf.strings.split(file_path, os.path.sep)
return parts[-2]
def process_video(file_path):
label = get_label(file_path)
video = np.load(file_path, allow_pickle=True)
return np.float32(video/255), np.float32(label)
def set_shape(video, label):
video.set_shape((40,160,160, 3))
label.set_shape([])
return video, label
## Data pipeline
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_ds = tf.data.Dataset.list_files("path/train/*/*",shuffle=True)
train_ds = train_ds.map(lambda item: tf.numpy_function(
process_video, [item], (tf.float32, tf.float32)) ,num_parallel_calls=AUTOTUNE)
train_ds = train_ds.map(set_shape)
train_ds = train_ds.batch(8)
train_ds = train_ds.prefetch(AUTOTUNE)
## Model
def create_LRCN_model():
model = Sequential()
model.add(TimeDistributed(Conv2D(64, (3, 3), padding='same',activation = 'relu'),
input_shape = (40, 160, 160, 3)))
model.add(TimeDistributed(MaxPooling2D((4, 4))))
model.add(TimeDistributed(Dropout(0.25)))
model.add(TimeDistributed(Conv2D(64, (3, 3), padding='same',activation = 'relu')))
model.add(TimeDistributed(MaxPooling2D((4, 4))))
model.add(TimeDistributed(Dropout(0.25)))
model.add(TimeDistributed(Conv2D(64, (3, 3), padding='same',activation = 'relu')))
model.add(TimeDistributed(MaxPooling2D((2, 2))))
model.add(TimeDistributed(Dropout(0.25)))
model.add(TimeDistributed(Conv2D(32, (3, 3), padding='same',activation = 'relu')))
model.add(TimeDistributed(MaxPooling2D((2, 2))))
#model.add(TimeDistributed(Dropout(0.25)))
model.add(TimeDistributed(Flatten()))
model.add(LSTM(32))
model.add(Dense(1, activation = 'sigmoid'))
model.summary()
return model
LRCN_model = create_LRCN_model()
early_stopping_callback = EarlyStopping(monitor = 'val_loss', patience = 15, mode = 'min', restore_best_weights = True)
LRCN_model.compile(loss='binary_crossentropy', optimizer = 'Adam', metrics = ["accuracy"])
LRCN_model_training_history = LRCN_model.fit(train_ds, validation_data= val_ds, epochs = 70, callbacks = [early_stopping_callback]) #class_weight= class_weights,
I am coming from medical background and a newbie in this machine learning field. I am trying to train my U-Net model using keras and tensorflow for image segmentation. However, my loss value is all NaN and the prediction is all black.
I would like to check the U-Net layer by layer but I don't know how to feed the data and from where to start. What I meant by checking for each layer is that I want to feed my images to first layer for example and see the output from the first layer and then moving on to the second layer and until to the last layer. Just want to see how the output is produced for each layer and to check from where the nan value is started. Really appreciate for your help.
These are my codes.
import os
import matplotlib.pyplot as plt
import tensorflow as tf
from keras_preprocessing.image
import ImageDataGenerator
from tensorflow import keras
#Constants
SEED = 42
BATCH_SIZE_TRAIN = 16
BATCH_SIZE_TEST = 16
IMAGE_HEIGHT = 512
IMAGE_WIDTH = 512
IMG_SIZE = (IMAGE_HEIGHT, IMAGE_WIDTH)
data_dir = 'data'
data_dir_train = os.path.join(data_dir, 'training')
data_dir_train_image = os.path.join(data_dir_train, 'img')
data_dir_train_mask = os.path.join(data_dir_train, 'mask')
data_dir_test = os.path.join(data_dir, 'test')
data_dir_test_image = os.path.join(data_dir_test, 'img')
data_dir_test_mask = os.path.join(data_dir_test, 'mask')
NUM_TRAIN = 1413
NUM_TEST = 210
NUM_OF_EPOCHS = 10
def create_segmentation_generator_train(img_path, mask_path, BATCH_SIZE):
data_gen_args = dict(rescale=1./255)
img_datagen = ImageDataGenerator(**data_gen_args)
mask_datagen = ImageDataGenerator(*data_gen_args)
img_generator = img_datagen.flow_from_directory(img_path, target_size=IMG_SIZE, class_mode=None, color_mode='grayscale', batch_size=BATCH_SIZE, seed=SEED)
mask_generator = mask_datagen.flow_from_directory(mask_path, target_size=IMG_SIZE, class_mode=None, color_mode='grayscale', batch_size=BATCH_SIZE, seed=SEED)
return zip(img_generator, mask_generator)
def create_segmentation_generator_test(img_path, mask_path, BATCH_SIZE):
data_gen_args = dict(rescale=1./255)
img_datagen = ImageDataGenerator(**data_gen_args)
mask_datagen = ImageDataGenerator(*data_gen_args)
img_generator = img_datagen.flow_from_directory(img_path, target_size=IMG_SIZE, class_mode=None, color_mode='grayscale', batch_size=BATCH_SIZE, seed=SEED)
mask_generator = mask_datagen.flow_from_directory(mask_path, target_size=IMG_SIZE, class_mode=None, color_mode='grayscale', batch_size=BATCH_SIZE, seed=SEED)
return zip(img_generator, mask_generator)
def display(display_list):
plt.figure(figsize=(15,15))
title = ['Input Image', 'True Mask', 'Predicted Mask']
for i in range(len(display_list)):
plt.subplot(1, len(display_list), i+1)
plt.title(title[i])
plt.imshow(tf.keras.preprocessing.image.array_to_img(display_list[i]), cmap='gray')
plt.show()
def show_dataset(datagen, num=1):
for i in range(0,num):
image,mask = next(datagen)
display([image[0], mask[0]])
def unet(n_levels, initial_features=32, n_blocks=2, kernel_size=3, pooling_size=2, in_channels=1, out_channels=1):
#n_blocks = how many conv in each level
inputs = keras.layers.Input(shape=(IMAGE_HEIGHT, IMAGE_WIDTH, in_channels))
x = inputs
convpars = dict(kernel_size=kernel_size, activation='relu', padding='same')
#downstream
skips = {}
for level in range(n_levels):
for _ in range (n_blocks):
x = keras.layers.Conv2D(initial_features * 2 ** level, **convpars)(x)
if level < n_levels - 1:
skips[level] = x
x = keras.layers.MaxPool2D(pooling_size)(x)
#upstream
for level in reversed(range(n_levels-1)):
x = keras.layers.Conv2DTranspose(initial_features * 2 ** level, strides=pooling_size, **convpars)(x)
x = keras.layers.Concatenate()([x, skips[level]])
for _ in range (n_blocks):
x = keras.layers.Conv2D(initial_features * 2 ** level, **convpars)(x)
#output
activation = 'sigmoid' if out_channels == 1 else 'softmax'
x = keras.layers.Conv2D(out_channels, kernel_size=1, activation='sigmoid', padding='same')(x)
return keras.Model(inputs=[inputs], outputs=[x], name=f'UNET-L{n_levels}-F{initial_features}')
EPOCH_STEP_TRAIN = NUM_TRAIN // BATCH_SIZE_TRAIN
EPOCH_STEP_TEST = NUM_TEST // BATCH_SIZE_TRAIN
model = unet(4)
model.compile(optimizer="adam", loss='binary_crossentropy', metrics=['accuracy'])
model.fit_generator(generator=train_generator, steps_per_epoch=EPOCH_STEP_TRAIN, validation_data=test_generator, validation_steps=EPOCH_STEP_TEST, epochs=NUM_OF_EPOCHS)
def show_prediction(datagen, num=1):
for i in range(0,num):
image,mask = next(datagen)
pred_mask = model.predict(image)[0] > 0.5
display([image[0], mask[0], pred_mask])
show_prediction(test_generator, 2)
To investigate your model layer-by-layer please see example how to show summary of the model and also how to save the model:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
#luodaan input
inputs=keras.Input(shape=(1,))
#luodaan kerros
dense=layers.Dense(64,activation="relu")
x=dense(inputs)
x=layers.Dense(64,activation="relu")(x)
outputs=layers.Dense(10)(x)
#Koostetaa
model=keras.Model(inputs=inputs,outputs=outputs,name="Spesiaali")
#Tarkastellaan
model.summary()
#Tallennellaan
model.save(".\model_to_be_investigated_by_someone_else_to_help_you")
...this makes it possible for you to see the whole model structure for "debugging your AI". If you do not find the solution itself, then add the last row of example to your own code, and then put the resulting folder e.g. to github and ask someone other to see the structure of your model to help you in solving the problem.
The blue drawing illustrates the output of command model.summary() and the red line illustrates the output shape of the first dense layer.
I trained a keras model with my own images, and I have defined an output layer of 3 neurons, but when I try to predict an individual image using model.predict(img) it returns a value out of range, so in my network it should only output the values 0, 1 and 2, but it is outputting values like 4, 6, etc.
Here follows the network code:
from textwrap import indent
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import sys
import cv2 as cv
from tensorflow.keras import datasets, layers, models
def main(training_images, training_labels, test_images, test_labels, single_image=None):
#learnModel(training_images, training_labels, test_images, test_labels)
predictionModel(single_image)
def learnModel(training_images, training_labels, test_images, test_labels):
#define the model, train it and save it
model = models.Sequential()
model.add(layers.Conv2D(32, (3,3), activation='relu', input_shape=(280, 400, 1)))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(64, (3,3), activation='relu')) #Convulotional layers filters images by their features (example: a cat has small legs)
model.add(layers.MaxPooling2D((2,2))) #Max Pooling layers filter the important information
model.add(layers.Conv2D(64, (3,3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(3, activation='softmax')) #Last layer
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(training_images, training_labels, epochs=10, validation_data=(test_images, test_labels))
loss, accuracy = model.evaluate(test_images, test_labels)
print(f"Loss: {loss}")
print(f"Accuracy: {accuracy}")
model.save('retina_disease_classifier.model')
def predictionModel(single_image):
model = models.load_model('retina_disease_classifier.model') #This loads an already trained model
class_names = ['Healthy', 'Glaucomatous', 'Diabetic Retinopathy']
img = cv.imread(single_image)
img = np.array([img]).reshape(-1, 280, 400, 1) / 255
prediction = model.predict(img)
index = np.argmax(prediction)
print(f"Prediction is {class_names[index]}")
Here is the code where I build the traning data, labels and test data:
from PIL import Image
from os import listdir
from os.path import isfile, join
from matplotlib import image
from matplotlib.pyplot import show
from numpy import asarray, single
import numpy as np
import sys
import logging
import gzip
import convNetwork
imageDatasetPath = "./Dataset/"
singleImagePath = "./Dataset/34761_dr.jpg"
imageLength = 400
imageHeigth = 280
imagePixelNum = imageLength * imageHeigth
def main():
training_images = createTrainingImages(imageDatasetPath)
training_labels = createTrainingLabels(imageDatasetPath)
test_images= createTrainingImages(imageDatasetPath)
test_labels = createTrainingLabels(imageDatasetPath)
#convNetwork.main(training_images, training_labels, test_images, test_labels)
convNetwork.main(training_images, training_labels, test_images, test_labels, single_image=singleImagePath)
def createTrainingImages(imageDatasetPath):
files = [f for f in listdir(imageDatasetPath) if isfile(join(imageDatasetPath, f))]
training_images = []
for fileName in files:
imagePath = imageDatasetPath + fileName
training_images.append(convertImageArray(imagePath))
training_images = np.array(training_images).reshape(-1, imageHeigth, imageLength, 1)
return training_images
def createTrainingLabels(imageDatasetPath):
files = [f for f in listdir(imageDatasetPath) if isfile(join(imageDatasetPath, f))]
training_labels = []
for fileName in files:
imagePath = imageDatasetPath + fileName
training_labels.append(getDiseaseType(fileName))
training_labels = np.reshape(training_labels, (len(training_labels), 1))
return training_labels
def convertImageArray(imagePath):
image = Image.open(imagePath)
# convert image to numpy array
data = asarray(image)
#data = np.reshape(data, (imagePixelNum, 1))
data = data / 255
return data
def getDiseaseType(imageName):
condition = imageName.split('.')[0]
condition = condition.split('_')[1]
if(condition == "h"):
return 0
elif(condition == "g"):
return 1
elif(condition == "dr"):
return 2
else:
logging.error("Invalid Input")
main()
This is the error that I get:
File "./convNetwork.py", line 76, in predictionModel
print(f"Prediction is {class_names[index]}")
IndexError: list index out of range
From what I understand the number of output neurons is defined in this way:
model.add(layers.Dense(3, activation='softmax'))
So, I dont understand how it is returning more outputs than the maximum defined.
I'm training a basic image classifier with seven classes, and I'm getting a Python error in Fit which I can't find other people talking about.
from keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense
from PIL import Image
import numpy as np
import os
imageSide = 256
def buildAndTrainNetwork():
classifier = Sequential()
classifier.add(Conv2D(32, (3, 3), input_shape = (imageSide, imageSide, 3), activation = 'relu', data_format="channels_last"))
classifier.add(MaxPooling2D(pool_size = (2, 2)))
classifier.add(Flatten())
classifier.add(Dense(units = 128, activation = 'relu'))
classifier.add(Dense(units = 7, activation = 'sigmoid'))
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
labelList = [('CarHatchback', [1,0,0,0,0,0,0]), ('CarMinivan', [0,1,0,0,0,0,0]), ('CarPickup', [0,0,1,0,0,0,0]), ('CarSaloon', [0,0,0,1,0,0,0]), ('CarSmart', [0,0,0,0,1,0,0]), ('CarSports', [0,0,0,0,0,1,0]), ('CarVan', [0,0,0,0,0,0,1])]
train_data = []
train_labels = []
test_data = []
for label,labelData in labelList:
dir = "mlData/train/" + label
for img in os.listdir(dir):
path = os.path.join(dir, img)
img = Image.open(path)
img = img.convert('RGB')
img = img.resize((imageSide, imageSide), Image.ANTIALIAS)
img = np.array(img)
train_data.append(img)
train_labels.append(labelData)
for label,labelData in labelList:
dir = "mlData/test/" + label
for img in os.listdir(dir):
path = os.path.join(dir, img)
img = Image.open(path)
img = img.convert('RGB')
img = img.resize((imageSide, imageSide), Image.ANTIALIAS)
img = np.array(img)
test_data.append(img)
train_data = np.array(train_data)
test_data = np.array(test_data)
train_labels = np.array(train_labels)
print("Training shape:")
print(train_data.shape)
print("Train labels shape:")
print(train_labels.shape)
print("Testing shape:")
print(test_data.shape)
classifier.fit(
train_data,
train_labels,
steps_per_epoch=8000,
epochs=10,
validation_data=test_data,
validation_steps=800
)
#
buildAndTrainNetwork()
The error I receive is:
File
"/home/ian/.local/lib/python3.6/site-packages/keras/engine/training.py",
line 1034, in fit
val_ins=val_ins, UnboundLocalError: local variable 'val_ins' referenced before assignment
FYI, the shape output is:
Training shape:
(3502, 256, 256, 3)
Train labels shape:
(3502, 7)
Testing shape:
(3506, 256, 256, 3)
I'm assuming that I haven't formatted the input data correctly, but I'm struggling to see the actual error.
validation_data in classifier.fit should be a tuple with the test images (which you have) and the test labels, which you have but forgot to load.
for label,labelData in labelList:
dir = "mlData/test/" + label
for img in os.listdir(dir):
# ...
test_data.append(img)
test_labels.append(labelData) # add this
Then
classifier.fit(
validation_data=(test_data, test_labels)
# ...
)
I have trained a CNN neural network in python with 800 samples and tested it on 60. The output accuracy is 50 and now every time I use model.predict it gives me the same result.
#main file - run this to train the network
import numpy as np
from keras.datasets import cifar10
from datasetFetch import DataFetch
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.constraints import maxnorm
from keras.optimizers import SGD
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.utils import np_utils
from keras import backend as K
K.set_image_dim_ordering('th')
import simplejson
from matplotlib import pyplot
from scipy.misc import toimage
# load data
#(X_train, y_train), (X_test, y_test) = cifar10.load_data()
# create a grid of 3x3 images
#for i in range(0, 9):
# pyplot.subplot(3,3,1 + i)
# pyplot.imshow(toimage(X_train[i]))
# show the plot
#pyplot.show()
#init data
CONST_PHOTOS = 400 # number of photos of each type
y_train = []
#train data
data = DataFetch('orange',CONST_PHOTOS)
data1 = data.openPictures()
data = DataFetch('apple', CONST_PHOTOS)
data.removeErrorImages()
data2 = data.openPictures()
#test data
tdata = DataFetch('test-orange',30)
tdata1 = tdata.openPictures()
tdata = DataFetch('test-apple',30)
tdata2 = tdata.openPictures()
#add togheter data
X_train = data.connectData(data1,data2,'train')
y_train = data.getYtrain('train')
X_test = tdata.connectData(tdata1,tdata2,'test')
y_test = tdata.getYtrain('test')
# fix random seed for reproducibility
seed = 7
np.random.seed(seed)
# normalize inputs from 0-255 to 0.0-1.0
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train = X_train / 255.0
X_test = X_test / 255.0
#one hot encode outputs
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_train.shape[1] #number of categories
# Create the model
model = Sequential()
model.add(Conv2D(224, (11, 11), input_shape=(224, 224, 3), activation='relu', padding='same'))
model.add(Dropout(0.2))
model.add(Conv2D(55, (5, 5), activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_last"))
model.add(Conv2D(13, (3, 3), activation='relu', padding='same'))
model.add(Dropout(0.5))
model.add(Conv2D(13, (3, 3), activation='relu', padding='same'))
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_last"))
model.add(Flatten())
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu', kernel_constraint=maxnorm(3)))
model.add(Dropout(0.2))
model.add(Dense(num_classes, activation='softmax'))
# Compile model
epochs = 100
lrate = 0.01
decay = lrate/epochs
sgd = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=False)
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])
#print(model.summary())
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=epochs, batch_size=10)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))
#and then we save
# serialize model to JSON
model_json = model.to_json()
with open("Data/model.json", "w") as json_file:
json_file.write(simplejson.dumps(simplejson.loads(model_json), indent=4))
# serialize weights to HDF5
model.save_weights("Data/model.h5")
print("Saved model to disk")
I used keras and tensorflow. Images are 224x224 pixels each split in 2 categories. I don't know very much about neural network, this being my first attempt to making one this big work. I heard it might be over fitting or maybe I need one more important layer, or maybe my batch-size/epochs/learn rate is wrong.
Any help is appreciated!
Edit1: How is the seed affecting the training of the network?
After training the accuracy is exactly 50% and by using a separate .py file which only loads the model and uses predict function on it returns the exact output percentage for any image I use. I tried with both images used for training and external ones.
I added the dataFetch code.
#preparing the photos to be 224x224 and getting them from urls saved in txt files
from PIL import Image
import requests
from io import BytesIO
import numpy as np
import socket
import random
from scipy import misc
from PIL import ImageChops
import math, operator
from functools import reduce
import glob
import os
import signal
compare = Image.open('/home/mihai/PycharmProjects/neuralnet/compare.jpg')
compare1 = Image.open('/home/mihai/PycharmProjects/neuralnet/compare1.jpg')
compare2 = Image.open('/home/mihai/PycharmProjects/neuralnet/compare2.jpg')
compare3 = Image.open('/home/mihai/PycharmProjects/neuralnet/compare3.jpg')
compare4 = Image.open('/home/mihai/PycharmProjects/neuralnet/compare4.jpg')
def rmsdiff(im1, im2):
"Calculate the root-mean-square difference between two images"
h = ImageChops.difference(im1, im2).histogram()
# calculate rms
return math.sqrt(reduce(operator.add, map(lambda h, i: h*(i**2), h, range(256))) / (float(im1.size[0]) * im1.size[1]))
class DataFetch:
chosenFile = ''
maxNumber = 0
y_train = []
y_test = []
def __init__(self, choice, number):
print('Images with '+choice+'s are being prepared')
self.chosenFile = choice
self.maxNumber = number
def getPictures(self):
imgArr = np.zeros((self.maxNumber, 224, 224, 3), dtype='uint8')
count = 0
class timeoutError(Exception):
signal.alarm(0)
def handler(signum, frame):
raise timeoutError
with open(self.chosenFile, "r") as ins:
for line in ins:
if count < self.maxNumber:
signal.signal(signal.SIGALRM, handler)
signal.alarm(3)
try:
try:
r = requests.get(line)
try:
img = Image.open(BytesIO(r.content))
ok = 0
try:
if rmsdiff(compare, img) > 1.3 and rmsdiff(compare1, img) > 1.3 and rmsdiff(compare2, img) > 1.3 and rmsdiff(compare3, img) > 1.3 and rmsdiff(compare4, img) > 1.3:
ok = 1
else:
print('Image removed from website')
except ValueError:
ok = 1
if ok == 1:
img = img.resize((224, 224))
img = img.convert('RGB')
img.save('/home/mihai/PycharmProjects/neuralnet/images/'+self.chosenFile+'/'+str(count)+".jpg", 'JPEG')
imgArr[count, :, :, :] = img
count = count + 1
print(count)
except OSError:
print('Image not Available')
except socket.error:
print('URL not available')
except timeoutError:
print("URL not available")
return imgArr
def openPictures(self):
cdir = os.getcwd()
imgArr = np.zeros((self.maxNumber, 224, 224, 3), dtype='uint8')
count = 0
for filename in glob.glob(cdir+'/images/'+self.chosenFile+'/*.jpg'):
if count < self.maxNumber:
img = Image.open(filename)
imgArr[count, :, :, :] = img
count = count + 1
return imgArr
def removeErrorImages(self):
cdir = os.getcwd()
for filename in glob.glob(cdir+'/images/'+self.chosenFile+'/*.jpg'):
img = Image.open(filename)
try:
if rmsdiff(compare, img) < 1.3 or rmsdiff(compare1, img) < 1.3 or rmsdiff(compare2, img) < 1.3 or rmsdiff(compare3, img) < 1.3 or rmsdiff(compare4, img) < 1.3:
os.remove(cdir+'/images/'+self.chosenFile+'/'+filename+'.jpg')
except ValueError:
pass
def getYtrain(self,outParam):
if outParam == 'train':
self.y_train = np.reshape(self.y_train, (len(self.y_train), 1))
return self.y_train
else:
self.y_test = np.reshape(self.y_test, (len(self.y_test), 1))
return self.y_test
def connectData(self, data1, data2, outParam):
d1c = 0
d2c = 0
outList = []
X_train = np.zeros((2 * self.maxNumber, 224, 224, 3), dtype='uint8')
for i in range(2 * self.maxNumber):
if d1c < self.maxNumber and d2c <self.maxNumber:
if random.random() <= 0.5:
X_train[d1c + d2c, :, :, :] = data1[d1c, :, :, :]
d1c = d1c + 1
outList.append(0)
else:
X_train[d1c + d2c, :, :, :] = data2[d2c, :, :, :]
d2c = d2c + 1
outList.append(1)
else:
if d1c < self.maxNumber:
X_train[d1c + d2c, :, :, :] = data1[d1c, :, :, :]
d1c = d1c + 1
outList.append(0)
else:
if d2c < self.maxNumber:
X_train[d1c + d2c, :, :, :] = data2[d2c, :, :, :]
d2c = d2c + 1
outList.append(1)
if outParam == 'train':
self.y_train = outList
else:
if outParam == 'test':
self.y_test = outList
return X_train
Code for predict:
#run this to test a sample
from keras.utils import np_utils
from keras.models import model_from_json
from keras.optimizers import SGD
from datasetFetch import DataFetch
# load json and create model
json_file = open('Data/model2.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)
# load weights into new model
loaded_model.load_weights("Data/model2.h5")
print("Loaded model from disk")
epochs = 100
lrate = 0.01
decay = lrate/epochs
sgd = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=False)
loaded_model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
#prepare X_test
tdata = DataFetch('test-orange',int(3))
tdata1 = tdata.openPictures()
tdata = DataFetch('test-apple',int(3))
tdata2 = tdata.openPictures()
X_test = tdata.connectData(tdata1,tdata2,'test')
y_test = tdata.getYtrain('test')
X_test = X_test.astype('float32')
X_test = X_test / 255.0
y_test = np_utils.to_categorical(y_test)
print('Number of samples to be tested: '+str(X_test.shape[0]))
scores = loaded_model.evaluate(X_test, y_test, verbose=0)
print(scores[1]*100)
score = loaded_model.predict(X_test,batch_size=6, verbose=1)
print(score) #prints percentages
The image preparation was correct. The problem was in the structure of the neural net plus the optimization method used.
Because of the huge number of neurons used for classifying just 2 classes, the structure was over fitting, causing the accuracy to stick at 50%.
The second problem was with the sgd optimizer. I instead used:
opt=keras.optimizers.rmsprop(lr=0.0001, decay=1e-6)
model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy']
Hope this helps others as well!