Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use TensorFlow Dataset API in combination with dense layers

I am trying out the Dataset API for my input pipeline shown in the TensorFlow documentation and use almost the same code:

tr_data = Dataset.from_tensor_slices((train_images, train_labels))
tr_data = tr_data.map(input_parser, NUM_CORES, output_buffer_size=2000)
tr_data = tr_data.batch(BATCH_SIZE)
tr_data = tr_data.repeat(EPOCHS)

iterator = dataset.make_one_shot_iterator()
next_example, next_label = iterator.get_next()

# Script throws error here
loss = model_function(next_example, next_label)

with tf.Session(...) as sess:
    sess.run(tf.global_variables_initializer())

     while True:
        try:
            train_loss = sess.run(loss)
        except tf.errors.OutOfRangeError:
            print("End of training dataset.")
            break

This should be faster since it avoids using the slow feed_dicts. But I can't make it work with my model, which is a simplified LeNet architecture. The problem is the tf.layers.dense in my model_function() which expects an known input shape (I guess because it has to know the number of weights beforehand). But next_example and next_label only get their shape by running them in the session. Before evaluating them their shape is just undefined ?

Declaring the model_function() throws this error:

ValueError: The last dimension of the inputs to Dense should be defined. Found None.

Right now, I don't know if I am using this Dataset API in the intended way or if there is a workaround.

Thanks in advance!

Edit 1: Below is my model and it throws the error at the first dense layer

def conv_relu(input, kernel_shape):
    # Create variable named "weights".
    weights = tf.get_variable("weights", kernel_shape,
        initializer=tf.random_normal_initializer())
    # Create variable named "biases".
    biases = tf.get_variable("biases", kernel_shape[3],
        initializer=tf.constant_initializer(0.0))
    conv = tf.nn.conv2d(input, weights,
        strides=[1, 1, 1, 1], padding='VALID')
    return tf.nn.relu(conv + biases)

def fully(input, output_dim):
    assert len(input.get_shape())==2, 'Wrong input shape, need flattened tensor as input'
    input_dim = input.get_shape()[1]

    weight = tf.get_variable("weight", [input_dim, output_dim],
        initializer=tf.random_normal_initializer())
    bias = tf.get_variable('bias', [output_dim],
        initializer=tf.random_normal_initializer())

    fully = tf.nn.bias_add(tf.matmul(input, weight), bias)
    return fully


def simple_model(x):

    with tf.variable_scope('conv1'):
        conv1 = conv_relu(x, [3,3,1,10])
        conv1 = tf.nn.max_pool(conv1,[1,2,2,1],[1,2,2,1],'SAME')

    with tf.variable_scope('conv2'):
        conv2 = conv_relu(conv1, [3,3,10,10])
        conv2 = tf.nn.max_pool(conv2,[1,2,2,1],[1,2,2,1],'SAME')

    with tf.variable_scope('conv3'):
        conv3 = conv_relu(conv2, [3,3,10,10])
        conv3 = tf.nn.max_pool(conv3,[1,2,2,1],[1,2,2,1],'SAME')

    flat = tf.contrib.layers.flatten(conv3)
    with tf.variable_scope('fully1'):
        fully1 = tf.layers.dense(flat, 1000)
        fully1 = tf.nn.relu(fully1)

    with tf.variable_scope('fully2'):
        fully2 = tf.layers.dense(fully1, 100)
        fully2 = tf.nn.relu(fully2)

    with tf.variable_scope('output'):
        output = tf.layers.dense(fully2, 4)
        fully1 = tf.nn.relu(output)


    return output

Edit 2:

Here you see the print of the tensors. Notice that next_example does not have a shape

next_example: Tensor("IteratorGetNext:0", dtype=float32)
next_label: Tensor("IteratorGetNext:1", shape=(?, 4), dtype=float32)

like image 974
KonArtist Avatar asked Sep 14 '17 14:09

KonArtist


People also ask

Which are the three main methods of getting data into a TensorFlow program?

TensorFlow's Basic Programming Elements TensorFlow allows us to assign data to three kinds of data elements: constants, variables, and placeholders. Let's take a closer look at what each of these data components represents.

Which API is used to build performant complex input pipelines from simple re usable pieces that will feed your model's training or evaluation loops?

Dataset API to build a pipeline for feeding data to your model. tf. data. Dataset is used to build performant, complex input pipelines from simple, re-usable pieces that will feed your model's training or evaluation loops.

What is dataset in TensorFlow?

TensorFlow Datasets is a collection of datasets ready to use, with TensorFlow or other Python ML frameworks, such as Jax. All datasets are exposed as tf. data. Datasets , enabling easy-to-use and high-performance input pipelines. To get started see the guide and our list of datasets.

What is TensorFlow prefetch?

Prefetching. Prefetching overlaps the preprocessing and model execution of a training step. While the model is executing training step s , the input pipeline is reading the data for step s+1 . Doing so reduces the step time to the maximum (as opposed to the sum) of the training and the time it takes to extract the data ...


1 Answers

I found the answer myself.

Following this thread the easy fix is to just set the shape with tf.Tensor.set_shape if you know your image sizes beforehand.

def input_parser(img_path, label):

    # read the img from file
    img_file = tf.read_file(img_path)
    img_decoded = tf.image.decode_image(img_file, channels=1)
    img_decoded = tf.image.convert_image_dtype(img_decoded, dtype=tf.float32)
    img_decoded.set_shape([90,160,1]) # This line was missing

    return img_decoded, label

It would have been nice if the tensorflow documentation included this line.

like image 156
KonArtist Avatar answered Sep 28 '22 05:09

KonArtist