Image Classification Fine-Tuning With EfficientNet - python

I'm trying to image classify with Keras Efficient Net. like here https://keras.io/examples/vision/image_classification_efficientnet_fine_tuning/ I have two folder named 1 and 0. The number of images in both folders is the same. F1 score is generated only for 0 class in sklearn report results. f1-score for class 1 is always 0. classifies everything as 0. How can I fix ? I would love any help.
both folders contain 62 images.
UPDATE:
I also tried with 500 images for each class and for 1 folder the results are still 0.
UPDATE
#----TF
import tensorflow as tf
from keras.utils import to_categorical
from tensorflow.python.data import AUTOTUNE
from keras.models import load_model
from keras import layers
from keras.applications import EfficientNetB0
from keras.callbacks import EarlyStopping, ModelCheckpoint
from keras.optimizers import SGD
from keras.applications import imagenet_utils
#---SK
from sklearn.metrics import classification_report
#
import imutils
from imutils import paths
import random
import cv2
import os
import numpy as np
import pandas as pd
import shutil
import matplotlib.pyplot as plt
main_path = 'C:\\Users\\A\\Desktop\\data\\'
all_images = list(paths.list_images(main_path))
#Bazi resimleri kontrol etme
random_images = random.choices(all_images, k=3)
for i in random_images:
random_image = cv2.imread(i)
random_images = cv2.cvtColor(random_image, cv2.COLOR_BGR2RGB)
random_image = imutils.resize(random_image, height=400)
cv2.imshow("example", random_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
random.shuffle(all_images)
i = int(len(all_images)*0.8) #%80
trainData = all_images[:i]
testData = all_images[i:]
#validation data
i = int(len(trainData)*0.10) #%10
validData = trainData[:i]
trainData = trainData[i:]
train_path = main_path+'training'
test_path = main_path+'test'
valid_path = main_path+'valid'
datasets = [("training", trainData, train_path ), ("validation", validData, valid_path), ("testing", testData, test_path)]
for (dtype, imagepaths, out_path) in datasets:
if not os.path.exists(out_path):
os.makedirs(out_path)
for inputpath in imagepaths:
filename = inputpath.split(os.path.sep)[-1]
label = inputpath.split(os.path.sep)[-2]
labelPath = os.path.sep.join([out_path, label])
if not os.path.exists(labelPath):
os.makedirs(labelPath) # onceden tanimlanan klasor
#goruntu alinir ve label klasorune kopyalanir
p = os.path.sep.join([labelPath, filename])
shutil.copy2(inputpath, p)
#3- tf.data() pipeline dagitma
def load_images(imagePath):
# --images
image = tf.io.read_file(imagePath)
image = tf.io.decode_jpeg(image, channels=3)
image = tf.image.resize(image, (150, 150)) / 255.0
# --labels
label = tf.strings.split(imagePath, os.path.sep)[-2]
label = tf.strings.to_number(label, tf.int32)
print(label)
return (image, label)
def augment(image, label):
image = tf.image.random_flip_up_down(image)
image = tf.image.random_flip_left_right(image)
image = tf.image.random_brightness(image,0.2) # data augmentation
return (image, label)
trainPaths = list(paths.list_images(train_path))
valPaths = list(paths.list_images(valid_path))
testPaths = list(paths.list_images(test_path))
trainDS = tf.data.Dataset.from_tensor_slices(trainPaths)
trainDS = (trainDS.shuffle(len(trainPaths)).map(load_images, num_parallel_calls=AUTOTUNE).map(augment,num_parallel_calls=AUTOTUNE).cache().batch(16).prefetch(AUTOTUNE))
# --validation
valDS = tf.data.Dataset.from_tensor_slices(valPaths)
valDS = (valDS.map(load_images, num_parallel_calls=AUTOTUNE).cache().batch(16).prefetch(AUTOTUNE))
# --Test
testDS = tf.data.Dataset.from_tensor_slices(testPaths)
testDS = (testDS.map(load_images, num_parallel_calls=AUTOTUNE).cache().batch(16).prefetch(AUTOTUNE))
NUM_CLASSES = 2
IMG_SIZE = 150
size = (IMG_SIZE, IMG_SIZE,3)
inputs = layers.Input(shape=(IMG_SIZE, IMG_SIZE, 3))
model = EfficientNetB0(include_top=False, input_shape=size)
flat1 = layers.Flatten()(model.layers[-1].output)
class1 = layers.Dense(1024, activation='relu')(flat1)
output = layers.Dense(1, activation='sigmoid')(class1)
model = tf.keras.Model(inputs=model.inputs, outputs=output)
model.summary()
# model = EfficientNetB0(include_top=False, input_shape=size)
# for layer in model.layers:
# layer.trainable = False
opt = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=["accuracy"])
early_s = EarlyStopping(monitor="val_loss", patience = 10, restore_best_weights=True)
save_b = ModelCheckpoint(filepath ="C:\\Users\\A\\Desktop\\Gun\\", monitor="val_loss", verbose = 1 )
callbacks = [early_s, save_b]
hist = model.fit(x = trainDS, validation_data=valDS, epochs= 50, callbacks=callbacks, verbose=1)
plt.figure()
plt.plot(hist.history["loss"], label="train_loss")
plt.plot(hist.history["val_loss"], label="val_loss")
plt.plot(hist.history["accuracy"], label="train_acc")
plt.plot(hist.history["val_accuracy"], label="val_acc")
plt.title("training loss and accuracy")
plt.xlabel("Epoch #")
plt.ylabel("loss/accuracy")
plt.legend(loc="lower left")
plt.show()
#test setinin etiketleri
test_paths = list(paths.list_images(test_path))
testlabels = [int(p.split(os.path.sep)[-2]) for p in test_paths]
testlabels = to_categorical(testlabels)
predictions = model.predict(testDS)
print(classification_report(testlabels.argmax(axis=1), predictions.argmax(axis=1), target_names=["0", "1"]))
UPDATE REPORT

Related

How to perform super pixel image segmentation and feature extraction

I am interested in multi class segmentation of skin tissues, I have 3000 skin tissue labels classified into 4 classes, I have created a CNN classification algorithm to train my classification model. I would like to use the classification model for segmentation task of new skin tissue image and perform feature extraction of the skin tissue belonging to each of the class
Following is the code that is written to train my classification model
from tensorflow.keras.layers import Input, Concatenate, Dropout, Flatten, Dense, GlobalAveragePooling2D, Conv2D
from tensorflow.keras import backend as K
#from tensorflow.keras.utils import np_utils
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import optimizers
from tensorflow.keras.metrics import top_k_categorical_accuracy
from tensorflow.keras.models import Sequential, Model, load_model
import tensorflow as tf
from tensorflow.keras.initializers import he_uniform
from tensorflow.keras.callbacks import ModelCheckpoint, LearningRateScheduler, TensorBoard, EarlyStopping, CSVLogger, ReduceLROnPlateau
#from tensorflow.compat.keras.backend import KTF
#import keras.backend.tensorflow_backend as KTF
from tensorflow.keras.applications.resnet50 import ResNet50
from tensorflow.keras.applications.inception_v3 import InceptionV3
import os
import matplotlib.pylab as plt
import numpy as np
import pandas as pd
#import numpy as np, Pillow, skimage, imageio, matplotlib
#from scipy.misc import imresize
from skimage.transform import resize
from tqdm import tqdm
from tensorflow.keras import metrics
#### PREPROCESS STAGE ####
# Path to superpixels class files
classes_file = "/home/DEV/SKIN_3000_CLASSES.csv"
concatenated_data= pd.read_csv(classes_file, header=None)
# Instances with targets
targets = concatenated_data[1].tolist()
# Split data according to their classes
class_0 = concatenated_data[concatenated_data[1] == 0]
class_1 = concatenated_data[concatenated_data[1] == 1]
class_2 = concatenated_data[concatenated_data[1] == 2]
class_3 = concatenated_data[concatenated_data[1] == 3]
# Holdout split train/test set (Other options are k-folds or leave-one-out)
split_proportion = 0.8
split_size_0 = int(len(class_0)*split_proportion)
split_size_1 = int(len(class_1)*split_proportion)
split_size_2 = int(len(class_2)*split_proportion)
split_size_3 = int(len(class_3)*split_proportion)
new_class_0_train = np.random.choice(len(class_0), split_size_0, replace=False)
new_class_0_train = class_0.iloc[new_class_0_train]
new_class_0_test = ~class_0.iloc[:][0].isin(new_class_0_train.iloc[:][0])
new_class_0_test = class_0[new_class_0_test]
new_class_1_train = np.random.choice(len(class_1), split_size_1, replace=False)
new_class_1_train = class_1.iloc[new_class_1_train]
new_class_1_test = ~class_1.iloc[:][0].isin(new_class_1_train.iloc[:][0])
new_class_1_test = class_1[new_class_1_test]
new_class_2_train = np.random.choice(len(class_2), split_size_2, replace=False)
new_class_2_train = class_2.iloc[new_class_2_train]
new_class_2_test = ~class_2.iloc[:][0].isin(new_class_2_train.iloc[:][0])
new_class_2_test = class_2[new_class_2_test]
new_class_3_train = np.random.choice(len(class_3), split_size_3, replace=False)
new_class_3_train = class_3.iloc[new_class_3_train]
new_class_3_test = ~class_3.iloc[:][0].isin(new_class_3_train.iloc[:][0])
new_class_3_test = class_3[new_class_3_test]
x_train_list = pd.concat(
[new_class_0_train, new_class_1_train, new_class_2_train, new_class_3_train])
x_test_list = pd.concat(
[new_class_0_test, new_class_1_test, new_class_2_test, new_class_3_test])
# Load superpixels files
imagePath = "/home/DEV/SKIN_SET_3000/"
x_train = []
y_train = []
for index, row in tqdm(x_train_list.iterrows(), total=x_train_list.shape[0]):
try:
loadedImage = plt.imread(imagePath + str(row[0]) + ".jpg")
x_train.append(loadedImage)
y_train.append(row[1])
except:
# Try with .png file format if images are not properly loaded
try:
loadedImage = plt.imread(imagePath + str(row[0]) + ".png")
x_train.append(loadedImage)
y_train.append(row[1])
except:
# Print file names whenever it is impossible to load image files
print(imagePath + str(row[0]))
x_test = []
y_test = []
for index, row in tqdm(x_test_list.iterrows(), total=x_test_list.shape[0]):
try:
loadedImage = plt.imread(imagePath + str(row[0]) + ".jpg")
x_test.append(loadedImage)
y_test.append(row[1])
except:
# Try with .png file format if images are not properly loaded
try:
loadedImage = plt.imread(imagePath + str(row[0]) + ".png")
x_test.append(loadedImage)
y_test.append(row[1])
except:
# Print file names whenever it is impossible to load image files
print(imagePath + str(row[0]))
# Reescaling of images
img_width, img_height = 139, 139
index = 0
for image in tqdm(x_train):
#aux = resize(image, (img_width, img_height, 3), "bilinear")
aux = resize(image, (img_width, img_height))
x_train[index] = aux / 255.0 # Normalization
index += 1
index = 0
for image in tqdm(x_test):
#aux = resize(image, (img_width, img_height, 3), "bilinear")
aux = resize(image, (img_width, img_height))
x_test[index] = aux / 255.0 # Normalization
index += 1
#### TRAINING STAGE ####
os.environ["KERAS_BACKEND"] = "tensorflow"
RANDOM_STATE = 42
def get_session(gpu_fraction=0.8):
num_threads = os.environ.get('OMP_NUM_THREADS')
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=gpu_fraction)
if num_threads:
return tf.Session(config=tf.ConfigProto(
gpu_options=gpu_options, intra_op_parallelism_threads=num_threads))
else:
return tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
#KTF.set_session(get_session())
def precision(y_true, y_pred):
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
precision = true_positives / (predicted_positives + K.epsilon())
return precision
def recall(y_true, y_pred):
true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
recall = true_positives / (possible_positives + K.epsilon())
return recall
def fbeta_score(y_true, y_pred, beta=1):
if beta < 0:
raise ValueError('The lowest choosable beta is zero (only precision).')
# Set F-score as 0 if there are no true positives (sklearn-like).
if K.sum(K.round(K.clip(y_true, 0, 1))) == 0:
return 0.0
p = precision(y_true, y_pred)
r = recall(y_true, y_pred)
bb = beta ** 2
fbeta_score = (1 + bb) * (p * r) / (bb * p + r + K.epsilon())
return fbeta_score
nb_classes = 4
final_model = []
# Option = InceptionV3
model = InceptionV3(weights="imagenet", include_top=False,
input_shape=(img_width, img_height, 3))
# Option = ResNet
# model = ResNet50(weights="imagenet", include_top=False, input_shape=(3,img_width, img_height))
# Creating new outputs for the model
x = model.output
x = Flatten()(x)
x = Dense(512, activation="relu")(x)
x = Dropout(0.5)(x)
x = Dense(512, activation="relu")(x)
x = Dropout(0.5)(x)
predictions = Dense(nb_classes, activation='softmax')(x)
#predictions = Dense(nb_classes, activation='sigmoid')(x)
final_model = Model(inputs=model.input, outputs=predictions)
# Metrics
learningRate = 0.001
optimizer = optimizers.SGD(learning_rate=learningRate, momentum=0.88, nesterov=True)
# Compiling the model...
final_model.compile(loss="categorical_crossentropy", optimizer=optimizer,
metrics=["accuracy", fbeta_score])
final_model.summary()
#final_model.compile(loss = 'categorical_crossentropy', optimizer = 'adam', metrics = ['accuracy'])
#model.compile(loss = 'sparse_categorical_crossentropy', optimizer = 'adam', metrics = ['accuracy'])
#x_train = np.array(x_train)
#x_test = np.array(x_test)
x_train = np.asarray(x_train).astype(np.float32)
#x_test = np.array(x_test)
x_test = np.asarray(x_test).astype(np.float32)
# Defining targets...
y_train = np.concatenate([np.full((new_class_0_train.shape[0]), 0), np.full((new_class_1_train.shape[0]), 1),
np.full((new_class_2_train.shape[0]), 2), np.full((new_class_3_train.shape[0]), 3)])
y_test = np.concatenate([np.full((new_class_0_test.shape[0]), 0), np.full((new_class_1_test.shape[0]), 1),
np.full((new_class_2_test.shape[0]), 2), np.full((new_class_3_test.shape[0]), 3)])
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
modelFilename = "/home/DEV/SKIN_SET_3000/model_inception.h5"
trainingFilename = "/home/DEV/SKIN_SET_3000/training.csv"
nb_train_samples = y_train.shape[0]
nb_test_samples = y_test.shape[0]
#epochs = 10000
epochs = 100
batch_size = 24
trainingPatience = 200
decayPatience = trainingPatience / 4
# Setting the data generator...
train_datagen = ImageDataGenerator(
horizontal_flip=True,
fill_mode="reflect",
zoom_range=0.2
)
train_generator = train_datagen.flow(x_train, y_train, batch_size=batch_size)
# Saving the model
checkpoint = ModelCheckpoint(modelFilename,
monitor='val_accuracy',
verbose=1,
save_best_only=True,
save_weights_only=False,
mode='auto',
save_freq=1)
adaptativeLearningRate = ReduceLROnPlateau(monitor='val_accuracy',
factor=0.5,
patience=decayPatience,
verbose=1,
mode='auto',
min_delta=0.0001,
cooldown=0,
min_lr=1e-8)
early = EarlyStopping(monitor='val_accuracy',
min_delta=0,
patience=trainingPatience,
verbose=1,
mode='auto')
csv_logger = CSVLogger(trainingFilename, separator=",", append=False)
# Callbacks
callbacks = [checkpoint, early, csv_logger, adaptativeLearningRate]
# Training of the model
final_model.fit(train_generator,
steps_per_epoch=nb_train_samples / batch_size,
epochs=epochs,
shuffle=True,
validation_data=(x_test, y_test),
validation_steps=nb_test_samples / batch_size,
callbacks=callbacks)
final_model.save('/home/DEV/SKIN_SET_3000/model_inception.h5')
#compile metrics
In order to segment my image, first i have transformed my input image to super pixel using SLIC
from skimage.segmentation import slic
from skimage.segmentation import mark_boundaries
from skimage.util import img_as_float
from skimage import io; io.use_plugin('matplotlib')
import cv2 as cv
from skimage.color import label2rgb
img_width, img_height = 139, 139
# load the model we saved
model = load_model('/home/DEV/SKIN_SET_3000/model_inception.h5', compile=False)
# Get test image ready
img = skimage.img_as_float(skimage.io.imread('/home/DEV/SKIN_ULCER.jpg')).astype(np.float32)
plt.imshow(img)
test_image_slic = slic(img, n_segments=500, compactness=10.0)
test_image_slic_out = mark_boundaries(img,test_image_slic)
plt.imshow(test_image_slic_out)
#test_image=test_image/255
test_image_array = np.array(test_image_slic_out)
test_image_resize = cv2.resize(test_image_array,(img_width,img_height))
test_image_reshape = test_image_resize.reshape(1,img_width, img_height,3)
I would like to check if each superpixel of my input is labeled as one of my target class among 4 tissue classes, and extract the features belonging to each class as a mask and quantify the total surface area of mask .
any suggestions of how to implement this approach would be appreciated.

Transfer learning using keras

I am trying to classify the medical images taken from publicly available datasets. I used transfer learning for this task. Initially, when I had used the following code on the same dataset with VGG, Resnet, Densenet, and Inception, the accuracy was above 85% without fine-tuning (TensorFlow version 1.15.2.) Now, after upgrading the TensorFlow to 2.x, when I try the same code on the same dataset, the accuracy is never crossing 32%. Can anyone please help me rectify the issue? Is it something to do with the TensorFlow version or something else? I have tried varying the learning rate, fine-tuning the model, etc. Is this the issue with batch normalization error in Keras?
import os
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "2"
import sys
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras.applications.resnet50 import ResNet50, preprocess_input
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.applications.densenet import DenseNet121
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.applications.inception_v3 import InceptionV3
import cv2
import glob
from tensorflow.keras.layers import Input, Dense, Flatten, Conv2D, MaxPooling2D, Dropout
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
import tensorflow.keras as keras
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping
import numpy as np
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
from keras import backend as k
from mlxtend.evaluate import confusion_matrix
from mlxtend.plotting import plot_confusion_matrix
import math
import pandas as pd
from openpyxl import load_workbook
save_dir = '../new_tran/'
def extract_outputs(cnf_matrix, mdl_name):
cnf_matrix_T=np.transpose(cnf_matrix)
recall = np.diag(cnf_matrix) / np.sum(cnf_matrix, axis = 1)
precision = np.diag(cnf_matrix) / np.sum(cnf_matrix, axis = 0)
n_class=3
TP=np.zeros(n_class)
FN=np.zeros(n_class)
FP=np.zeros(n_class)
TN=np.zeros(n_class)
for i in range(n_class):
TP[i]=cnf_matrix[i,i]
FN[i]=np.sum(cnf_matrix[i])-cnf_matrix[i,i]
FP[i]=np.sum(cnf_matrix_T[i])-cnf_matrix[i,i]
TN[i]=np.sum(cnf_matrix)-TP[i]-FP[i]-FN[i]
P=TP+FN
N=FP+TN
classwise_sensitivity=np.true_divide(TP,P)
classwise_specificity=np.true_divide(TN,N)
classwise_accuracy=np.true_divide((TP+TN), (P+N))
OS=np.mean(classwise_sensitivity)
OSp=np.mean(classwise_specificity)
OA=np.sum(np.true_divide(TP,(P+N)))
Px=np.sum(P)
TPx=np.sum(TP)
FPx=np.sum(FP)
TNx=np.sum(TN)
FNx=np.sum(FN)
Nx=np.sum(N)
pox=OA
pex=((Px*(TPx+FPx))+(Nx*(FNx+TNx)))/(math.pow((TPx+TNx+FPx+FNx),2))
kappa_overall=[np.true_divide(( pox-pex ), ( 1-pex )),np.true_divide(( pex-pox ), ( 1-pox ))]
kappa=np.max(kappa_overall)
Rcl=np.mean(recall)
Prcn=np.mean(precision)
#######--------------------- Print all scores
print('classwise_sen',classwise_sensitivity*100)
print('classwise_spec',classwise_specificity*100)
print('classwise_acc',classwise_accuracy*100)
print('overall_sen',OS*100)
print('overall_spec',OSp*100)
print('overall_acc',OA*100)
print('overall recall', Rcl)
print('overall precision',Prcn)
f1score=(2 * Prcn * Rcl) / (Prcn + Rcl)
print('overall F1-score',f1score )
print('Kappa',kappa)
def preProcess(X):
X = X.astype('float32')
# scale from [0,255] to [-1,1]
X = (X - 127.5) / 127.5
return X
train_datagen = ImageDataGenerator(preprocessing_function=preProcess)
test_datagen = ImageDataGenerator(preprocessing_function=preProcess)
IMG_SIZE = 256
batch_size = 16
train_data_dir = '../data/train/'
test_dir = '../data/test/'
val_dir = '../data/val/'
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(IMG_SIZE , IMG_SIZE),
batch_size=16,
class_mode='sparse')
valid_generator = train_datagen.flow_from_directory(
val_dir,
target_size=(IMG_SIZE , IMG_SIZE),
batch_size=16,
class_mode='sparse')
test_generator = train_datagen.flow_from_directory(
test_dir,
target_size=(IMG_SIZE , IMG_SIZE),
batch_size=16,
class_mode='sparse')
test_im=np.concatenate([test_generator.next()[0] for i in range(test_generator.__len__())])
test_lb=np.concatenate([test_generator.next()[1] for i in range(test_generator.__len__())])
t_x, t_y = next(train_generator)
checkpoint1 = ModelCheckpoint(save_dir+"best_res.hdf5", monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')
checkpoint2 = EarlyStopping(monitor='val_loss', patience=10, verbose=0, mode='min')
callbacks_list1 = [checkpoint1, checkpoint2]
def new_model():
img_in = Input(t_x.shape[1:])
model = DenseNet121(include_top= False ,
layers=tf.keras.layers,
weights='imagenet',
input_tensor= img_in,
input_shape= t_x.shape[1:],
pooling ='avg')
x = model.output
predictions = Dense(3, activation="softmax", name="predictions")(x)
model = Model(inputs=img_in, outputs=predictions)
return model
model1 = new_model()
opt = Adam(lr=3E-4)
model1.compile(optimizer = opt, loss = 'sparse_categorical_crossentropy',metrics = ['accuracy'])
history1 = model1.fit(train_generator,
validation_data = valid_generator,
epochs = 200,
callbacks=callbacks_list1)
model1.load_weights(save_dir+'best_res.hdf5')
model1.compile(optimizer = opt, loss = 'sparse_categorical_crossentropy',metrics = ['accuracy'])
y_pred1 = model1.predict(test_im)
pred_class1=np.argmax(y_pred1,axis=1)
print('accuracy = ',accuracy_score(pred_class1,test_lb))
cm = confusion_matrix(y_target=test_lb,y_predicted=pred_class1, binary=False)
print(cm)
fig, ax = plot_confusion_matrix(conf_mat=cm)
plt.gcf().savefig(save_dir+"resnet.png", dpi=144)
plt.close()
extract_outputs(cm, 'Resnet')
Here are some of the screenshots of the output from tensorflow 2.x
Basically the flow_from_directory by default shuffle the data and you didn't change it.
Just add shuffle=False to your test_generator should be enough.
Like
test_generator = train_datagen.flow_from_directory(
test_dir,
target_size=(IMG_SIZE, IMG_SIZE),
batch_size=16,
class_mode='sparse',
shuffle=False)
Or if you really want to have it shuffled then test_im and test_lb have to be in the same order. For example
test_im = []
test_lb = []
for im, lb in test_generator:
test_im.append(im)
test_lb.append(lb)
test_im = np.array(test_im)
test_lb = np.array(test_lb)

keras image classifier model configuration

I am trying to learn image classification using Keras and TensorFlow.
I am referring to https://www.kaggle.com/c/dogs-vs-cats problem.
My Code is as below:
#!/usr/bin/env python
# coding: utf-8
# # Cats and Dogs Identification Kaggle
#
# https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html
# ## Tensorflow and GPU Memory Config
# In[14]:
import tensorflow as tf
from tensorflow.keras.models import Sequential
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
from tensorflow.keras.layers import Dense, Flatten, Activation, Conv2D, MaxPooling2D, Reshape, BatchNormalization
from keras import backend as K
# tf.reset_default_graph()
# tf.set_random_seed(42)
# tf.config.set_per_process_memory_growth(True)
# tf.config.gpu.set_per_process_memory_fraction(0.4)
tf.debugging.set_log_device_placement(True)
print("Num GPUs Available: ", len(tf.config.experimental.list_physical_devices('GPU')))
tf.config.experimental.list_physical_devices('GPU')
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
# Restrict TensorFlow to only allocate 1GB of memory on the first GPU
try:
tf.config.experimental.set_virtual_device_configuration(
gpus[0],
[tf.config.experimental.VirtualDeviceConfiguration(memory_limit=2048)])
logical_gpus = tf.config.experimental.list_logical_devices('GPU')
print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
except RuntimeError as e:
# Virtual devices must be set before GPUs have been initialized
print(e)
print('Keras image_data_format {}'.format(K.image_data_format()))
print('if keras image_data_format is channel_last means data should be loaded in 32X32X3 dimensions')
# In[2]:
import os
import shutil
from shutil import copyfile
from random import seed
from random import random
def createPathIfNoExists(path):
if not os.path.exists(path):
os.mkdir(path)
cats_dir = '/cats'
dogs_dir = '/dogs'
source_images = '/home/user/Desktop/dogs_cat_keras'
data_dir = source_images + '/data'
train_dir = data_dir + '/train'
train_cats_dir = train_dir + cats_dir
train_dogs_dir = train_dir + dogs_dir
validation_dir = data_dir + '/validation'
validation_cats_dir = validation_dir + cats_dir
validation_dogs_dir = validation_dir + dogs_dir
createPathIfNoExists(data_dir)
createPathIfNoExists(train_dir)
createPathIfNoExists(train_cats_dir)
createPathIfNoExists(train_dogs_dir)
createPathIfNoExists(validation_dir)
createPathIfNoExists(validation_cats_dir)
createPathIfNoExists(validation_dogs_dir)
print('Source directory {}'.format(source_images))
print('Data directory {}'.format(data_dir))
print('train directory {}'.format(train_dir))
print('train cats directory {}'.format(train_cats_dir))
print('train dogs directory {}'.format(train_dogs_dir))
print('validation directory {}'.format(validation_dir))
print('validation directory {}'.format(validation_cats_dir))
print('validation directory {}'.format(validation_dogs_dir))
# inputFiles = source_images + '/train'
# cats = [inputFiles+'/' + d for d in os.listdir(inputFiles) if d.startswith('cat')]
# print('All cats count {}'.format(len(cats)))
# dogs = [inputFiles+'/' + d for d in os.listdir(inputFiles) if d.startswith('dog')]
# print('All dogs count {}'.format(len(dogs)))
# data_split_70 = 8400
# train_cats = cats[:data_split_70]
# validation_cats = cats[data_split_70:]
# train_dogs = dogs[:data_split_70]
# validation_dogs = dogs[data_split_70:]
# print('Total train cats {} and validation cats {}'.format(len(train_cats), len(validation_cats)))
# print('Total train dogs {} and validation dogs {}'.format(len(train_dogs), len(validation_dogs)))
# # Put train cats data in train directory
# for item in train_cats:
# if os.path.isfile(item):
# shutil.copyfile(item, train_cats_dir + '/' + os.path.basename(item))
# # Put validation cats data in validation directory
# for item in validation_cats:
# if os.path.isfile(item):
# shutil.copyfile(item, validation_cats_dir + '/' + os.path.basename(item))
# # Put train cats data in train directory
# for item in train_dogs:
# if os.path.isfile(item):
# shutil.copyfile(item, train_dogs_dir + '/' + os.path.basename(item))
# # Put validation cats data in validation directory
# for item in validation_dogs:
# if os.path.isfile(item):
# shutil.copyfile(item, validation_dogs_dir + '/' + os.path.basename(item))
# ## General imports
# In[15]:
import datetime
import numpy as np
from sklearn.pipeline import Pipeline
from sklearn.model_selection import KFold, GridSearchCV, RandomizedSearchCV
from sklearn.preprocessing import MinMaxScaler
get_ipython().run_line_magic('matplotlib', 'inline')
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier
import h5py
# ## Data Import
# In[16]:
dataGenerator = ImageDataGenerator(rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
# ### Image Display
# In[17]:
img = load_img('/home/user/Desktop/dogs_cat_keras/data/train/cats/cat.12467.jpg') # this is a PIL image
x = img_to_array(img) # this is a Numpy array with shape (width X height X 3)
print(x.shape)
# print(type(img))
# print(img.size)
# print(img.mode)
plt.imshow(x/255)
plt.show()
print('Shape before reshape {}'.format(x.shape))
## Generate data = 0
x = x.reshape((1,) + x.shape) # this is a Numpy array with shape (1, width, height, 3)
print('Shape after reshape {}'.format(x.shape))
# ### Generate augumented data using image generator
# In[6]:
# import os
# augumented_data_path = data_path + '/preview'
# if not os.path.exists(augumented_data_path):
# os.mkdir(augumented_data_path)
# i = 0
# for batch in dataGenerator.flow(x, batch_size=1,
# save_to_dir=augumented_data_path, save_prefix='cat', save_format='jpeg'):
# i += 1
# if i > 20:
# break # otherwise the generator would loop indefinitely
# ### Building Graph
# In[23]:
img_width, img_height = 150, 150
input_shape = (img_width, img_height, 3)
nnModel = Sequential()
nnModel.add(Flatten(input_shape=(input_shape)))
nnModel.add(Dense(32, activation='relu'))
nnModel.add(Dense(16, activation='relu'))
nnModel.add(Dense(2, activation='softmax'))
# ### Compile function
# In[26]:
nnModel.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])
# ### Train Generator
# In[20]:
batch_size = 32
train_data_gen = ImageDataGenerator(rescale = 1/255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
train_generator = train_data_gen.flow_from_directory(
train_dir, # this is the target directory
target_size=(img_width, img_height), # all images will be resized to 150x150
batch_size=batch_size,
class_mode='binary')
print('Train path {}'.format(train_dir))
test_data_gen = ImageDataGenerator(rescale = 1/255)
print('Test path {}'.format(validation_dir))
validation_generator = test_data_gen.flow_from_directory(
validation_dir, # this is the target directory
target_size=(img_width, img_height), # all images will be resized to 150x150
batch_size=batch_size,
class_mode='binary')
# In[24]:
nnModel.summary()
# ### Train
# In[27]:
nnModel.fit_generator(train_generator,
steps_per_epoch=2048,
epochs=64,
validation_data=validation_generator,
validation_steps=1024)
I am getting following exception
<ipython-input-27-59bf3c75cdc4> in <module>
3 epochs=64,
4 validation_data=validation_generator,
----> 5 validation_steps=1024)...
A target array with shape (32, 1) was passed for an output of shape (None, 2) while using as loss `binary_crossentropy`. This loss expects targets to have the same shape as the output.
Problem statement has lot of notebook solution, but here i don't want to use cnn for learning purpose. Please help me solve this.
Your problem in your code comes from this line:
nnModel.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])
You have to change your loss function to categorical_crossentropy, not binary_crossentropy. Practically, in your code, you have to write nnModel.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
If you have a binary classification problem, you can opt for one of these two variants:
Dense(1,activation='sigmoid') + loss = 'binary_crossentropy'
Dense(2,activation='softmax') + loss = 'categorical_crossentropy'
The only small change you may need to also make is for ImageDataGenerator, with the class_mode(set it to 'binary' in the first case and to 'categorical' in the second case)

Keras 2.2.4 fit_generator problem . Value error, Problem in inputting values to the input layer

I am running Keras multi_gpu model. My model takes 2 inputs. one input is given by the Imagedatagenerator and other input is generated through a function inside the model. please have a look at the following code:
import numpy as np
import keras
from keras.layers.convolutional import Conv2D
from keras.layers import ReLU,MaxPooling2D,ZeroPadding2D,BatchNormalization,Dense,Dropout, Activation, Flatten, Lambda, Concatenate, Add
from keras.models import Model
from keras.layers import Input
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot
from keras.utils import plot_model
from keras import backend as K
from keras_preprocessing.image import ImageDataGenerator
from keras.callbacks import ModelCheckpoint
from keras.models import model_from_json
from keras.utils import multi_gpu_model
import pandas as pd
import os
import sys
from tqdm import *
# import skimage
import matplotlib.pyplot as plt
# %matplotlib inline
import cv2
import tensorflow as tf
import multiprocessing
# import pydot
########### Make Log directory #####################################
cwd=os.getcwd()
log_dir = cwd+'/log_dir/Relation_net_logs'
if not os.path.exists(log_dir):
os.makedirs(log_dir)
tensorboard_logsdir = log_dir+"/tensorboard_logdir"
if not os.path.exists(tensorboard_logsdir):
os.makedirs(tensorboard_logsdir)
######### Make Network##############################################
def ConvolutionNetworks(kernel_size=3, stride_size=2):
def conv(model):
model = Conv2D(24, (9, 9), strides=(stride_size, stride_size),activation='relu',input_shape=(100, 100, 3), data_format='channels_last')(model)
model = BatchNormalization()(model)
model = Conv2D(24, (7, 7), strides=(stride_size, stride_size),activation='relu')(model)
model = BatchNormalization()(model)
model = Conv2D(24, (kernel_size, kernel_size), strides=(stride_size, stride_size),activation='relu')(model)
model = BatchNormalization()(model)
model = Conv2D(24, (5, 5), strides=(1, 1),activation='relu')(model)
model = BatchNormalization()(model)
return model
return conv
######### Compute Relations #######
def compute_relations(objects):
def get_top_dim_1(t):
return t[:, 0, :, :]
def get_all_but_top_dim_1(t):
return t[:, 1:, :, :]
def get_top_dim_2(t):
return t[:, 0, :]
def get_all_but_top_dim2(t):
return t[:, 1:, :]
slice_top_dim_1 = Lambda(get_top_dim_1)
slice_all_but_top_dim_1 = Lambda(get_all_but_top_dim_1)
slice_top_dim_2 = Lambda(get_top_dim_2)
slice_all_but_top_dim2 = Lambda(get_all_but_top_dim2)
d = K.int_shape(objects)[2]
features = []
for i in range(d): #This loop extracts top layer of the feature map
features1 = slice_top_dim_1(objects)
objects = slice_all_but_top_dim_1(objects)
for j in range(d): #This loop extract each object from the "top layer" extracted in the previous loop and append it in variable "features"
features2 = slice_top_dim_2(features1)
features1 = slice_all_but_top_dim2(features1)
features.append(features2)
relations = []
concat = Concatenate()
for feature1 in features:
for feature2 in features:
relations.append(concat([feature1, feature2]))
return relations
############## f_theta ############################
def f_theta():
def f(model):
model = Dense(256,activation='relu')(model)
# model = Activation('relu')(model)
model = Dense(256,activation='relu')(model)
# model = Activation('relu')(model)
# model = Dropout(0.5)(model)
model = Dense(256,activation='relu')(model)
# model = Activation('relu')(model)
model = Dense(256,activation='relu')(model)
# model = Activation('relu')(model)
return model
return f
################# Relation module and tag building #########################################
from keras.utils import plot_model
def g_th(layers):
def f(model):
for n in range(len(layers)):
model = layers[n](model)
return model
return f
def stack_layer(layers):
def f(x):
for k in range(len(layers)):
x = layers[k](x)
return x
return f
def g_theta(h_unit=256, layers=4):
r = []
for k in range(layers):
r.append(Dense(h_unit))
r.append(Activation('relu'))
return g_th(r)
def get_MLP():
return g_th()
def RelationNetworks(objects):
g_t = g_theta()
relations = compute_relations(objects)
print("length of relations={}".format(len(relations)))
g_all = []
for r in tqdm(relations):
g_all.append(g_t(r)) #send each relation to g_t and append to a list for easy summation.
print("relation computed")
combined_relation = Add()(g_all)
print("relation combined")
f_out = f_theta()(combined_relation)
print("relation went through f_theta")
return f_out
def build_tag(conv):
d = K.int_shape(conv)[2]
tag = np.zeros((d,d,2))
print("tagging in process")
for i in range(d):
for j in range(d):
tag[i,j,0] = float(int(i%d))/(d-1)*2-1
tag[i,j,1] = float(int(j%d))/(d-1)*2-1
tag = K.variable(tag)
tag = K.expand_dims(tag, axis=0)
batch_size = K.shape(conv)[0]
tag = K.tile(tag, [batch_size,1,1,1])
print("tagging done")
return Input(tensor=tag)
################################# Build Model ###################################################################################
visual_scene = Input((100, 100, 3))
# visual_question = Input((11,))
visual_conv = ConvolutionNetworks()(visual_scene)
tag = build_tag(visual_conv)
visual_conv = Concatenate()([tag, visual_conv])
visual_RN = RelationNetworks(visual_conv)
visual_out = Dense(4, activation='softmax')(visual_RN)
VisualModel = Model(inputs=[tag,visual_scene], outputs=visual_out)
print("model made")
# plot_model(VisualModel, to_file='/home/aakash/Relation_Network/figures/VisualModel1.png')
################################ Create parallel model ###############
# This executes Data Parallelism. Batch is divided equally on all GPUs for computation
try:
parallel_model = multi_gpu_model(VisualModel, cpu_merge=True, cpu_relocation=True,gpus=2)
print("Training using multiple GPUs..")
except:
parallel_model = model
print("Training using single GPU or CPU..")
################################# Training #################################################################################
workers=multiprocessing.cpu_count()-1
batchsize=32
IMG_SIZE=100
train_df_path="/home/aakash/Relation_Network/training_df.pkl"
valid_df_path="/home/aakash/Relation_Network/validation_df.pkl"
image_dir="/home/aakash/Relation_Network/DL_Dataset"
from keras.optimizers import Adam
lr = 1e-4
adam = Adam(lr=lr)
parallel_model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])
#Save architecture
NAME = "2_conv_model"
with open(NAME+".json", "w") as json_file:
json_file.write(VisualModel.to_json())
print("model architecture saved as json file")
#create callbacks
# NAME = "{}-conv-{}-nodes-{}-dense-{}".format(conv_layer, layer_size, dense_layer, int(time.time()))
checkpoint = keras.callbacks.ModelCheckpoint(log_dir+'/'+NAME+'.h5', monitor='val_loss',verbose=0, save_best_only=True, save_weights_only=True, mode='auto', period=1)
csv_logger = keras.callbacks.CSVLogger(log_dir+"/"+NAME+".csv", separator=',', append=False)
tensorboard = keras.callbacks.TensorBoard(log_dir=tensorboard_logsdir+'/'+NAME, histogram_freq=0, batch_size=batchsize, write_graph=True, write_grads=False, write_images=False, embeddings_freq=0,
embeddings_layer_names=None, embeddings_metadata=None, embeddings_data=None, update_freq='epoch')
training_df=pd.read_pickle(train_df_path)
validation_df=pd.read_pickle(valid_df_path)
datagen=ImageDataGenerator(rescale=1./255)
train_generator=datagen.flow_from_dataframe(dataframe=training_df, directory=image_dir,
x_col="image", y_col="lesion", class_mode="categorical",
target_size=(IMG_SIZE,IMG_SIZE), batch_size=batchsize,shuffle=True)
validation_generator=datagen.flow_from_dataframe(dataframe=validation_df, directory=image_dir,
x_col="image", y_col="lesion", class_mode="categorical",
target_size=(IMG_SIZE,IMG_SIZE), batch_size=batchsize)
parallel_model.fit_generator(generator = train_generator,
steps_per_epoch = (training_df.shape[0])//batchsize,
validation_data = validation_generator,
validation_steps = (validation_df.shape[0])//batchsize,
epochs = 30,verbose=1,callbacks=[checkpoint, csv_logger,tensorboard],
use_multiprocessing=True,workers=workers)
build_tag function returns an input layer with a tensor (this is my second input).
But when I run this code, it shows the following error
!(https://drive.google.com/file/d/1gGjoO89zwRw_zUQ14sUIrdC7oRKrdVT1/view?usp=sharing)
I made the build_tag function a Lambda layer and the value returned by build_tag is just value "tag" and NOT an input layer and remove "tag" input to the model and it starts to work.
This is the model-architecture before converting the build_tag into Lambda layer and this one is after conversion.

CNN return the same result for classification (keras)

I am using CNN to classify two types of pollen: sugi and hinoki. When I used the images taken in visible light as data, it predicted "sugi" for all the test images. In the other hand, when I used images taken in ultraviolet as data, it predicted "hinoki" for all the pics in test set. I have change number of epochs, filter size, batch size, number of channels for several times but the result was the same. What should I do?
Here is my code:
Train program:
import os
from keras.applications.vgg16 import VGG16
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential, Model
from keras.layers import Input, Activation, Dropout, Flatten, Dense, Conv2D, MaxPool2D
#from keras.callbacks import EarlyStoppingByLossVal
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
import numpy as np
import time
from PIL import Image
import csv
import shutil
#import numpy.distutils.system_info as sysinfo
import scipy
import scipy.misc
import matplotlib.pyplot as plt
import pandas as pd
# kaneko
from keras.callbacks import TensorBoard
#sysinfo.get_info('lapack')
# 分類するクラス
classes = ['sugi', 'hinoki']
nb_classes = len(classes)
img_width, img_height = 100, 100
# トレーニング用とバリデーション用の画像格納先
train_data_dir = 'cut.kashi/train'
validation_data_dir = 'cut.kashi/validation'
# 今回はトレーニング用に200枚、バリデーション用に50枚の画像を用意した。
nb_train_samples = 1362
nb_validation_samples = 337
#nb_train_samples = 2171
#nb_validation_samples = 528
#batch_size = 64
nb_epoch = 50
gen_tr_batches = 4
folder = './output'
result_dir = 'results'
if not os.path.exists(result_dir):
os.mkdir(result_dir)
train_imagelist = os.listdir(train_data_dir)
test_list = "./test.train"
font = cv2.FONT_HERSHEY_COMPLEX
def vgg_model_maker():
model = Sequential()
model.add(Conv2D(32,5,input_shape=(img_width, img_height,3)))
model.add(Activation('relu'))
#model.add(Conv2D(32,5))
#model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Conv2D(64,5))
model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Flatten())
model.add(Dense(200))
model.add(Activation('relu'))
#model.add(Dropout(1.0))
model.add(Dense(nb_classes, activation='softmax'))
return model
def image_generator():
""" ディレクトリ内の画像を読み込んでトレーニングデータとバリデーションデータの作成 """
train_datagen = ImageDataGenerator(
rescale=1.0 / 255,
zoom_range=0.2,
horizontal_flip=True,
rotation_range = 180)
validation_datagen = ImageDataGenerator(rescale=1.0 / 255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
color_mode='rgb',
classes=classes,
class_mode='categorical',
batch_size=batch_size,
shuffle=True)
validation_generator = validation_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
color_mode='rgb',
classes=classes,
class_mode='categorical',
batch_size=batch_size,
shuffle=True)
return (train_generator,validation_generator)
def global_contrast_normalization(filename, s, lmda, epsilon):
X = numpy.array(Image.open(filename))
# replacement for the loop
X_average = numpy.mean(X)
print('Mean: ', X_average)
X = X - X_average
# `su` is here the mean, instead of the sum
contrast = numpy.sqrt(lmda + numpy.mean(X**2))
X = s * X / max(contrast, epsilon)
# scipy can handle it
scipy.misc.imsave('result.jpg', X)
# Generator for the network's training generator.
# Actual generator for the network's training.
if __name__ == '__main__':
start = time.time()
for the_file in os.listdir(folder):
file_path = os.path.join(folder, the_file)
try:
if os.path.isfile(file_path):
os.unlink(file_path)
#elif os.path.isdir(file_path): shutil.rmtree(file_path)
except Exception as e:
print(e)
# kaneko
tensorboard = TensorBoard(log_dir="./kaneko", histogram_freq=0, batch_size= batch_size,write_graph=True)
# モデル作成
vgg_model = vgg_model_maker()
# 最後のconv層の直前までの層をfreeze
#for layer in vgg_model.layers[:15]:
#layer.trainable = False
# 多クラス分類を指定
vgg_model.compile(loss='categorical_crossentropy',
optimizer=optimizers.SGD(lr=1e-3, momentum=0.9),
metrics=['accuracy'])
# 画像のジェネレータ生成
train_generator,validation_generator = image_generator()
# Fine-tuning
history_callback = vgg_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=[tensorboard])
loss_history = history_callback.history["loss"]
accuracy_history = history_callback.history["acc"]
val_loss_history = history_callback.history["val_loss"]
val_accuracy_history = history_callback.history["val_acc"]
numpy_loss_history = np.array(loss_history)
numpy_accuracy_history = np.array(accuracy_history)
numpy_val_loss_history = np.array(val_loss_history)
numpy_val_accuracy_history = np.array(val_accuracy_history)
f = open("results/result.csv","w")
writer = csv.writer(f)
writer.writerow(["loss","accuracy","validation loss","validation accuracy"])
for j in range(len(numpy_loss_history)):
writer.writerow([numpy_loss_history[j],numpy_accuracy_history[j],numpy_val_loss_history[j],numpy_val_accuracy_history[j]])
epochnum = range(len(numpy_loss_history))
print(len(epochnum))
#plt.plot(epochnum,numpy_loss_history, label = "loss")
#plt.legend()
plt.plot(loss_history)
plt.plot(val_loss_history)
plt.legend(['loss', 'val_loss'])
plt.show()
#plt.savefig("./Documents/Ghi1/shigaisen_loss.png")
plt.clf()
plt.plot(epochnum,numpy_accuracy_history, label = "accuracy")
plt.show()
#plt.savefig(".../Documents/Ghi1/shigaisen_accuracy.png")
plt.clf()
vgg_model.save_weights(os.path.join(result_dir, 'finetuning.h5'))
process_time = (time.time() - start) / 60
print(u'学習終了。かかった時間は', process_time, u'分です。')
Test program:
import os, sys
import numpy as np
import cv2
from keras.applications.vgg16 import VGG16
from keras.models import Sequential, Model
from keras.layers import Input, Activation, Dropout, Flatten, Dense, Conv2D,MaxPool2D
from keras.preprocessing import image
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
from datetime import datetime
classes = ['sugi', 'hinoki']
nb_classes = len(classes)
img_width, img_height = 100, 100
DataShape = (100,100,3)
result_dir = 'results'
#test_list = "./testfile"
test_list = "./test.train"
font = cv2.FONT_HERSHEY_COMPLEX
# このディレクトリにテストしたい画像を格納しておく
test_data_dir = 'cut/test'
folder = './output'
def model_load():
# VGG16, FC層は不要なので include_top=False
model = Sequential()
model.add(Conv2D(32,5,input_shape=(img_width, img_height,3)))
model.add(Activation('relu'))
#model.add(Conv2D(32,5))
#model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Conv2D(64,5))
model.add(Activation('relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Flatten())
model.add(Dense(200))
model.add(Activation('relu'))
#model.add(Dropout(1.0))
model.add(Dense(nb_classes, activation='softmax'))
#adam = Adam(lr=1e-4)
# 学習済みの重みをロード
model.load_weights(os.path.join(result_dir, 'finetuning.h5'))
# 多クラス分類を指定
model.compile(loss='categorical_crossentropy',
optimizer=optimizers.SGD(lr=1e-3, momentum=0.9),
metrics=['accuracy'])
return model
def image_generator():
""" ディレクトリ内の画像を読み込んでトレーニングデータとバリデーションデータの作成 """
test_datagen = ImageDataGenerator(
rescale=1.0 / 255,
zoom_range=0.2,
horizontal_flip=True,
rotation_range = 180)
#validation_datagen = ImageDataGenerator(rescale=1.0 / 255)
test_generator = test_datagen.flow_from_directory(
test_data_dir,
target_size=(img_width, img_height),
color_mode='rgb',
classes=classes,
class_mode='categorical',
batch_size=batch_size,
shuffle=True)
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
# initialize the dimensions of the image to be resized and
# grab the image size
dim = None
(h, w) = image.shape[:2]
# if both the width and height are None, then return the
# original image
if width is None and height is None:
return image
# check to see if the width is None
if width is None:
# calculate the ratio of the height and construct the
# dimensions
r = height / float(h)
dim = (int(w * r), height)
# otherwise, the height is None
else:
# calculate the ratio of the width and construct the
# dimensions
r = width / float(w)
dim = (width, int(h * r))
# resize the image
resized = cv2.resize(image, dim, interpolation = inter)
# return the resized image
return resized
def test(model,path,filename,sugi):
test_imagelist = []
# テスト用画像取得
#test_imagelist = os.listdir(test_data_dir)
#test_imagelist = os.listdir(test_data_dir)
iml = cv2.imread(path,cv2.IMREAD_COLOR)
img = image_resize(iml,height=960)
img_array = np.array(img)
cimg = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cimg = cv2.medianBlur(cimg,5)
#_,cimg = cv2.threshold(cimg,0,255,cv2.THRESH_BINARY| cv2.THRESH_OTSU)
#cv2.imwrite(datetime.now().strftime('%s')+"binary.jpg",cimg)
#sys.exit()
circles = cv2.HoughCircles(cimg,cv2.HOUGH_GRADIENT,1,10,param1=15,param2=20,minRadius=10,maxRadius=25)
circles = np.uint16(np.around(circles))[0,:]
print (len(circles))
center = []
predict = []
for i in circles:
half = DataShape[0]//2
zoom_data = img_array[i[1]-half:i[1]+half,i[0]-half:i[0]+half,:]
if zoom_data.shape!=DataShape : continue
czoom = cv2.cvtColor(zoom_data, cv2.COLOR_BGR2GRAY)
czoomarr = np.array(zoom_data)
cen = czoom[half,half]
#edge = czoom[0,0]
if cen != 0:
#if cen < 255:
#if czoom[30,30] < 80:
test_imagelist.append(zoom_data)
center.append(i)
label_num = len(test_imagelist)
print(len(center))
print(label_num)
for im in test_imagelist:
x = image.img_to_array(im)
x = np.expand_dims(x, axis=0)
# 学習時に正規化してるので、ここでも正規化
x = x / 255
pred = model.predict(x)[0]
print(pred)
predict.append(pred)
TP = 0
TN = 0
FN = 0
FP = 0
for j in range(label_num):
if predict[j][0] > predict[j][1]:
if sugi == 1:
#TP+=1
TN+=1
else:
#FP+=1
FN+=1
#cv2.circle(img,(center[j][0],center[j][1]),center[j][2],(0,255,0),2)
cv2.putText(img,'S',(center[j][0],center[j][1]), font, 0.5,(0,255,0),1,cv2.LINE_AA)
if predict[j][0] < predict[j][1]:
#cv2.circle(img,(center[j][0],center[j][1]),center[j][2],(0,0,255),2)
if sugi == 1:
#FN+=1
FP+=1
else:
#TN+=1
TP+=1
cv2.putText(img,'H',(center[j][0],center[j][1]), font,0.5,(0,0,255),1,cv2.LINE_AA)
cv2.imwrite("output/"+"output"+filename,img)
return TP, FP, FN, TN
if __name__ == '__main__':
# モデルのロード
TP,FP,FN,TN = 0,0,0,0
print(TP,FP,FN,TN)
sugi = 0
c = "ス"
model = model_load()
for the_file in os.listdir(folder):
file_path = os.path.join(folder, the_file)
try:
if os.path.isfile(file_path):
os.unlink(file_path)
#elif os.path.isdir(file_path): shutil.rmtree(file_path)
except Exception as e:
print(e)
for the_file in os.listdir(test_list):
#print(the_file)
if c in the_file:
sugi = 1
else:
sugi = 0
file_path = os.path.join(test_list, the_file)
tp1,fp1,fn1,tn1 = test(model,file_path,the_file,sugi)
TP += tp1
FP += fp1
FN += fn1
TN += tn1
precision = TP/(TP + FP)
recall = TP/(TP + FN)
F = (2*recall*precision)/(recall + precision)
#cv2.imwrite("output/" + "result.jpg",img)
print("TP = %lf, TN = %lf, FN = %lf, FP = %lf" %(TP,TN,FN,FP))
print("precision = %lf, recall = %lf" %(precision,recall))
print("F measure = %lf" %(F))
One problem I can see is here x = x / 255 in test method. You need to get float values for proper normalisation. I faced the same issue and proper scaling got it working. Here's the link
I hope this helps.
EDIT: My answer is considering for python 2.
I suspect you got a wrong folder structure.
The ImageDataGenerator will create classes based on the folder structure you use.
You should have inside your "datadir":
One "sugi" folder with all sugi images
One "hinoki" folder with all hinoki images
But it seems you have instead:
One "visible" folder
One "ultraviolet" folder
This will certainly make the generator think "visible=sugi" and "ultraviolet=hinoki".

Categories

Resources