problem overfitting model VGG16 small dataset - python-3.x

Screenshot of the problem
i have two classes, each of them contains an equal number of pictures
Train
360 train pictures for classe one
360 train pictures for classe two
Test
90 test pictures classe one
90 test pictures classe two
my code
def load_split(basePath, csvPath):
data = []
labels = []
rows = open(csvPath).read().strip().split("\n")[1:]
random.shuffle(rows)
for (i, row) in enumerate(rows):
if i > 0:
print("[INFO] processed {} total images".format(i))
(label, imagePath) = row.strip().split(",")[-2:]
imagePath = os.path.sep.join([basePath, imagePath])
image = io.imread(imagePath)
image = transform.resize(image, (224, 224))
image = exposure.equalize_adapthist(image, clip_limit=0.1)
data.append(image)
labels.append(int(label))
data = np.array(data)
labels = np.array(labels)
return (data, labels)
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True,
help="path to input GTSRB")
ap.add_argument("-m", "--model", required=True,
help="path to output model")
ap.add_argument("-p", "--plot", type=str, default="plot.png",
help="path to training history plot")
args = vars(ap.parse_args())
NUM_EPOCHS = 30
INIT_LR = 1e-4
BS = 64
labelNames = open("signnames.csv").read().strip().split("\n")[1:]
labelNames = [l.split(",")[1] for l in labelNames]
trainPath = os.path.sep.join([args["dataset"], "Train.csv"])
testPath = os.path.sep.join([args["dataset"], "Test.csv"])
print("[INFO] loading training and testing data...")
(trainX, trainY) = load_split(args["dataset"], trainPath)
(testX, testY) = load_split(args["dataset"], testPath)
trainX = (trainX-np.mean(trainX))/np.std(trainX)
testX = (testX-np.mean(testX))/np.std(testX)
numLabels = len(np.unique(trainY))
trainY = to_categorical(trainY, numLabels)
testY = to_categorical(testY, numLabels)
classTotals = trainY.sum(axis=0)
classWeight = classTotals.max() / classTotals
aug = ImageDataGenerator(
rotation_range=10,
zoom_range=0.15,
width_shift_range=0.1,
height_shift_range=0.1,
shear_range=0.15,
horizontal_flip=False,
vertical_flip=False,
fill_mode="nearest")
print("[INFO] compiling model...")
opt = Adam(lr=INIT_LR)
model = TrafficSignNet.build(width=224, height=224, depth=3,
classes=numLabels)
model.compile(loss="categorical_crossentropy", optimizer=opt,
metrics=["accuracy"])
print("[INFO] training network...")
H = model.fit_generator(
aug.flow(trainX, trainY, batch_size=BS),
validation_data=(testX, testY),
steps_per_epoch=trainX.shape[0] // BS,
epochs=NUM_EPOCHS,
class_weight=classWeight,
verbose=1)
print("[INFO] evaluating network...")
predictions = model.predict(testX, batch_size=BS)
print(classification_report(testY.argmax(axis=1),
predictions.argmax(axis=1), target_names=labelNames))
print("[INFO] serializing network to '{}'...".format(args["model"]))
model_json = model.to_json()
with open("model.json", "w") as json_file:
json_file.write(model_json)
model.save_weights("model.h5")
print("Saved model to disk")
Enddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd

I could not get access to your training script for some reason - can check your screenshot only.
I think your problem is not overfitting - your model is actually not learning, since the loss is not reduced while the accuracy keeps at the same level. Please double check you network, learning rate (most important) and preprocessing. Also, you may consider loading the VGG16 pretrained weight or not to load if you have done.
Or just post your code, I can take a look when I get a chance.
Update:
Based on your codes, I found you did not make any changes internally on the VGG16 - which is easy to debug.
Check you training and test set and make sure the classes are evenly distributed
Print out the label (Y test and train), carefully check if they are correct.
Try to standardize the X train and test instead of dividing by 255. x=(x-mean)/std
Try use learning rate as 0.0001 (I found it's generally good for VGG16 based network)
Stay simple at the first time. Don't use the decayed optimization, just try the standard ADAM firstly
Bests,

Related

ram crashed while using imagedatagenerator in google colab

I have no coding experience, new to python.
task: use cnn to do image binary classification
problem: memory error
# data is confidential, image example is pasted. [enter image description here][1]
# two classes of images: 294 images for class 'e'; 5057 images for class 'l'. Given datasets were imbalanced, the original plan was set batch_size=500 in datagen.flow_from_directory for each class. So, in every batch, the whole dataset of class 'e' and 500 images of class 'l' were fed to the model. However, google colab keeps crashing out of ram. Batch_size was downgraded to 50, still failed.
# x=image data; y=label; bs=batch_size
bs = 50
def generate_batch_data_random(x, y, bs):
ylen = len(y)
loopcount = ylen // bs
while (True):
i = random.randint(0,loopcount)
yield x[i * bs:(i + 1) * bs], y[i * bs:(i + 1) * bs]
def train_and_validate_model(model, x, y):
(trainX, testX, trainY, testY) = train_test_split(x, y, test_size=0.25, random_state=6)
trainY = to_categorical(trainY, num_classes=2)
testY = to_categorical(testY, num_classes=2)
logger = CSVLogger(kfold_train_and_validate, append=True)
H = model.fit_generator(generator=generate_batch_data_random(trainX, trainY, bs),
steps_per_epoch= len(trainX) / bs,
epochs=10,
validation_data=generate_batch_data_random(testX, testY, bs), validation_steps= len(testX) /bs,
callbacks=[checkpoint])
return H,testX,testY
# use imagedatagenerator to save memory. Split groups seem more appropriate than fixed training and validate groups. So dataset structure was built based on the classes of images (one folder of images for each class), not the training and validation groups. The plan was to use imagedatagenerator to send images in batches, then use kfold to split each batch into training and validate groups.
path = '/content/drive/MyDrive/er_lr/erlr_vs_er'
datagen = ImageDataGenerator(rescale=1./255)
data_e = datagen.flow_from_directory(directory=path,
target_size=(128,128),
classes='e',
batch_size=50,
class_mode='categorical')
x_e, y_e = next(data_e)
data_l = datagen.flow_from_directory(directory=path,
classes='l',
target_size=(128,128),
batch_size=50,
class_mode='categorical')
x_l, y_l = next(data_l)
for i in range(0,len(y_e)):
y_e[i] = 0
for j in range(0,len(y_l)):
y_l[j] = 1
x = []
y = []
x.extend(np.array(data_e)[0][0])
x.extend(np.array(data_l)[0][0])
y.extend(np.array(y_e))
y.extend(np.array(y_l))
seed = 10
np.random.seed(seed)
filepath = '/content/drive/MyDrive/er_lr/hdf5/my_best_model.epoch{epoch:02d}-loss{val_loss:.2f}.hdf5'
fold = 1
kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=seed)
for train, test in kfold.split(x, y):
model = create_model()
checkpoint = keras.callbacks.ModelCheckpoint(filepath,
monitor='val_loss', save_weights_only=True,verbose=1,save_best_only=True, save_freq='epoch', period=1)
H,validationX,validationY=train_and_validate_model(model, x[train], y[train])
training_ACCs.append(H.history['accuracy'])
training_loses.append(H.history['loss'])
val_ACCs.append(H.history['val_accuracy'])
val_loses.append(H.history['val_loss'])
labels_test_cat = to_categorical(y[test], num_classes=2)
scores = model.evaluate(x[test], labels_test_cat, verbose=0)
fold = fold + 1
crashed in google colab repeatedly for out of ram. batch_size of 50 and np.shape of (128, 128, 3) of each image do not seem large-scaled.
Any thoughts?
[1]: https://i.stack.imgur.com/Lp1H9.png

How to find loss function values in unsupervised learning with Autoencoder?

To simplify my story: I was trying to test dimensionality reduction on my UNLABELED data with the encoder method using keras/tensorflow.
So I looked at the internet and found a nice code that might be useful for me. Here's the link: https://github.com/IvanBongiorni/TensorFlow2.0_Notebooks/blob/master/TensorFlow2.0__02.01_Autoencoder_for_Dimensionality_Reduction.ipynb
Although, I'm interested just in the encoder part. So here I added part of that code to mine, but I can't figure out how the code calculates loss function values if I didn't give any targets/labels. I'm new using keras/tensorflow and thought loss function values could only be generated if you give true and predicted labels.
data = np.random.randint(1, 100, 500)
df = pd.DataFrame({'f1':data, 'f2':data**2, 'f3':data*0.33, 'f4':data/20})
scaler = StandardScaler()
scaled_df = scaler.fit_transform(df)
scaled_df = pd.DataFrame(scaled_df, columns=['f1','f2','f3','f4'])
n_input_layer = scaled_df.shape[1]
n_encoding_layer = 1
n_output_layer = n_input_layer
# AUTOENCODER
autoencoder = tf.keras.models.Sequential([
# ENCODER
Dense(n_input_layer, input_shape = (n_input_layer,), activation = 'elu'),
# CENTRAL LAYER
Dense(n_encoding_layer, activation = 'elu', name = 'central_layer'),
# DECODER
Dense(n_output_layer, activation = 'elu')])
n_epochs = 5000
loss = tf.keras.losses.MeanSquaredError()
optimizer = tf.optimizers.Adam(learning_rate = 0.001, decay = 0.0001, clipvalue = 0.5)
loss_history = [] # save loss improvement
for epoch in range(n_epochs):
with tf.GradientTape() as tape:
current_loss = loss(autoencoder(scaled_df.values), scaled_df.values)
gradients = tape.gradient(current_loss, autoencoder.trainable_variables)
optimizer.apply_gradients(zip(gradients, autoencoder.trainable_variables))
loss_history.append(current_loss.numpy()) # save current loss in its history
# show loss improvement every 200 epochs
if (epoch+1) % 200 == 0:
print(str(epoch+1) + '.\tLoss: ' + str(current_loss.numpy()))
Could anyone show me what I am missing? Thanks

How to determine the optimal number of "Steps" and "Batch Size" for test dataset in Keras ImageDataGenerator?

I have trained an image similarity network. The network is designed to distinguish between similar/dissimilar pairs of images.
Whare a pair contains a camera image and its corresponding sketch image.
The test dataset contains 4 image directories (camera_positive, sketch_positive, camera_negative, sketch_negative).
I am facing problem while evaluating the performance of the network on the test dataset.
As the test dataset is huge to fit into the memory, I decided to use Keras ImageDataGenerator.
I implemented the following code. Each directory contains 20 images (for small demonstration).
Therefore, in total 80 images and 40 predictions.
As the ImageDataGenerator gives us the option to save the image I used "save_to_dir" parameter as can be seen in the following code to verify the correct working.
Each directory contains 20 images therefore, I am expecting after running the predictions it will save the same images to the specified directories.
After running the code, it generates 31 images in each folder instead of 20!
I played around the different step sizes but no one gives accurate results.
What is wrong with this code. Please suggest!
import os
import numpy as np
from keras.models import load_model
from keras.preprocessing.image import ImageDataGenerator
batch_size = 1
image_size = 224
class_mode = None
"""
c_pos/neg: camera positive/neg image
s_pos/neg: sketch positive/neg image
"""
c_pos = r"testing\c_pos"
c_neg = r"testing\c_neg"
s_pos = r"testing\s_pos"
s_neg = r"testing\s_neg"
datagen_constructor = ImageDataGenerator()
def initialize_generator(generator, c_pos, s_pos, c_neg, s_neg):
camera_pos=generator.flow_from_directory(
c_pos,
target_size=(image_size, image_size),
color_mode="rgb",
batch_size=batch_size,
class_mode=class_mode,
shuffle = False,
seed=7,
save_to_dir='results/c_pos',
save_format='jpeg',
save_prefix='CPOS'
)
sketch_pos=generator.flow_from_directory(
s_pos,
target_size=(image_size, image_size),
color_mode="rgb",
batch_size=batch_size,
class_mode=class_mode,
shuffle = False,
seed=7,
save_to_dir='results/s_pos',
save_format='jpeg',
save_prefix='SPOS'
)
camera_neg=generator.flow_from_directory(
c_neg,
target_size=(image_size, image_size),
color_mode="rgb",
batch_size=batch_size,
class_mode=class_mode,
shuffle = False,
seed=7,
save_to_dir='results/c_neg',
save_format='jpeg',
save_prefix='CNEG'
)
sketch_neg=generator.flow_from_directory(
s_neg,
target_size=(image_size, image_size),
color_mode="rgb",
batch_size=batch_size,
class_mode=class_mode,
shuffle = False,
seed=7,
save_to_dir='results/s_neg',
save_format='jpeg',
save_prefix='SNEG'
)
while True:
camerapos = np.expand_dims(camera_pos.next(), axis=0)
sketchpos = np.expand_dims(sketch_pos.next(), axis=0)
cameraneg = np.expand_dims(camera_neg.next(), axis=0)
sketchneg = np.expand_dims(sketch_neg.next(), axis=0)
camera = np.concatenate((camerapos[0], cameraneg[0]))
sketch = np.concatenate((sketchpos[0], sketchneg[0]))
camera = np.asarray(list(camera), dtype=np.float32)
sketch = np.asarray(list(sketch), dtype=np.float32)
yield [camera, sketch]
test_datagen = initialize_generator(datagen_constructor, c_pos, s_pos, c_neg, s_neg)
# Load pre-trained model
model = load_model("model.h")
# Evaluating network performance on test dataset
predict = model.predict_generator(test_datagen, steps = 20)
You could manually iterate through each folder and make a prediction like this:
model = load_model("model.h")
image_paths = [image.path for image in os.scandir(path_to_my_folder)]
for image_path in image_paths:
image = cv2.imread(image_path)
image_to_predict = np.expand_dims(image,axis=0) # this is important to add the batch index, keras only predicts on batches and here we have batch of size 1
prediction = model.predict(image_to_predict)
Then, you could compare each prediction with the ground truth label you know it belongs to.

how can i improve number predictions?

I've got some number classification model, on test data it works OK, but when I want to classifier other images, I faced with problems that my model can't exactly predict what number is it. Pls, help me improve the model.predict() performance.
I've tried to train my model in many ways, in the code below there is a function that creates classification model, I trained this model actually many ways, [1K < n < 60K] of input test data, [3 < e < 50] of trained iterations.
def load_data():
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()
train_images = tf.keras.utils.normalize(train_images, axis = 1)
test_images = tf.keras.utils.normalize(test_images, axis = 1)
return (train_images, train_labels), (test_images, test_labels)
def create_model():
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(128, activation = tf.nn.relu))
model.add(tf.keras.layers.Dense(128, activation = tf.nn.relu))
model.add(tf.keras.layers.Dense(10, activation = tf.nn.softmax))
data = load_data(n=60000, k=5)
model.compile(optimizer ='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(data[0][0][:n], data[0][1][:n], epochs = e)# ive tried from 3-50 epochs
model.save(config.model_name)
def load_model():
return tf.keras.models.load_model(config.model_name)def predict(images):
try:
model = load_model()
except:
create_model()
model = load_model()
images = tf.keras.utils.normalize(images, axis = 0)
d = load_data()
plot_many_images([d[0][0][0].reshape((28,28)), images[0]],['data', 'image'])
predictions = model.predict(images)
return predictions
I think that my input data isn't looking like the data is predicting model, but I've tried to make it as similar as I can. On this pic(https://imgur.com/FfLGMEK) on the LEFT is train data image, and on RIGHT is my parsed image, they are both 28x28 pix, both a cv2.noramalized
for the test image predictions I've used this(https://imgur.com/RMfKtag) sudoku, it's already formatted to be similar with a test data numbers, but when I test this image with the model prediction the result is not so nice(https://imgur.com/RQFvLNE)
As you can see predicted data leaves much to be desired.
P.S. the (' ') items in predicted data result made by my hands(I've replaced numbers at that positions by ' '), cos after predictions they all have some value(1-9), its not necessary now.
what do you mean "on test data it works OK"? if you mean its works good for train data but do not has a good prediction on test data, maybe your model was over-fit in training phase. i suggest to use train/validation/test approach to train your network.

batching huge data in tensorflow

I am trying to perform binary classification using the code/tutorial from
https://github.com/eisenjulian/nlp_estimator_tutorial/blob/master/nlp_estimators.py
print("Loading data...")
(x_train_variable, y_train), (x_test_variable, y_test) = imdb.load_data(num_words=vocab_size)
print(len(y_train), "train sequences")
print(len(y_test), "test sequences")
print("Pad sequences (samples x time)")
x_train = sequence.pad_sequences(x_train_variable,
maxlen=sentence_size,
padding='post',
value=0)
x_test = sequence.pad_sequences(x_test_variable,
maxlen=sentence_size,
padding='post',
value=0)
print("x_train shape:", x_train.shape)
print("x_test shape:", x_test.shape)
def train_input_fn():
dataset = tf.data.Dataset.from_tensor_slices((x_train, x_len_train, y_train))
dataset = dataset.shuffle(buffer_size=len(x_train_variable))
dataset = dataset.batch(100)
dataset = dataset.map(parser)
dataset = dataset.repeat()
iterator = dataset.make_one_shot_iterator()
return iterator.get_next()
def eval_input_fn():
dataset = tf.data.Dataset.from_tensor_slices((x_test, x_len_test, y_test))
dataset = dataset.batch(100)
dataset = dataset.map(parser)
iterator = dataset.make_one_shot_iterator()
return iterator.get_next()
def cnn_model_fn(features, labels, mode, params):
input_layer = tf.contrib.layers.embed_sequence(
features['x'], vocab_size, embedding_size,
initializer=params['embedding_initializer'])
training = mode == tf.estimator.ModeKeys.TRAIN
dropout_emb = tf.layers.dropout(inputs=input_layer,
rate=0.2,
training=training)
conv = tf.layers.conv1d(
inputs=dropout_emb,
filters=32,
kernel_size=3,
padding="same",
activation=tf.nn.relu)
# Global Max Pooling
pool = tf.reduce_max(input_tensor=conv, axis=1)
hidden = tf.layers.dense(inputs=pool, units=250, activation=tf.nn.relu)
dropout_hidden = tf.layers.dropout(inputs=hidden,
rate=0.2,
training=training)
logits = tf.layers.dense(inputs=dropout_hidden, units=1)
# This will be None when predicting
if labels is not None:
labels = tf.reshape(labels, [-1, 1])
optimizer = tf.train.AdamOptimizer()
def _train_op_fn(loss):
return optimizer.minimize(
loss=loss,
global_step=tf.train.get_global_step())
return head.create_estimator_spec(
features=features,
labels=labels,
mode=mode,
logits=logits,
train_op_fn=_train_op_fn)
cnn_classifier = tf.estimator.Estimator(model_fn=cnn_model_fn,
model_dir=os.path.join(model_dir, 'cnn'),
params=params)
train_and_evaluate(cnn_classifier)
The example here loads data from IMDB movie reviews. I have my own dataset in the form of text which is approx 2GB huge. Now in this example the line
(x_train_variable, y_train), (x_test_variable, y_test) = imdb.load_data(num_words=vocab_size) tries to load whole dataset in memory. If I try to do the same I run out of memory. How can I restructure this logic to read data in batches from my disk?
You want to change the dataset = tf.data.Dataset.from_tensor_slices((x_train, x_len_train, y_train)) line. There are lots of ways of creating a dataset - from_tensor_slices is the easiest, but won't work on its own if you can't load the entire dataset to memory.
The best way depends on how you have the data stored, or how you want to store it/manipulate it. The simplest in my opinion with very little down-side (unless running on multiple GPUs) is to have the original dataset just give indices to data, and write a normal numpy function for loading the ith example.
dataset = tf.data.Dataset.from_tensor_slices(tf.range(epoch_size))
def tf_map_fn(i):
def np_map_fn(i):
return load_ith_example(i)
inp1, inp2 = tf.py_func(np_map_fn, (i,), Tout=(tf.float32, tf.float32), stateful=False)
# other preprocessing/data augmentation goes here.
# unbatched sizes
inp1.set_shape(shape1)
inp2.set_shape(shape2)
return inp1, inp2
dataset = dataset.repeat().shuffle(epoch_size).map(tf_map_fn, 8)
dataset = dataset.batch(batch_size)
dataset = dataset.prefetch(1) # start loading data as GPU trains on previous batch
inp1, inp2 = dataset.make_one_shot_iterator().get_next()
Here I assume your outputs are float32 tensors (Tout=...). set_shape calls aren't strictly necessary, but if you know the shape it'll do better error checks.
So long as your preprocessing doesn't take longer than your network to run, this should run just as fast as any other method on a single GPU machine.
The other obvious way is to convert your data to tfrecords, but that'll take up more space on disk and is more of a pain to manage if you ask me.

Resources