Detecting multiply forms on one image - python

I made a convolutional neural network, have trained the model, and now it can accurately determine the form that is on the photo.
But now I need to make sure that it determines all the forms that are in one photo. So I need to somehow cut the original photo into parts, and then identify each.
What is the best way to do it? I am using Python3, keras. Learning and recognition code:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import argparse
import random
import pickle
import cv2
import os
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from keras.models import Sequential
from keras.layers.core import Dense, Flatten
from keras.layers import Dropout
from keras.layers import Conv2D, MaxPooling2D
from keras.utils import to_categorical
from keras.optimizers import SGD
from keras.models import load_model
from imutils import paths
matplotlib.use ("Agg")
categories = ['bread', 'chicken', 'cucumbers', 'dry_peas', 'eggs',
              'green_peas', 'kolbasa', 'potato', 'raw_beef',
              'spaghetti', 'tomatoes']
dataset = "ingredients"
model_path = "test_model.model"
label_bin = "test_model.pickle"
plot = "output / test_model_plot.png"
print ("[INFO] loading images ...")
data = []
labels = []
imagePaths = sorted (list (paths.list_images (dataset)))
random.seed (42)
random.shuffle (imagePaths)
for imagePath in imagePaths:
    try:
        image = cv2.imread (imagePath)
        image = cv2.resize (image, (32, 32))
        data.append (image / 255)
        label = imagePath.split (os.path.sep) [- 2]
        labels.append (categories.index (label))
    except Exception as e:
        print ("[WARNING]", e)
data = np.array (data)
print (labels)
labels = to_categorical (np.array (labels))
print (labels)
(trainX, testX, trainY, testY) = train_test_split (data, labels,
                                                  test_size = 0.2,
                                                  random_state = 42)
lb = LabelBinarizer ()
trainY = lb.fit_transform (trainY)
testY = lb.transform (testY)
'' '
model = Sequential ()
model.add (Conv2D (32, (3, 3), activation = 'relu', input_shape = (32, 32, 3)))
model.add (MaxPooling2D ((2, 2)))
model.add (Conv2D (64, (3, 3), activation = 'relu'))
model.add (MaxPooling2D ((2, 2)))
model.add (Flatten ())
model.add (Dropout (0.5))
model.add (Dense (512, activation = "sigmoid"))
model.add (Dense (len (lb.classes_), activation = "softmax"))
'' '
model = load_model ('test_model.model')
INIT_LR = 0.01
EPOCHS = 150
print ("[INFO] training network ...")
opt = SGD (lr = INIT_LR)
model.compile (loss = "categorical_crossentropy", optimizer = opt,
              metrics = ["accuracy"])
H = model.fit (trainX, trainY, validation_data = (testX, testY),
              epochs = EPOCHS, batch_size = 32)
print ("[INFO] evaluating network ...")
predictions = model.predict (testX, batch_size = 32)
print (predictions)
#print (classification_report (testY.argmax (axis = 1)
# predictions.argmax (axis = 1), target_names = lb.classes_))
N = np.arange (0, EPOCHS)
plt.style.use ("ggplot")
plt.figure ()
print (H.history.keys ())
plt.plot (N, H.history ["loss"], label = "train_loss")
plt.plot (N, H.history ["val_loss"], label = "val_loss")
plt.plot (N, H.history ["accuracy"], label = "train_acc")
plt.plot (N, H.history ["val_accuracy"], label = "val_acc")
plt.title ("Training Loss and Accuracy (Simple NN)")
plt.xlabel ("Epoch #")
plt.ylabel ("Loss / Accuracy")
plt.legend ()
plt.savefig (plot)
print ("[INFO] serializing network and label binarizer ...")
model.save (model_path)
f = open (label_bin, "wb")
f.write (pickle.dumps (lb))
f.close ()
and
import argparse
import pickle
import cv2
import flask
import werkzeug
from keras.models import load_model
import keras
import tensorflow as tf
import keras.backend.tensorflow_backend as tb
from tensorflow.python.keras.backend import set_session
from tensorflow.python.keras.models import load_model
import sys
sys.modules['keras'] = keras
class FoodRecognizer:
def __init__(self, model, label_bin, size, flatten):
self.label_bin = label_bin
self.size = size
self.width, self.height = self.size
self.flatten = flatten
print("[INFO] loading network and label binarizer...")
set_session(sess)
self.model = load_model(model)
self.lb = pickle.loads(open(self.label_bin, "rb").read())
def load_image(self, image_file):
image = cv2.imread(image_file)
output = image.copy()
image = cv2.resize(image, self.size)
image = image / 255.0
image = image.reshape(1, *image.shape)
self.image = image
def recognize(self):
preds = self.model.predict(self.image)
result = list(preds[0])
for i in range(len(result)):
print(categories[i].ljust(10, " "), result[i], sep='\t')
i = preds.argmax(axis=1)[0]
print()
out = sorted(result)[-3:][::-1]
print("Скорее всего, на фотографии:")
for o in out:
print(categories[result.index(o)], f"{round(o * 100, 2)}%")
label = self.lb.classes_[i]
return label
app = flask.Flask(__name__)
#app.route('/', methods=['POST'])
def handle_request():
print(flask.request.files.to_dict())
imagefile = flask.request.files['image']
filename = werkzeug.utils.secure_filename(imagefile.filename)
print("\nReceived image File name : " + imagefile.filename)
imagefile.save('images/' + str(filename))
MFR.load_image('images/' + filename)
print(MFR.image)
print('images/' + filename)
with graph.as_default():
set_session(sess)
result = MFR.recognize()
print(result)
return categories[result]
categories = ['bread', 'chicken', 'cucumbers', 'dry_peas', 'eggs',
'green_peas', 'kolbasa', 'potato', 'raw_beef',
'spaghetti', 'tomatoes']
if __name__ == "__main__":
model_path = "test_model.model"
label_path = "test_model.pickle"
size = (32, 32)
flatten = 1
sess = tf.Session()
graph = tf.get_default_graph()
MFR = FoodRecognizer(model_path, label_path, size, flatten)
#MFR.load_image("images/test_image.jpg")
#print(categories[MFR.recognize()])
set_session(sess)
app.run(host='10.61.4.238', debug=True, threaded=False)

I think you are refering to image segmentation, check out this article to find out more information.
In short, it is similar to classification but instead of giving one class it draws bounding boxes around the detected objects.

Related

TypeError: only integer scalar arrays can be converted to a scalar index (python)

i tried to create a python script for detect the object in a picture and return the similar images, but it return always an error:
TypeError: only integer scalar arrays can be converted to a scalar index
the ids : is the matrix returned after the detection; and it returned perfectly
but the problem is only in the last line: scores = [img_paths[id] for id in ids].
My code :
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.vgg16 import VGG16, preprocess_input
from tensorflow.keras.models import Model
import numpy as np
from PIL import Image
#from feature_extractor import FeatureExtractor
from datetime import datetime
from flask import Flask, request, render_template
from pathlib import Path
from keras.optimizers import Adam
from tensorflow.keras.layers import Dropout, Dense, Activation, Flatten
class FeatureExtractor:
def __init__(self):
input_shape = (224, 224, 3)
base_model = VGG16(weights='imagenet', include_top=False, input_shape=input_shape)
for layer in base_model.layers:
layer.trainable = False
last = base_model.layers[-1].output
x = Flatten()(last)
x = Dense(1000, activation='relu', name='fc1')(x)
x = Dropout(0.3)(x)
x = Dense(10, activation='softmax', name='predictions')(x)
model = Model(base_model.input, x)
model.compile(optimizer=Adam(lr=0.001),
loss = 'categorical_crossentropy',metrics=['accuracy'])
self.model = Model(inputs=base_model.input, outputs=base_model.layers[-1].output)
def extract(self, img):
"""
Extract a deep feature from an input image
Args:
img: from PIL.Image.open(path) or tensorflow.keras.preprocessing.image.load_img(path)
Returns:
feature (np.ndarray): deep feature with the shape=(4096, )
"""
img = img.resize((224, 224)) # VGG must take a 224x224 img as an input
img = img.convert('RGB') # Make sure img is color
x = image.img_to_array(img) # To np.array. Height x Width x Channel. dtype=float32
x = np.expand_dims(x, axis=0) # (H, W, C)->(1, H, W, C), where the first elem is the number of img
x = preprocess_input(x) # Subtracting avg values for each pixel
feature = self.model.predict(x)[0] # (1, 4096) -> (4096, )
return feature / np.linalg.norm(feature) # Normalize
path = "/home/virtuag/www/storage/searchSCB.jpg"
img = Image.open(path)
app = Flask(__name__)
fe = FeatureExtractor()
features = []
img_paths = []
for feature_path in Path("/home/virtuag/www/storage/images_article").glob("*.npy"):
features.append(np.load(feature_path))
img_paths.append(Path("/home/virtuag/www/storage/images_article") / (feature_path.stem + ".jpg"))
features = np.array(features)
query = fe.extract(img)
dists = np.linalg.norm(features-query, axis=1)
ids = np.argsort(dists)[:30]
scores = [img_paths[id] for id in ids]

python : keras package : (ValueError: No such layer: fc1)

when i tryed to execute my python code, i get this error: (ValueError: No such layer: fc1) : error capture
i use in my code TensorFlow and Keras package to detect Object in image and return the similar images from custom Dataset.
it s work perfectly on local, but when i trayed in the server OVH there is always the error
(i trayed to change the layer to 'block5_pool' but it's not working with my code.)
my code :
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.vgg16 import VGG16, preprocess_input
from tensorflow.keras.models import Model
import numpy as np
from PIL import Image
from datetime import datetime
from flask import Flask, request, render_template
from pathlib import Path
class FeatureExtractor:
def __init__(self):
base_model = VGG16(weights='imagenet', include_top=False)
self.model = Model(inputs=base_model.input, outputs=base_model.get_layer('fc1').output)
def extract(self, img):
"""
Extract a deep feature from an input image
Args:
img: from PIL.Image.open(path) or tensorflow.keras.preprocessing.image.load_img(path)
Returns:
feature (np.ndarray): deep feature with the shape=(4096, )
"""
img = img.resize((224, 224))
img = img.convert('RGB')
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
feature = self.model.predict(x)[0]
return feature / np.linalg.norm(feature)
path = "/home/virtuag/www/storage/searchSCB.jpg"
img = Image.open(path)
app = Flask(__name__)
fe = FeatureExtractor()
features = []
img_paths = []
for feature_path in Path("/home/virtuag/www/storage/images_article").glob("*.npy"):
features.append(np.load(feature_path))
img_paths.append(Path("/home/virtuag/www/storage/images_article") / (feature_path.stem + ".jpg"))
features = np.array(features)
query = fe.extract(img)
dists = np.linalg.norm(features-query, axis=1) # L2 distances to features
ids = np.argsort(dists)[:30] # Top 30 results
scores = [img_paths[id] for id in ids]
print (scores)```
thank you
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.vgg16 import VGG16, preprocess_input
from tensorflow.keras.models import Model
import numpy as np
from PIL import Image
#from feature_extractor import FeatureExtractor
from datetime import datetime
from flask import Flask, request, render_template
from pathlib import Path
from keras.optimizers import Adam
from tensorflow.keras.layers import Dropout, Dense, Activation, Flatten
class FeatureExtractor:
def __init__(self):
input_shape = (224, 224, 3)
base_model = VGG16(weights='imagenet', include_top=False, input_shape=input_shape)
for layer in base_model.layers:
layer.trainable = False
last = base_model.layers[-1].output
x = Flatten()(last)
x = Dense(1000, activation='relu', name='fc1')(x)
x = Dropout(0.3)(x)
x = Dense(10, activation='softmax', name='predictions')(x)
model = Model(base_model.input, x)
model.compile(optimizer=Adam(lr=0.001),
loss = 'categorical_crossentropy',metrics=['accuracy'])
self.model = Model(inputs=base_model.input, outputs=base_model.layers[-1].output)
def extract(self, img):
"""
Extract a deep feature from an input image
Args:
img: from PIL.Image.open(path) or tensorflow.keras.preprocessing.image.load_img(path)
Returns:
feature (np.ndarray): deep feature with the shape=(4096, )
"""
img = img.resize((224, 224))
img = img.convert('RGB')
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
feature = self.model.predict(x)[0]
return feature / np.linalg.norm(feature)
path = "/home/virtuag/www/storage/searchSCB.jpg"
#path = "c:/xamppp/htdocs/projet/V-stock/PWA/public/storage/searchSCB.jpg"
img = Image.open(path)
app = Flask(__name__)
fe = FeatureExtractor()
features = []
img_paths = []
for feature_path in Path("/home/virtuag/www/storage/images_article").glob("*.npy"):
#for feature_path in Path("c:/xamppp/htdocs/projet/V-stock/PWA/public/storage/images_article").glob("*.npy"):
features.append(np.load(feature_path))
#img_paths.append(Path("c:/xamppp/htdocs/projet/V-stock/PWA/public/storage/images_article") / (feature_path.stem + ".jpg"))
img_paths.append(Path("/home/virtuag/www/storage/images_article") / (feature_path.stem + ".jpg"))
features = np.array(features)
query = fe.extract(img)
dists = np.linalg.norm(features-query, axis=1)
ids = np.argsort(dists)[:30]
scores = [img_paths[id] for id in ids]
#print (img_paths)
#print(query)
and the error :
raceback (most recent call last): File "server.py", line 71, in <module> scores = [img_paths[id] for id in ids] File "server.py", line 71, in <listcomp> scores = [img_paths[id] for id in ids] TypeError: only integer scalar arrays can be converted to a scalar index

keras model.predict IndexError: list index out of range

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.

Keras: "local variable 'val_ins' referenced before assignment"

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)
# ...
)

keras CNN same output

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!

Categories