Use Tfrecord to feed multi-input neural network - tensorflow

I have a dataset on Tfrecord that includes images and tabular data, I want to feed those data into a mixed neural network data. I saw examples of how to use multi-input neural network by using numpy arrays
model.fit([X_images,X_tabular],[Y_images,Y_tabular])
but transforming Tfrecord dataset into a numpy array by iterating slows down the process.
Is there a way to train it directly on the Tfrecord data. So far I have a model that train only an images and this is the code that I am using
tfrecords_schema = {
'id': tf.io.FixedLenFeature([], tf.string),
'y_label': tf.io.FixedLenFeature([], tf.int64),
'image': tf.io.FixedLenFeature([], tf.string),
'x_1': tf.io.FixedLenFeature([], tf.float32),
'x_2': tf.io.FixedLenFeature([], tf.float32),
'x_3': tf.io.FixedLenFeature([], tf.int64),
'x_4': tf.io.FixedLenFeature([], tf.int64),
}
def _parse_function(example_proto):
parsed_example = tf.io.parse_single_example(example_proto, tfrecords_schema)
return parsed_example['image'], parsed_example['y_label']
def _parse_error(image, label):
return image != b''
def _preprocess_function(image, label):
image = tf.image.decode_jpeg(image)
image = tf.image.resize(image, (299, 299))
label = label_decoder(label)
return image, label
train_data = (
train_data
.map(_parse_function)
.filter(_parse_error)
.map(_preprocess_function)
.apply(tf.data.experimental.ignore_errors())
.batch(BATCH_SIZE)
)
validation_data = (
validation_data
.map(_parse_function)
.filter(_parse_error)
.map(_preprocess_function)
.apply(tf.data.experimental.ignore_errors())
.batch(BATCH_SIZE)
)
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_data = train_data.prefetch(buffer_size=AUTOTUNE)
validation_data = validation_data.prefetch(buffer_size=AUTOTUNE)
def make_model(image_shape, num_classes):
inputs = tf.keras.Input(shape=image_shape)
x = tf.keras.applications.inception_v3.preprocess_input(inputs)
base_model = tf.keras.applications.InceptionV3(input_shape=IMAGE_SHAPE, include_top=False, weights='imagenet')
base_model.trainable = False
x = base_model(x, training=False)
global_average_layer = tf.keras.layers.GlobalAveragePooling2D()
x = global_average_layer(x)
x = tf.keras.layers.Dropout(0.3)(x)
prediction_layer = tf.keras.layers.Dense(num_classes)
outputs = prediction_layer(x)
return tf.keras.Model(inputs, outputs)
model = make_model(IMAGE_SHAPE, NUM_CLASSES)
learning_rate = 0.0001
model.compile(
optimizer=tf.keras.optimizers.Adam(lr=learning_rate),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=["accuracy"]
)
callbacks = [
tf.keras.callbacks.ModelCheckpoint(filepath="tf/pvc_data/tmp/weights.hdf5", verbose=1, save_best_only=True)
]
history = model.fit(
train_data, epochs=1, callbacks=callbacks, validation_data=validation_data
)

Related

ValueError: Input 0 of layer is incompatible with the layer: expected shape=(None, 224, 224, 3), found shape=(224, 224, 3)

"after converting the dataset to the tfrecord file format, I tried to train the model I created with it, but I couldn't convert it to the input format suitable for the model. image shape (224,224.3).
The model has already passed through the pre-processing layers
The image cannot be converted to the correct shape for the model's input
import matplotlib.pylab as plt
import numpy as np
import tensorflow as tf
import keras
IMG_HEIGHT = 224
IMG_WIDTH = 224
IMG_CHANNELS = 3
def decode_image(image, shape=None):
image = tf.image.decode_jpeg(image, channels=3)
image = tf.cast(image, dtype=tf.float32)
image = tf.convert_to_tensor(image, dtype=np.float32)
return image
def parse_tfrecord(example):
feature_description = {
"image" : tf.io.FixedLenFeature([], tf.string),
"height" : tf.io.FixedLenFeature([], tf.int64),
"width" : tf.io.FixedLenFeature([], tf.int64),
"depht" : tf.io.FixedLenFeature([], tf.int64),
"shape" : tf.io.VarLenFeature(tf.int64),
"label" : tf.io.FixedLenFeature([], tf.string, default_value=""),
"label_index" : tf.io.FixedLenFeature([], tf.int64)
}
example = tf.io.parse_single_example(example, feature_description)
# tf.sparse.to_dense(example["shape"]
image = decode_image(example["image"], [224,224,3])
# image = tf.image.decode_jpeg(example["image"], [224,224,3])
label_index = tf.cast(example["label_index"], tf.int32)
image = tf.reshape(image, (224,224,3))
# label_indx = rec["label_index"]
return image, label_index
def preprocess(image, label_index):
prepro_image = tf.expand_dims(image, 0)
prepro_image = keras.layers.Resizing(224 , 224, crop_to_aspect_ratio=True, input_shape=(224,224,3))(prepro_image)
prepro_image = keras.layers.Rescaling(1./255)(prepro_image)
prepro_image = keras.layers.RandomFlip(mode="horizontal_and_vertical")(prepro_image)
prepro_image = tf.squeeze(prepro_image, 0)
return prepro_image, label_index
batch_size = 32
epochs = 1
steps_per_epoch = 50
AUTOTUNE = tf.data.AUTOTUNE
def create_preproc_dataset(pattern):
trainds = tf.data.TFRecordDataset(pattern).map(parse_tfrecord).map(preprocess).shuffle(25)
return trainds
trainds = create_preproc_dataset("valid_tfrecords")
NUM_EPOCHS = 25
IMG_HEIGHT = 224
IMG_WIDTH = 224
IMG_CHANNELS = 3
CLASS_NAMES = 'bluebel buttercup crocus daffodil daisy dandelion iris lilyvalley pansy snowdrop sunflowers tulip'.split()
def train_and_evaluate(batch_size = 32,
lrate = 0.001,
l1 = 0.,
l2 = 0.,
num_hidden = 16):
regularizer = tf.keras.regularizers.l1_l2(l1, l2)
train_dataset = create_preproc_dataset(
'train_tfrecord')
eval_dataset = create_preproc_dataset(
'valid_tfrecord')
layers = [
# input layer
# image preprocessing layers
# keras.layers.Resizing(height=224, width=224,crop_to_aspect_ratio=True, input_shape=(224,224,3)),
#keras.layers.RandomFlip(mode="horizontal_and_vertical", name='random_lr_flip/none'),
#RandomColorDistortion(name='random_contrast_brightness/none'),
# core layers
keras.layers.Conv2D(32, 3, activation="relu", input_shape=(224, 224, 3)),
keras.layers.MaxPooling2D(pool_size=2),
keras.layers.Conv2D(64, 3, activation="relu"),
keras.layers.MaxPooling2D(pool_size=2),
keras.layers.Conv2D(128, 3, activation="relu"),
keras.layers.MaxPooling2D(pool_size=2),
keras.layers.Conv2D(256, 3, activation="relu"),
keras.layers.MaxPooling2D(pool_size=2),
# flatten layers
keras.layers.Flatten(),
keras.layers.Dense(num_hidden, activation="relu"),
keras.layers.Dropout(0.5),
# output layers
keras.layers.Dense(12, activation="softmax")
]
# checkpoint and early stopping callbacks
model_checkpoint_cb = keras.callbacks.ModelCheckpoint(
filepath="\work_images\chkpts",monitor = "val_accuracy", mode="max",
save_best_only=True)
early_stopping_cb = keras.callbacks.EarlyStopping(
monitor="val_accuracy", mode="max",
patience=2)
# model training
model = tf.keras.Sequential(layers, name='flower_classification')
model.build([ 224, 224, 3])
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=lrate),
loss=tf.keras.losses.CategoricalCrossentropy(
from_logits=False),
metrics=['accuracy'])
print(model.summary())
history = model.fit(train_dataset, validation_data=eval_dataset,
epochs=NUM_EPOCHS,
callbacks=[model_checkpoint_cb, early_stopping_cb])
training_plot(['loss', "accuracy"], history)
return model
model = train_and_evaluate()
Replace this
def create_preproc_dataset(pattern):
trainds = tf.data.TFRecordDataset(pattern).map(parse_tfrecord).map(preprocess).shuffle(25)
return trainds
with this
def create_preproc_dataset(pattern):
trainds = tf.data.TFRecordDataset(pattern).map(parse_tfrecord).map(preprocess).shuffle(25).batch(32)
return trainds
and changing the loss to SparseCategoricalCrossentropy will help.
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=lrate),
loss=tf.keras.losses.SparseCategoricalCrossentropy(
from_logits=False),
metrics=['accuracy'])

TFrecord pre-process data before feeding to a model

I have a TFrecord file that consist of such features
features = {
'features': tf.FixedLenFeature([17920], tf.float32),
'video_id': tf.FixedLenFeature([], tf.string),
'split_id': tf.FixedLenFeature([], tf.int64),
'audio': tf.FixedLenFeature([44100], tf.float32)
}
The way I currently get the iterator is as such:
def getiterator(batch_size, decode_parallel_calls=1,repeat=False,
shuffle=False,
shuffle_buffer_size=None,
prefetch_size=None,
prefetch_gpu_num=None):
dataset = tf.data.TFRecordDataset(['../main.tfrecords'])
# Shuffle all filepaths every epoch
if shuffle:
dataset = dataset.shuffle(buffer_size=sum(1 for _ in tf.python_io.tf_record_iterator('../main.tfrecords')))
# Repeat
if repeat:
dataset = dataset.repeat()
# Shuffle examples
if shuffle:
dataset = dataset.shuffle(buffer_size=shuffle_buffer_size)
def extract_fn(data_record):
features = {
'features': tf.FixedLenFeature([17920], tf.float32),
'video_id': tf.FixedLenFeature([], tf.string),
'split_id': tf.FixedLenFeature([], tf.int64),
'audio': tf.FixedLenFeature([44100], tf.float32)
}
return tf.parse_single_example(data_record, features)
dataset = dataset.map(extract_fn, num_parallel_calls=decode_parallel_calls)
# Make batches
dataset = dataset.batch(batch_size, drop_remainder=True)
# Get tensors
iterator = dataset.make_one_shot_iterator()
return iterator.get_next()
One thing that I am interested in doing is preprocessing the audio data by downsampling to 16000Hz. However, I am not sure how to do it so as I currently only get Tensors. What would be a good approach?
You could simply place your downsampling logic inside extract_fn.
def extract_fn(data_record):
features = {
'features': tf.FixedLenFeature([17920], tf.float32),
'video_id': tf.FixedLenFeature([], tf.string),
'split_id': tf.FixedLenFeature([], tf.int64),
'audio': tf.FixedLenFeature([44100], tf.float32)
}
features_in = tf.parse_single_example(data_record, features)
# This is your audio tensor before downsampling.
audio_tensor = features_in['audio']
# Doing something to downsample audio_tensor
downsampled_audio_tensor = do_something(audio_tensor)
# Now I assume you need every other tensors as is, but replace the audio with
# the one we downsampled above.
features_out = {
'features': features_in['features'],
'video_id': features_in['video_id'],
'split_id': features_in['split_id'],
'audio': downsampled_audio_tensor,
}
return features_out

Create SavedModel for BERT

I'm using this Colab for BERT model.
In last cells in order to make predictions we have:
def getPrediction(in_sentences):
labels = ["Negative", "Positive"]
input_examples = [run_classifier.InputExample(guid="", text_a = x, text_b = None, label = 0) for x in in_sentences] # here, "" is just a dummy label
input_features = run_classifier.convert_examples_to_features(input_examples, label_list, MAX_SEQ_LENGTH, tokenizer)
predict_input_fn = run_classifier.input_fn_builder(features=input_features, seq_length=MAX_SEQ_LENGTH, is_training=False, drop_remainder=False)
predictions = estimator.predict(predict_input_fn)
return [(sentence, prediction['probabilities'], labels[prediction['labels']]) for sentence, prediction in zip(in_sentences, predictions)]
pred_sentences = [
"That movie was absolutely awful",
"The acting was a bit lacking",
"The film was creative and surprising",
"Absolutely fantastic!"
]
predictions = getPrediction(pred_sentences)
I want to create a 'SavedModel' to be used with TF serving. How to create a SavedModel for this model?
Normally I would define the following:
def serving_input_fn():
"""Create serving input function to be able to serve predictions later
using provided inputs
:return:
"""
feature_placeholders = {
'sentence': tf.placeholder(tf.string, [None]),
}
return tf.estimator.export.ServingInputReceiver(feature_placeholders,
feature_placeholders)
latest_ckpt = tf.train.latest_checkpoint(OUTPUT_DIR)
last_eval = estimator.evaluate(input_fn=test_input_fn, steps=None, checkpoint_path=latest_ckpt)
# Export the model to GCS for serving.
exporter = tf.estimator.LatestExporter('exporter', serving_input_fn, exports_to_keep=None)
exporter.export(estimator, OUTPUT_DIR, latest_ckpt, last_eval, is_the_final_export=True)
Not sure how to define my tf.estimator.export.ServingInputReceiver
If you look at create_model function present in notebook. It takes some arguments. These are the features which will be passed to the model.
You need to update the serving_input_fn function to include them.
def serving_input_fn():
feature_spec = {
"input_ids" : tf.FixedLenFeature([MAX_SEQ_LENGTH], tf.int64),
"input_mask" : tf.FixedLenFeature([MAX_SEQ_LENGTH], tf.int64),
"segment_ids" : tf.FixedLenFeature([MAX_SEQ_LENGTH], tf.int64),
"label_ids" : tf.FixedLenFeature([], tf.int64)
}
serialized_tf_example = tf.placeholder(dtype=tf.string,
shape=[None],
name='input_example_tensor')
receiver_tensors = {'example': serialized_tf_example}
features = tf.parse_example(serialized_tf_example, feature_spec)
return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)

Tensorflow, read tfrecord without a graph

I tried to write a good structured Neural network model with Tensorflow. But I met a problem about feed the data from tfrecord into the graph. The code is as below, it hangs on at the following function, how can I make it work?
images, labels = network.load_tfrecord_data(1)
this function can not get the features (images) and labels from my datafile, .tfrecords?
Any idea will be appreciated?
from __future__ import division
from __future__ import print_function
import datetime
import numpy as np
import tensorflow as tf
layers = tf.contrib.layers
losses = tf.contrib.losses
metrics = tf.contrib.metrics
LABELS = 10
WIDTH = 28
HEIGHT = 28
HIDDEN = 100
def read_and_decode_single_example(filename):
filename_queue = tf.train.string_input_producer([filename], num_epochs=None)
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
features = tf.parse_single_example(
serialized_example,
features={
'label': tf.FixedLenFeature([], tf.int64),
'image': tf.FixedLenFeature([50176], tf.int64)
})
label = features['label']
image = features['image']
image = tf.reshape(image, [-1, 224, 224, 1])
label = tf.one_hot(label - 1, 11, dtype=tf.int64)
return label, image
class Network:
def __init__(self, logdir, experiment, threads):
# Construct the graph
with tf.name_scope("inputs"):
self.images = tf.placeholder(tf.float32, [None, WIDTH, HEIGHT, 1], name="images")
self.labels = tf.placeholder(tf.int64, [None], name="labels")
# self.keep_prob = keep_prob
self.keep_prob = tf.placeholder(tf.float32, name="keep_prob")
flattened_images = layers.flatten(self.images)
hidden_layer = layers.fully_connected(flattened_images, num_outputs=HIDDEN, activation_fn=tf.nn.relu, scope="hidden_layer")
output_layer = layers.fully_connected(hidden_layer, num_outputs=LABELS, activation_fn=None, scope="output_layer")
loss = losses.sparse_softmax_cross_entropy(labels=self.labels, logits=output_layer, scope="loss")
self.training = layers.optimize_loss(loss, None, None, tf.train.AdamOptimizer(), summaries=['loss', 'gradients', 'gradient_norm'], name='training')
with tf.name_scope("accuracy"):
predictions = tf.argmax(output_layer, 1, name="predictions")
accuracy = metrics.accuracy(predictions, self.labels)
tf.summary.scalar("training/accuracy", accuracy)
self.accuracy = metrics.accuracy(predictions, self.labels)
with tf.name_scope("confusion_matrix"):
confusion_matrix = metrics.confusion_matrix(predictions, self.labels, weights=tf.not_equal(predictions, self.labels), dtype=tf.float32)
confusion_image = tf.reshape(confusion_matrix, [1, LABELS, LABELS, 1])
# Summaries
self.summaries = {'training': tf.summary.merge_all() }
for dataset in ["dev", "test"]:
self.summaries[dataset] = tf.summary.scalar(dataset + "/loss", loss)
self.summaries[dataset] = tf.summary.scalar(dataset + "/accuracy", accuracy)
self.summaries[dataset] = tf.summary.image(dataset + "/confusion_matrix", confusion_image)
# Create the session
self.session = tf.Session(config=tf.ConfigProto(inter_op_parallelism_threads=threads,
intra_op_parallelism_threads=threads))
self.session.run(tf.global_variables_initializer())
timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H%M%S")
self.summary_writer = tf.summary.FileWriter("{}/{}-{}".format(logdir, timestamp, experiment), graph=self.session.graph, flush_secs=10)
self.steps = 0
def train(self, images, labels, keep_prob):
self.steps += 1
feed_dict = {self.images: self.session.run(images), self.labels: self.session.run(labels), self.keep_prob: keep_prob}
if self.steps == 1:
metadata = tf.RunMetadata()
self.session.run(self.training, feed_dict, options=tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE), run_metadata=metadata)
self.summary_writer.add_run_metadata(metadata, 'step1')
elif self.steps % 100 == 0:
_, summary = self.session.run([self.training, self.summaries['training']], feed_dict)
self.summary_writer.add_summary(summary, self.steps)
else:
self.session.run(self.training, feed_dict)
def evaluate(self, dataset, images, labels):
feed_dict ={self.images: images, self.labels: labels, self.keep_prob: 1}
summary = self.summaries[dataset].eval({self.images: images, self.labels: labels, self.keep_prob: 1}, self.session)
self.summary_writer.add_summary(summary, self.steps)
def load_tfrecord_data(self, training):
training = training
if training:
label, image = read_and_decode_single_example("mhad_Op_train.tfrecords")
# print(self.session.run(image))
else:
label, image = read_and_decode_single_example("mhad_Op_test.tfrecords")
# image = tf.cast(image, tf.float32) / 255.
images_batch, labels_batch = tf.train.shuffle_batch(
[image, label], batch_size=50, num_threads=2,
capacity=80,
min_after_dequeue=30)
return images_batch, labels_batch
if __name__ == '__main__':
# Fix random seed
np.random.seed(42)
tf.set_random_seed(42)
# Parse arguments
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--batch_size', default=256, type=int, help='Batch size.')
parser.add_argument('--epochs', default=50, type=int, help='Number of epochs.')
parser.add_argument('--logdir', default="logs", type=str, help='Logdir name.')
parser.add_argument('--exp', default="mnist-final-confusion_matrix_customized_loss", type=str, help='Experiment name.')
parser.add_argument('--threads', default=1, type=int, help='Maximum number of threads to use.')
args = parser.parse_args()
# Load the data
keep_prob = 1
# Construct the network
network = Network(logdir=args.logdir, experiment=args.exp, threads=args.threads)
# Train
for i in range(args.epochs):
images, labels = network.load_tfrecord_data(1)
network.train(images, labels, keep_prob)
print('current epoch', i)
You need to start the queue before using images, labels in your model.
with tf.Session() as sess:
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
images, labels = network.load_tfrecord_data(1)
...
coord.request_stop()
coord.join(threads)
Check this tutorial for a full example

make tf.Estimator use default graph

I am trying to make use of tensorflow protobuffer feeding pipeline. The easiest way seemed to use tf.estimator.Estimator with tf.contrib.data.TFRecordDataset. However, I came across the issue that it creates a new Graph in spite of being launched within with g.as_default(). In following code I see that both model tensors and tensors returned by the TFRecordDataset are the same before I feed them to Estimator, but become different within the Estimator. Any ideas how to put them on the same graph?
# coding: utf-8
import sys
import tensorflow as tf
from keras.applications.inception_v3 import InceptionV3
import numpy as np
final_activation='linear'
g = tf.Graph()
with g.as_default():
model = InceptionV3(weights='imagenet',
include_top=True,
input_tensor=None,
input_shape=None,
pooling=None,
classes=1000)
def model_fn(mode, features, labels, params):
optimizer = params["optimizer"]
opt_params= params.get("opt_params", {})
predictions = model(features)
if (mode == tf.estimator.ModeKeys.TRAIN or
mode == tf.estimator.ModeKeys.EVAL):
loss = tf.contrib.keras.backend.categorical_crossentropy(predictions, labels)
#loss = tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=logyhat)
else:
loss = None
if mode == tf.estimator.ModeKeys.TRAIN:
optimizer = getattr(tf.train, optimizer)
train_op = optimizer(opt_params).minimize(loss)
else:
train_op = None
return tf.estimator.EstimatorSpec(
mode=mode,
predictions=predictions,
loss=loss,
train_op=train_op)
def parser(record):
keys_to_features = {
'height': tf.FixedLenFeature([], tf.int64),
'width': tf.FixedLenFeature([], tf.int64),
'image_raw': tf.FixedLenFeature([], tf.string),
'label': tf.FixedLenFeature([], tf.int64)
}
features = tf.parse_single_example(
record,
features=keys_to_features)
# Convert from a scalar string tensor to a uint8 tensor
image = tf.decode_raw(features['image_raw'], tf.float32)
height = tf.cast(features['height'], tf.int32)
width = tf.cast(features['width'], tf.int32)
image_shape = tf.stack([height, width, 3])
image = tf.reshape(image, image_shape)
label = tf.cast(features["label"], tf.int32)
return image, label
def get_dataset_inp_fn(filenames, epochs=20):
def dataset_input_fn():
dataset = tf.contrib.data.TFRecordDataset(filenames)
# Use `Dataset.map()` to build a pair of a feature dictionary and a label
# tensor for each example.
dataset = dataset.map(parser)
dataset = dataset.shuffle(buffer_size=10000)
dataset = dataset.batch(32)
dataset = dataset.repeat(epochs)
iterator = dataset.make_one_shot_iterator()
features, labels = iterator.get_next()
return features, labels
return dataset_input_fn
inpfun = get_dataset_inp_fn(["mydataset.tfrecords"], epochs=20)
x,y = inpfun()
print("X", x.graph)
print("DEFAULT", g)
print("MODEL", model.input.graph)
# everything is on the same graph
if not x.graph is tf.get_default_graph():
raise ValueError()
with tf.Session(graph=g) as sess:
est = tf.estimator.Estimator(
model_fn,
model_dir=None,
config=None,
params={"optimizer": "AdamOptimizer",
"opt_params":{}}
)
est.train(inpfun)