简体   繁体   中英

Error with creating a model in Tensorflow. ValueError: Input 0 of layer conv2d_1 is incompatible with the layer: : expected min_ndim=4, found ndim=3

I get an error when trying to create a model with Tensorflow. The error is:

Traceback (most recent call last): at block 5, line 154 at block 5, line 61, in init (self) at block 5, line 41, in conv(self, input, num_outputs, name) ValueError: Input 0 of layer conv2d_1 is incompatible with the layer: : expected min_ndim=4, found ndim=3. Full shape received: (Dimension(None), Dimension(32), Dimension(32))

I have Tensorflow version 2.5.0

Here is my code:

    import numpy
    import os
    import math
    import glob
    import random
    import time
    import skimage.data
    import skimage.transform
    import sklearn.preprocessing
    import numpy as np
    import tensorflow.compat.v1 as tf
    from tf_slim.layers import layers as _layers
    import imageio
    import matplotlib
    import matplotlib.pyplot as plt
    from IPython import display
    
    
    TRAIN_DATA_DIR = "traffic/datasets/BelgiumTS/Training"
    TEST_DATA_DIR = "traffic/datasets/BelgiumTS/Testing"
    IMAGE_WIDTH = IMAGE_HEIGHT = 32
    
    def load(data_dir, width, height):
        labels = []
        images = []
        for f in glob.glob(os.path.join(data_dir, "*/*.ppm")):
            labels.append(int(f.split("/")[-2]))
            images.append(skimage.transform.resize(imageio.imread(f), (width, height), mode='constant'))
        labels = np.array(labels)
        images = np.array(images)
        return images, labels
    
    
    train_images, train_labels = load(TRAIN_DATA_DIR, IMAGE_WIDTH, IMAGE_HEIGHT)
    test_images, test_labels = load(TEST_DATA_DIR, IMAGE_WIDTH, IMAGE_HEIGHT)
    
    
    
    class Model4():
        def conv(self, input, num_outputs, name=None):
            return tf.layers.conv2d(
                                        input, filters=num_outputs, kernel_size=(5, 5), strides=(1, 1),
                                        padding="SAME", activation='relu'
            )
        
        def pool(self, input):
            return layers.max_pool2d(input, kernel_size=(2, 2),
                                     stride=(2, 2), padding="SAME")
        
        def __init__(self):
            self.train_log = []
            self.train_time = ()
    
            self.graph = tf.Graph()
            with self.graph.as_default():
                self.global_step = tf.Variable(0, trainable=False, name='global_step')
    
                self.images = tf.placeholder(tf.float32, [None, IMAGE_HEIGHT, IMAGE_WIDTH], name='images')
                self.labels = tf.placeholder(tf.int32, [None], name='labels')
    
                self.conv1 = self.conv(self.images, 8)
                self.pool1 = self.pool(self.conv1)
    
                self.conv2 = self.conv(self.pool1, 12)
                self.pool2 = self.pool(self.conv2)
    
                self.conv3 = self.conv(self.pool2, 16)
                self.pool3 = self.pool(self.conv3)
    
                self.flat = layers.flatten(self.pool3)
    
                self.logits = layers.fully_conneccted(self.flat, 62, lrelu)
    
                self.predicted_labels = tf.argmax((self.logits, 1))
    
                self.loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(
                                                                                          logits=self.logits, labels=self.labels))
                self.train = tf.train.AdamOptimizer(learning_rate=0.001)\
                .minimize(self.loss, global_step=self.global_step)
    
                self.init = tf.global_variables_initializer()
    
                self.session = tf.Session()
    
                self.session.run(self.init)
    
    
    
    def train_graph(model, train_images, train_labels, val_images, val_labels, train_count):
        t_start = time.time()
    
        for i in range(1, train_count+1):
            indexes = np.random.choice(np.arange(train_images.shape[0], 100, replace=False))
            batch_images = train_images[indexes]
            batch_labels = train_labels[indexes]
            _, loss = model.session.run([model.train, model.loss], {
                                                                    model.images: batch_images,
                                                                    model.labels: batch_labels,
            })
            if i % 50 == 0:
                evaluate_graph(model, batch_images, batch_labels, val_images, val_labels, time.time() - t_start)
        evaluate_graph(model, batch_images, batch_labels, val_images, val_labels, time.time() - t_start)
    
    
    def evaluate_graph(model, train_images, train_lables, val_images, val_labels, training_time):
        #Run predictions against of a batch of a training set
        train_predicted, train_loss, step = model.session.run(
                                                              {model.predicted_labels, model.loss, model.global_step},
                                                              {model.images: train_images, model.labels: train_lables})
    
        #Run predictions against the full test set
        val_predicted, val_loss = model.session.run(
                                                    {model.predicted_labels, model.loss},
                                                    {model.images: val_images, model.labels: val_lables})
    
        #Calculate accuracy
        train_accuracy = np.sum(train_labels == train_predicted) / train_labels.shape[0]
        val_accuracy = np.sum(val_labels == val_predicted / val_lables.shape[0])
        #Append to training set
        #Не впевнений
        model.train_log.append((step, train_loss, train_accuracy, val_loss, val_accuracy, training_time))
        #Plot
        draw_graph(model.train_log)
    
    
    def draw_graph(logs):
        #Expand log tuples  to the list
        steps, train_losses, train_accuracies, val_losses, val_accuracies, times = zip(*logs)
        #Clear output
        display.clear_output(wait=True)
        fig, (ax1, ax2) = plt.subplots(2, sharex=True, figsize=(0,6))
        #Graph 1: Accuracies
        ax1.set_title("Step: {}  Training Time {:.0f} seconds\n"\
                      "Training Accuracy: {:.3f}  Validation Accuracy: {:.3f}"\
                      .format(steps[-1], times[-1], train_accuracies[-1], val_accuracies[-1], fonsize=9, color=color))
        ax1.plot(steps, train_accuracies, label="Training Accuracy")
        ax1.plot(steps, val_accuracies, label="Validation Accuracy")
        ax1.set_ylabel("Accuracy")
        ax1.legend(fontsize=8, loc=lower_right)
        #ax1.set_ylim(0, 1.1)
        #Graph 2: losses
        ax2.set_title("Training Loss: {:.f} Validation Loss: {:.f}"\
                      .format(train_losses[-1], val_losses[-1]), fontsize=9)
        ax2.set_yscale('log')
        ax2.plot(steps, train_losses, label="Training Loss")
        ax2.plot(steps, val_losses, label="Validation Loss")
        ax2.set_ylabel('Loss')
        ax2.legend(fontsize=8, loc='lower left')
        ax2.set_xlabel('Steps')
        _ = plt.show()
    
    
    
    m4 = Model4()
    train_graph(m4, train_images, train_labels, test_images, test_labels, 4000)

I assume that you are inputting a grayscale image, I see that

self.images = tf.placeholder(tf.float32, [None, IMAGE_HEIGHT, IMAGE_WIDTH]

In tensorflow2.x the Conv2D layer expects four dimensions: batch size, height, width, channel. So even if it is a grayscale image, you should add a dimension of 1 at the end of the image.

I suggest trying to add np.expand_dims(images, axis=-1) to your load() function

def load(data_dir, width, height):
labels = []
images = []
for f in glob.glob(os.path.join(data_dir, "*/*.ppm")):
    labels.append(int(f.split("/")[-2]))
    images.append(skimage.transform.resize(imageio.imread(f), (width, height), mode='constant'))
labels = np.array(labels)
images = np.array(images)
images = np.expand_dims(images, axis=-1)
return images, labels

This should give you an input shape of [None, IMAGE_HEIGHT, IMAGE_WIDTH, 1]

Then you should also adjust any placeholder that declares the shape of the images so it matches with the input image dimension

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM