How to deal with labels in input pipeline? - tensorflow

I do have an images' names and labels as a list and I want to get a batch of 64 images/labels. I could get the images in a right way but for labels, its dimension is (64,8126). Each column has the same element 64 times. And rows consists 8126 original label values without getting shuffled.
I understand the problem that for every image tf.train.shuffle_batch considers the 8126 element label vector. But how would I pass only single element for each image?
def _get_images(shuffle=True):
"""Gets the images and labels as a batch"""
#get image and label list
_img_names,_img_class = _get_list() #list of image names and labels
filename_queue = tf.train.string_input_producer(_img_names)
#reader
image_reader = tf.WholeFileReader()
_, image_file = image_reader.read(filename_queue)
#decode jpeg
image_original = tf.image.decode_jpeg(image_file)
label_original = tf.convert_to_tensor(_img_class,dtype=tf.int32)
#print label_original
#image preprocessing
image = tf.image.resize_images(image_original, [224,224])
float_image = tf.cast(image,dtype=tf.float32)
float_image = tf.image.per_image_standardization(image)
#set the shape
float_image.set_shape((224, 224, 3))
#label_original.set_shape([8126]) #<<<<<=========== causes (64,8126) dimension label without shuffle
#parameters for shuffle
batch_size = 64
num_preprocess_threads = 16
num_examples_per_epoch = 8000
min_fraction_of_examples_in_queue = 0.4
min_queue_examples = int(num_examples_per_epoch *
min_fraction_of_examples_in_queue)
if shuffle:
images_batch, label_batch = tf.train.shuffle_batch(
[float_image,label_original],
batch_size=batch_size,
num_threads=num_preprocess_threads,
capacity=min_queue_examples + 3 * batch_size,
min_after_dequeue=min_queue_examples)
else:
images_batch, label_original = tf.train.batch(
[float_image,_img_class],
batch_size=batch_size,
num_threads=num_preprocess_threads,
capacity=min_queue_examples + 3 * batch_size)
return images_batch,label_batch

you may use tf.train.slice_input_producer
# here _img_class should be a list
labels_queue = tf.train.slice_input_producer([_img_class])
...
images_batch, label_batch = tf.train.shuffle_batch(
[float_image,labels_queue],
batch_size=batch_size,
num_threads=num_preprocess_threads,
capacity=min_queue_examples + 3 * batch_size,
min_after_dequeue=min_queue_examples)

Related

Retrieve final (incomplete) batch of custom Data Generator

I have a made a custom data generator that outputs batches of image sequences of shape (batch size, sequence length, image height, image width, channels), along with two labels y1 and y2.
However, I cant seem to retrieve the final (incomplete) batch during training. Any ideas where I am going wrong?
class DataGenerator(tf.keras.utils.Sequence):
'Generates data for Keras'
def __init__(self, list_IDs, labels, training_set=False, batch_size=32, dim=(224, 224), n_channels=3, shuffle=True):
'Initialization'
self.dim = dim
self.batch_size = batch_size
self.labels = labels
self.training_set = training_set
self.list_IDs = list_IDs
self.n_channels = n_channels
self.shuffle = shuffle
self.on_epoch_end()
def __len__(self):
'Denotes the number of batches per epoch'
num_batchs_per_epoch = int(np.floor(len(self.list_IDs) / self.batch_size))
return num_batchs_per_epoch
def __getitem__(self, index):
'Generate one batch of data'
# Generate indexes of the batch
start = index*self.batch_size
end = (index+1)*self.batch_size
indexes = self.indexes[start:end]
# Find list of IDs
list_IDs_temp = [self.list_IDs[k] for k in indexes]
# Generate data
X, y1, y2 = self.__data_generation(list_IDs_temp)
return X, [y1, y2]
def on_epoch_end(self):
'Updates indexes after each epoch'
self.indexes = np.arange(len(self.list_IDs))
if self.shuffle == True:
np.random.shuffle(self.indexes)
def __data_generation(self, list_IDs_temp):
'Generates data containing batch_size samples' # X : (n_samples, 3, *dim, n_channels)
# Initialization
X = np.empty((self.batch_size, 3, *self.dim, self.n_channels))
y1 = np.empty((self.batch_size), dtype=float)
y2 = np.empty((self.batch_size), dtype=int)
# Generate data
for i, ID in enumerate(list_IDs_temp):
sequence = [s for s in ID]
f0, f1, f2 = [self.load_resize_image(image) for image in sequence]
# preprocess steps
f0 = self.preprocess(f0, self.training_set)
f1 = self.preprocess(f1, self.training_set)
f2 = self.preprocess(f2, self.training_set)
triplet = np.concatenate((f0,f1,f2), axis=0)
X[i,:,:,:,:] = triplet
ID = tuple(ID)
y1[i] = self.labels[ID][0]
y2[i] = self.labels[ID][1]
return X, y1, y2
def preprocess(self, img, training_set):
if self.training_set:
# apply transformations
gen = ImageDataGenerator()
img[0,:,:,:] = gen.apply_transform(x=img[0,:,:,:], transform_parameters={'theta':random.uniform(-180, 180),
'brightness': random.uniform(0.8, 1.2),
'flip_horizontal': random.getrandbits(1),
'shear': random.uniform(0,5),
'zx': random.uniform(0.9,1.1),
'zy': random.uniform(0.9,1.1),
'flip_vertical': random.getrandbits(1)
})
return img
def load_resize_image(self, image):
img = cv2.imread(image)
img = cv2.resize(img, dsize=(224, 224), interpolation=cv2.INTER_CUBIC)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_array = np.array(img)
img_array = np.expand_dims(img_array, 0)
return img_array
And at training...
history = model.fit(
training_generator,
epochs=epochs,
validation_data=validation_generator,
callbacks=callbacks
)
The code will always omit the last batch of data, due to this line of code:
int(np.floor(len(self.list_IDs) / self.batch_size))
See the example below:
number_of_samples = 1002
batch_size = 4
num_batches_per_epoch = int(np.floor(number_of_samples / 4))
num_batches_per_epoch (=250, if number_of_samples == 1000,1001,1002,1003)
The way the dataset is written, it will always omit one batch, which is not a problem, since in essence it is incomplete.
As you are shuffling at the end of each epoch:
if self.shuffle == True:
np.random.shuffle(self.indexes)
the not seen few samples in an epoch will definitely be seen in later epochs.

Can't preprocess data before training for image segmentation

I'm trying to do some image segmentation for ocr, my mask image is a 3 classes image, like this
and my original image is a gray image like this
but when I try to fit the model I get this error
could not broadcast input array from shape (128,128,3) into shape (128,128)
here is the code I'm using to create the datasets
img_size = (128, 128)
batch_size = 32
input_img_paths = sorted(
[ os.path.join(input_dir, fname)
for fname in os.listdir(input_dir)
if fname.endswith(".jpg") ] )
target_img_paths = sorted(
[ os.path.join(target_dir, fname)
for fname in os.listdir(target_dir)
if fname.endswith(".jpg") and not fname.startswith(".") ])
class OxfordPets(keras.utils.Sequence):
"""Helper to iterate over the data (as Numpy arrays)."""
def __init__(self, batch_size, img_size, input_img_paths, target_img_paths):
self.batch_size = batch_size
self.img_size = img_size
self.input_img_paths = input_img_paths
self.target_img_paths = target_img_paths
def __len__(self):
return len(self.target_img_paths) // self.batch_size
def __getitem__(self, idx):
"""Returns tuple (input, target) correspond to batch #idx."""
i = idx * self.batch_size
batch_input_img_paths = self.input_img_paths[i : i + self.batch_size]
batch_target_img_paths = self.target_img_paths[i : i + self.batch_size]
x = np.zeros((batch_size,) + self.img_size, dtype="float32")
for j, path in enumerate(batch_input_img_paths):
img = load_img(path, target_size=self.img_size)
x[j] = img
y = np.zeros((batch_size,) + self.img_size, dtype="float32")
for j, path in enumerate(batch_target_img_paths):
img = load_img(path, target_size=self.img_size, color_mode="rgb")
y[j] = img
return x, y
val_samples = 150
random.Random(1337).shuffle(input_img_paths)
random.Random(1337).shuffle(target_img_paths)
train_input_img_paths = input_img_paths[:-val_samples]
train_target_img_paths = target_img_paths[:-val_samples]
val_input_img_paths = input_img_paths[-val_samples:]
val_target_img_paths = target_img_paths[-val_samples:]
# Instantiate data Sequences for each split
train_gen = OxfordPets(
batch_size, img_size, train_input_img_paths, train_target_img_paths
)
val_gen = OxfordPets(batch_size, img_size, val_input_img_paths, val_target_img_paths)
but when i try to fit whit this
model_history = model.fit(train_gen, epochs=30,
steps_per_epoch=50,
validation_steps=25,
validation_data=val_gen)
I get the error, I am trying to adapt this solution
https://keras.io/examples/vision/oxford_pets_image_segmentation/?fbclid=IwAR2wFYju-N0X7FUaWkhvOVaAAaVqLdOryBwg7xDC0Rji9LQ5F2jYOkeNnns
from keras
into the example of the tensorflow page
https://www.tensorflow.org/tutorials/images/segmentation
and I have the impression that the problem has something to do whit the fact that the original image is on gray scale, how can I solve this error? any advice would be great!
You should convert your image to RGB first. Your image is gray-scaled and has only 1 channel. Its shape is (128,128,1). Them apply sth like opencv: backtorgb = cv2.cvtColor(gray,cv2.COLOR_GRAY2RGB) to every image in your data and everything will be ok
Your mask is RGB and has 3 channels. but your image is grayscale and has one channel. See This question for converting RGB image to grayscale image

Something went wrong with the input pipeline in tensorflow

I am trying to get a batch of 64 images each has [64,224,224,3] dimensions and labels have [64]. There are 8126 _img_class and _img_names. However, I am getting an unexpected output. Basically, I am getting nothing and script never terminate when I run it.
def _get_images(shuffle=True):
"""Gets the images and labels as a batch"""
#get image and label list
_img_names,_img_class = _get_list()
filename_queue = tf.train.string_input_producer(_img_names)
#reader
image_reader = tf.WholeFileReader()
_, image_file = image_reader.read(filename_queue)
#decode jpeg
image_original = tf.image.decode_jpeg(image_file)
label_original = tf.convert_to_tensor(_img_class,dtype=tf.int32)
#image preprocessing
image = tf.image.resize_images(image_original, [224,224])
float_image = tf.cast(image,dtype=tf.float32)
float_image = tf.image.per_image_standardization(image)
#set the shape
float_image.set_shape((224, 224, 3))
label_original.set_shape([8126])
#parameters for shuffle
batch_size = 64
num_preprocess_threads = 16
num_examples_per_epoch = 8000
min_fraction_of_examples_in_queue = 0.4
min_queue_examples = int(num_examples_per_epoch *
min_fraction_of_examples_in_queue)
if shuffle:
images_batch, label_batch = tf.train.shuffle_batch(
[float_image,label_original],
batch_size=batch_size,
num_threads=num_preprocess_threads,
capacity=min_queue_examples + 3 *
batch_size,
min_after_dequeue=min_queue_examples)
else:
images_batch, label_batch = tf.train.batch(
[float_image,label_original],
batch_size=batch_size,
num_threads=num_preprocess_threads,
capacity=min_queue_examples + 3 * batch_size)
return images_batch,label_batch
with tf.Session() as sess:
tf.global_variables_initializer().run()
# Coordinate the loading of image files.
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
images,labels = _get_images(shuffle=True)
# Get an image tensor and print its value.
image_tensor,labels = sess.run([images,labels])
# Finish off the filename queue coordinator.
coord.request_stop()
coord.join(threads)
When I set enqueue_many=True I am getting the following error.
TypeError: 'Tensor' object is not iterable.
You need to start the queue_runners after calling the _get_images function. As queue is defined in that function.
...
images,labels = _get_images(shuffle=True)
tf.global_variables_initializer().run()
tf.local_variables_initializer().run()
# Coordinate the loading of image files.
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
image_tensor,labels = sess.run([images,labels])

Passing two queues to Tensorflow training

I'm trying to create a train operation based on CIFAR10 example from Tensorflow that uses tf.RandomShuffleQueue and my labels comes from the name of the files as mentioned in (Accessing filename from file queue in Tensor Flow). How can I use this code with that?
When I try to run the following code, where path is a directory with many files:
filenames = [path, f) for f in os.listdir(path)][1:]
file_fifo = tf.train.string_input_producer(filenames,
shuffle=False,
capacity=len(filenames))
reader = tf.WholeFileReader()
key, value = reader.read(file_fifo)
image = tf.image.decode_png(value, channels=3, dtype=tf.uint8)
image.set_shape([config.image_height, config.image_width, config.image_depth])
image = tf.cast(image, tf.float32)
image = tf.divide(image, 255.0)
labels = [int(os.path.basename(f).split('_')[-1].split('.')[0]) for f in filenames]
label_fifo = tf.FIFOQueue(len(filenames), tf.int32, shapes=[[]])
label_enqueue = label_fifo.enqueue_many([tf.constant(labels)])
label = label_fifo.dequeue()
bq = tf.RandomShuffleQueue(capacity=16 * batch_size,
min_after_dequeue=8 * batch,
dtypes=[tf.float32, tf.int32])
batch_enqueue_op = bq.enqueue([image, label_enqueue])
runner = tf.train.queue_runner.QueueRunner(bq, [batch_enqueue_op] * num_threads)
tf.train.add_queue_runner(runner)
# Read 'batch' labels + images from the example queue.
images, labels = batch_queue.dequeue_many(FLAGS.batch_size)
labels = tf.reshape(labels, [FLAGS.batch_size, 1])
I get obvious erros, because I know my code doesn't make much sense. I have two FIFO queues file_fifo and label_fifo, but I don't know how to make my label_fifo input of my tf.RandomShuffleQueue.
Can someone help? Thank you :-)
I changed my code to:
filenames = [os.path.join(FLAGS.data_path, f) for f in os.listdir(FLAGS.data_path)][1:]
np.random.shuffle(filenames)
file_fifo = tf.train.string_input_producer(filenames, shuffle=False, capacity=len(filenames))
reader = tf.WholeFileReader()
key, value = reader.read(file_fifo)
image = tf.image.decode_png(value, channels=3, dtype=tf.uint8)
image.set_shape([config.image_height, config.image_width, config.image_depth])
image = tf.cast(image, tf.float32)
image = tf.divide(image, 255.0)
labels = [int(os.path.basename(f).split('_')[-1].split('.')[0]) for f in filenames]
label_fifo = tf.FIFOQueue(len(filenames), tf.int32, shapes=[[]])
label_enqueue = label_fifo.enqueue_many([tf.constant(labels)])
label = label_fifo.dequeue()
if is_train:
images, label_batch = tf.train.shuffle_batch([image, label],
batch_size=FLAGS.batch_size,
num_threads=FLAGS.num_threads,
capacity=16 * FLAGS.batch_size,
min_after_dequeue=8 * FLAGS.batch_size)
labels = tf.reshape(label_batch, [FLAGS.batch_size, 1])
For training I have:
class _LoggerHook(tf.train.SessionRunHook):
"""Logs loss and runtime."""
def begin(self):
self._step = -1
def before_run(self, run_context):
self._step += 1
self._start_time = time.time()
if self._step % int(config.train_examples / FLAGS.batch_size) == 0 or self._step == 0:
run_context.session.run(label_enqueue_op)
return tf.train.SessionRunArgs({'loss': loss, 'net': net})
and I run training as:
with tf.train.MonitoredTrainingSession(
checkpoint_dir=FLAGS.train_path,
hooks=[tf.train.StopAtStepHook(last_step=FLAGS.max_steps), tf.train.NanTensorHook(loss), _LoggerHook()],
config=tf.ConfigProto(log_device_placement=FLAGS.log_device_placement)) as mon_sess:
while not mon_sess.should_stop():
mon_sess.run(train_op)
The training starts, but it runs only for the very first step and hangs - maybe because it's waiting for some queue command

debugging 'TypeError: Can not convert a ndarray into a Tensor or Operation' for CNN

I am trying to build a CNN, I have 8 classes in the input_samples with 45 samples in each class. so total number of input samples are 360. I have divided my first 20 samples as train samples and remaining 25 samples as test samples in each class (My input is a text file and the data is in rows is my preprocessed data, so I am reading the rows in textfile and reshaping the images which are 16x12 size).
I am unable to fix the error in the code
My code:
import numpy as np
import random
import tensorflow as tf
folder = 'D:\\Lab_Project_Files\\TF\\Practice Files\\'
Datainfo = 'dataset_300.txt'
ClassInfo = 'classTrain.txt'
INPUT_WIDTH = 16
IMAGE_HEIGHT = 12
IMAGE_DEPTH = 1
IMAGE_PIXELS = INPUT_WIDTH * IMAGE_HEIGHT # 192 = 12*16
NUM_CLASSES = 8
STEPS = 500
STEP_VALIDATE = 100
BATCH_SIZE = 5
def load_data(file1,file2,folder):
filename1 = folder + file1
filename2 = folder + file2
# loading the data file
x_data = np.loadtxt(filename1, unpack=True)
x_data = np.transpose(x_data)
# loading the class information of the data loaded
y_data = np.loadtxt(filename2, unpack=True)
y_data = np.transpose(y_data)
# divide the data in to test and train data
x_data_train = x_data[np.r_[0:20, 45:65, 90:110, 135:155, 180:200, 225:245, 270:290, 315:335],:]
x_data_test = x_data[np.r_[20:45, 65:90, 110:135, 155:180, 200:225, 245:270, 290:315, 335:360], :]
y_data_train = y_data[np.r_[0:20, 45:65, 90:110, 135:155, 180:200, 225:245, 270:290, 315:335]]
y_data_test = y_data[np.r_[20:45, 65:90, 110:135, 155:180, 200:225, 245:270, 290:315, 335:360],:]
return x_data_train,x_data_test,y_data_train,y_data_test
def reshapedata(data_train,data_test):
data_train = np.reshape(data_train, (len(data_train),INPUT_WIDTH,IMAGE_HEIGHT))
data_test = np.reshape(data_test, (len(data_test), INPUT_WIDTH, IMAGE_HEIGHT))
return data_train,data_test
def batchdata(data,label, batchsize):
# generate random number required to batch data
order_num = random.sample(range(1, len(data)), batchsize)
data_batch = []
label_batch = []
for i in range(len(order_num)):
data_batch.append(data[order_num[i-1]])
label_batch.append(label[order_num[i-1]])
return data_batch, label_batch
# CNN trail
def conv_net(x):
weights = tf.Variable(tf.random_normal([INPUT_WIDTH * IMAGE_HEIGHT * IMAGE_DEPTH, NUM_CLASSES]))
biases = tf.Variable(tf.random_normal([NUM_CLASSES]))
out = tf.add(tf.matmul(x, weights), biases)
return out
sess = tf.Session()
# get filelist and labels for training and testing
data_train,data_test,label_train,label_test = load_data(Datainfo,ClassInfo,folder)
data_train, data_test, = reshapedata(data_train, data_test)
############################ get files for training ####################################################
image_batch, label_batch = batchdata(data_train,label_train,BATCH_SIZE)
# input output placeholders
x = tf.placeholder(tf.float32, [None, IMAGE_PIXELS])
y_ = tf.placeholder(tf.float32,[None, NUM_CLASSES])
# create the network
y = conv_net( x )
# loss
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y, y_))
# train step
train_step = tf.train.AdamOptimizer( 1e-3 ).minimize( cost )
############################## get files for validataion ###################################################
image_batch_test, label_batch_test = batchdata(data_test,label_test,BATCH_SIZE)
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
sess.run(tf.initialize_all_variables())
################ CNN Program ##############################
for i in range(STEPS):
# checking the accuracy in between.
if i % STEP_VALIDATE == 0:
imgs, lbls = sess.run([image_batch_test, label_batch_test])
print(sess.run(accuracy, feed_dict={x: imgs, y_: lbls}))
imgs, lbls = sess.run([image_batch, label_batch])
sess.run(train_step, feed_dict={x: imgs, y_: lbls})
imgs, lbls = sess.run([image_batch_test, label_batch_test])
print(sess.run(accuracy, feed_dict={ x: imgs, y_: lbls}))
file can be downloaded dataset_300.txt and ClassInfo.txt
Session.run accepts only a list of tensors or tensor names.
imgs, lbls = sess.run([image_batch_test, label_batch_test])
In the previous line, you are passing image_batch_test and label_batch_test which are numpy arrays. I am not sure what you are trying to do by imgs, lbls = sess.run([image_batch_test, label_batch_test])