buiquangdinh
buiquangdinh

Reputation: 51

got shape [4575, 32, 32, 3], but wanted [4575] Tensorflow

I'm a newbie of Tensorflow. I have created CNNs of Tensorflow followingthis topic : A Guide to TF Layers: Building a Convolutional Neural Network

I want to create CNNs to using it for training traffic sign dataset. The dataset I use is : BelgiumTS. It includes two part, one part stores images for training, second parth stores images for testing. All of this is .ppm format.

I define a method to load the dataset :

def load_data(data_dir):
"""Load Data and return two numpy array"""
directories = [d for d in os.listdir(data_dir) if os.path.isdir(os.path.join(data_dir,d))]

list_labels = []
list_images = []

for d in directories:
    label_dir = os.path.join(data_dir,d)
    file_names = [os.path.join(label_dir,f) for f in os.listdir(label_dir) if f.endswith(".ppm")]

    for f in file_names:
        list_images.append(skimage.data.imread(f))
        list_labels.append(int(d))
 #resize images to 32x32 pixel       
list_images32 = [skimage.transform.resize(image,(32,32)) for image in list_images]

#Got Error "Value passed to parameter 'input' has DataType float64 not in list of allowed values: float16, float32" if I don't add this line
list_images32 = tf.cast(list_images32,tf.float32)

images = np.array(list_images32)
labels = np.asarray(list_labels,dtype=int32)

return images,labels

And this is CNNs define :

def cnn_model_fn(features, labels, mode):
#Input layer
input_layer = tf.reshape(features["x"],[-1,32,32,1])

#Convolutional layer 1
conv1 = tf.layers.conv2d(
    inputs=input_layer,
    filters=32,
    kernel_size=[5,5],
    padding="same",
    activation=tf.nn.relu)

#Pooling layer 1
pool1 = tf.layers.max_pooling2d(inputs=conv1,pool_size=[2,2],strides=2)

#Convolutional layer 2
conv2 = tf.layers.conv2d(
    inputs=pool1,
    filters=64,
    kernel_size=[5,5],
    padding="same",
    activation=tf.nn.relu)

#Pooling layer 2
pool2 = tf.layers.max_pooling2d(inputs=conv2,pool_size=[2,2],strides=2)

#Dense layer
pool2_flat = tf.reshape(pool2,[-1,7*7*64])
dense = tf.layers.dense(inputs=pool2_flat,units=1024,activation=tf.nn.relu)

#Dropout
dropout = tf.layers.dropout(inputs=dense,rate=0.4,training=mode == tf.estimator.ModeKeys.TRAIN)

#Logits layer
logits = tf.layers.dense(inputs=dropout,units=10)

predictions = {
    "classes": tf.argmax(input=logits,axis=1),
    "probabilities": tf.nn.softmax(logits,name="softmax_tensor")
    }

if mode == tf.estimator.ModeKeys.PREDICT:
    return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions)

#Calculate Loss Value
onehot_labels = tf.one_hot(indices=tf.cast(labels,tf.int32),depth=10)
loss = tf.losses.softmax_cross_entropy(onehot_labels=onehot_labels,logits=logits)

if mode == tf.estimator.ModeKeys.TRAIN:
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
    train_op = optimizer.minimize(
        loss = loss,
        global_step = tf.train.get_global_step())
    return tf.estimator.EstimatorSpec(mode=mode,loss=loss,train_op=train_op)

eval_metric_ops = {
    "accuracy": tf.metrics.accuracy(
        labels=labels,predictions=predictions["classes"])}
return tf.estimator.EstimatorSpec(mode=mode,loss=loss,eval_metric_ops=eval_metric_ops)

I run my app in main :

def main(unused_argv):
   # Load training and eval data
   train_data_dir = "W:/Projects/AutoDrive/Training"
   test_data_dir = "W:/Projects/AutoDrive/Testing"

   images,labels = load_data(train_data_dir) 
   test_images,test_labels = load_data(test_data_dir)


   # Create the Estimator
   autoDrive_classifier = tf.estimator.Estimator(
  model_fn=cnn_model_fn, model_dir="/tmp/autoDrive_convnet_model")

   # Set up logging for predictions
   # Log the values in the "Softmax" tensor with label "probabilities"
   tensors_to_log = {"probabilities": "softmax_tensor"}
   logging_hook = tf.train.LoggingTensorHook(
  tensors=tensors_to_log, every_n_iter=50)

   # Train the model
   train_input_fn = tf.estimator.inputs.numpy_input_fn(
                               x={"x": images},
                               y=labels,
                               batch_size=100,
                               num_epochs=None,
                               shuffle=True)
   autoDrive_classifier.train(
            input_fn=train_input_fn,
            steps=10000,
            hooks=[logging_hook])

   # Evaluate the model and print results
   eval_input_fn = tf.estimator.inputs.numpy_input_fn(
                              x={"x": test_images},
                              y=test_labels,
                              num_epochs=1,
                              shuffle=False)
   eval_results = autoDrive_classifier.evaluate(input_fn=eval_input_fn)
   print(eval_results)

But when I run it, I got this error : ValueError: Argument must be a dense tensor ... got shape [4575, 32, 32, 3], but wanted [4575] Did I lost something ?

Finally, this is full code :

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import numpy as np
import tensorflow as tf
import os
import skimage.data
import skimage.transform
import matplotlib
import matplotlib.pyplot as plt

tf.logging.set_verbosity(tf.logging.INFO)

def load_data(data_dir):
    """Load Data and return two lists"""
    directories = [d for d in os.listdir(data_dir) if 
    os.path.isdir(os.path.join(data_dir,d))]

    list_labels = []
    list_images = []

    for d in directories:
        label_dir = os.path.join(data_dir,d)
        file_names = [os.path.join(label_dir,f) for f in os.listdir(label_dir) if f.endswith(".ppm")]

    for f in file_names:
        list_images.append(skimage.data.imread(f))
        list_labels.append(int(d))

    list_images32 = [skimage.transform.resize(image,(32,32)) for image in list_images]
    list_images32 = tf.cast(list_images32,tf.float32)
    images = np.array(list_images32)
    labels = np.asarray(list_labels,dtype=int32)

    return images,labels

def cnn_model_fn(features, labels, mode):
    #Input layer
    input_layer = tf.reshape(features["x"],[-1,32,32,1])

    #Convolutional layer 1
    conv1 = tf.layers.conv2d(
    inputs=input_layer,
    filters=32,
    kernel_size=[5,5],
    padding="same",
    activation=tf.nn.relu)

   #Pooling layer 1
   pool1 = tf.layers.max_pooling2d(inputs=conv1,pool_size=[2,2],strides=2)

   #Convolutional layer 2
   conv2 = tf.layers.conv2d(
    inputs=pool1,
    filters=64,
    kernel_size=[5,5],
    padding="same",
    activation=tf.nn.relu)

  #Pooling layer 2
  pool2 = tf.layers.max_pooling2d(inputs=conv2,pool_size=[2,2],strides=2)

  #Dense layer
  pool2_flat = tf.reshape(pool2,[-1,7*7*64])
  dense = tf.layers.dense(inputs=pool2_flat,units=1024,activation=tf.nn.relu)

  #Dropout
  dropout = tf.layers.dropout(inputs=dense,rate=0.4,training=mode == tf.estimator.ModeKeys.TRAIN)

  #Logits layer
  logits = tf.layers.dense(inputs=dropout,units=10)

  predictions = {
    "classes": tf.argmax(input=logits,axis=1),
    "probabilities": tf.nn.softmax(logits,name="softmax_tensor")
    }

  if mode == tf.estimator.ModeKeys.PREDICT:
    return tf.estimator.EstimatorSpec(mode=mode,predictions=predictions)

  #Calculate Loss Value
  onehot_labels = tf.one_hot(indices=tf.cast(labels,tf.int32),depth=10)
  loss = tf.losses.softmax_cross_entropy(onehot_labels=onehot_labels,logits=logits)

  if mode == tf.estimator.ModeKeys.TRAIN:
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
    train_op = optimizer.minimize(
        loss = loss,
        global_step = tf.train.get_global_step())
    return tf.estimator.EstimatorSpec(mode=mode,loss=loss,train_op=train_op)

  eval_metric_ops = {
    "accuracy": tf.metrics.accuracy(
        labels=labels,predictions=predictions["classes"])}
  return tf.estimator.EstimatorSpec(mode=mode,loss=loss,eval_metric_ops=eval_metric_ops)


  def main(unused_argv):
      # Load training and eval data
      train_data_dir = "W:/Projects/TSRecognition/Training"
      test_data_dir = "W:/Projects/TSRecognition/Testing"

      images,labels = load_data(train_data_dir) 
      test_images,test_labels = load_data(test_data_dir)


      # Create the Estimator
      TSRecognition_classifier = tf.estimator.Estimator(
      model_fn=cnn_model_fn, model_dir="/tmp/TSRecognition_convnet_model")

      # Set up logging for predictions
      # Log the values in the "Softmax" tensor with label "probabilities"
      tensors_to_log = {"probabilities": "softmax_tensor"}
      logging_hook = tf.train.LoggingTensorHook(
      tensors=tensors_to_log, every_n_iter=50)

      # Train the model
      train_input_fn = tf.estimator.inputs.numpy_input_fn(
                           x={"x": images},
                           y=labels,
                           batch_size=100,
                           num_epochs=None,
                           shuffle=True)
      TSRecognition_classifier.train(
             input_fn=train_input_fn,
             steps=10000,
             hooks=[logging_hook])

      # Evaluate the model and print results
      eval_input_fn = tf.estimator.inputs.numpy_input_fn(
                            x={"x": test_images},
                            y=test_labels,
                            num_epochs=1,
                            shuffle=False)
      eval_results = TSRecognition_classifier.evaluate(input_fn=eval_input_fn)
      print(eval_results)

if __name__ == "__main__":
tf.app.run()

Upvotes: 3

Views: 2256

Answers (1)

kramer
kramer

Reputation: 101

Short answer for your code:

Get rid of the np.array and np.asarray calls in your load_data function. In particular, change:

list_images32 = [skimage.transform.resize(image,(32,32)) for image in list_images]

...to...

list_images32 = [skimage.transform.resize(image,(32,32)).astype(np.float32).tolist() for image in list_images]

...and return list_images32 AS IS from your load_data function. Don't "wrap it" with the np.asarray() call. The tolist() part of my suggestion is what is important. With the astype() call I'm just suggesting doing in numpy something you're doing in TensorFlow.

Simply getting rid of the np.asarray you have on list_labels should suffice for your labels.

The full answer for those that want to understand what's going on...

The "got shape...but wanted" exception is thrown from exactly one place in TensorFlow (tensor_util.py) and the reason is this function:

def _GetDenseDimensions(list_of_lists):
   """Returns the inferred dense dimensions of a list of lists."""
   if not isinstance(list_of_lists, (list, tuple)):
     return []
   elif not list_of_lists:
     return [0]
   else:
     return [len(list_of_lists)] + _GetDenseDimensions(list_of_lists[0])

It is trying to traverse what it assumes are nested plain Python lists or plain Python tuples; it doesn't know what to do with the Numpy array type it finds in your data structure because of the np.array/np.asarray calls.

Upvotes: 2

Related Questions