简体   繁体   中英

Tensorflow error : Dimensions must be equal

I have a dataset of 25000 colored pictures 100*100(*3) and I am trying to build a simple neural network with one convolutional layer. Its pictures of cells that are infected or not by Malaria, so my output is 2. But it seems like I have a dimension mismatch, and I don't know where my error comes from.

My neural network :

def simple_nn(X_training, Y_training, X_test, Y_test):
    input = 100*100*3
    batch_size = 25

    X = tf.placeholder(tf.float32, [batch_size, 100, 100, 3])
    #Was:
    # W = tf.Variable(tf.zeros([input, 2]))
    # b = tf.Variable(tf.zeros([2]))
    #Now:
    W = tf.Variable(tf.truncated_normal([4, 4, 3, 3], stddev=0.1))
    B = tf.Variable(tf.ones([3])/10) # What should I put here ??

    init = tf.global_variables_initializer()

    # model
    #Was:
    # Y = tf.nn.softmax(tf.matmul(tf.reshape(X, [-1, input]), W) + b)
    #Now:
    stride = 1  # output is still 28x28
    Ycnv = tf.nn.conv2d(X, W, strides=[1, stride, stride, 1], padding='SAME')
    Y = tf.nn.relu(Ycnv + B)

    # placeholder for correct labels
    Y_ = tf.placeholder(tf.float32, [None, 2])


    # loss function
    cross_entropy = -tf.reduce_sum(Y_ * tf.log(Y))

    # % of correct answers found in batch
    is_correct = tf.equal(tf.argmax(Y,1), tf.argmax(Y_,1))
    accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))

    learning_rate = 0.00001

    optimizer = tf.train.GradientDescentOptimizer(learning_rate)
    train_step = optimizer.minimize(cross_entropy)
    sess = tf.Session()
    sess.run(init)
    #Training here...

My error :

Traceback (most recent call last):
  File "neural_net.py", line 135, in <module>
    simple_nn(X_training, Y_training, X_test, Y_test)
  File "neural_net.py", line 69, in simple_nn
    cross_entropy = -tf.reduce_sum(Y_ * tf.log(Y))
...
ValueError: Dimensions must be equal, but are 2 and 3 for 'mul' (op: 'Mul') with input shapes: [?,2], [25,100,100,3].

I used a simple layer before, and it was working. I changed my weight and bias, and honestly, I don't know why my bias are setup like this, I followed a tutorial ( https://codelabs.developers.google.com/codelabs/cloud-tensorflow-mnist/#11 ) but it is not explained. I also replaced my Y to a conv2D. And I don't know what my ouput should be if I want to get a vector of size 2*1 as a result.

You have correctly defined your labels as

Y_ = tf.placeholder(tf.float32, [None, 2])

So the last dimension is 2. However, the output from the convolution step is not directly suitable for comparing it to the labels. What I mean is the following: if you do

Ycnv = tf.nn.conv2d(X, W, strides=[1, stride, stride, 1], padding='SAME')
Y = tf.nn.relu(Ycnv + B)

The dimensions of this are going to be four as the error says:

ValueError: Dimensions must be equal, but are 2 and 3 for 'mul' (op: 'Mul') with input shapes: [?,2], [25,100,100,3].

So it is impossible to multiply directly (or operate) the output from convolution with the labels. What I recommend is to flatten (reshape it to only one dimension) the output of convolution and pass it to a fully connected layer of 2 units (as much as classes you have). Like this:

Y = tf.reshape(Y, [1,-1])
logits = tf.layers.dense(Y, units= 2)

and you can pass this to the loss.

Also I recommend you to change the loss to a more approprite version. For example, tf.losses.sigmoid_cross_entropy .

Also, the way you use convolutions is strange. Why do you put handmade filters in the convolution? besides you should have to initialize and before it putting them in a collection. In conclusion I recommend you to delete all the following code:

    W = tf.Variable(tf.truncated_normal([4, 4, 3, 3], stddev=0.1))
    B = tf.Variable(tf.ones([3])/10) # What should I put here ??

    init = tf.global_variables_initializer()

    # model
    #Was:
    # Y = tf.nn.softmax(tf.matmul(tf.reshape(X, [-1, input]), W) + b)
    #Now:
    stride = 1  # output is still 28x28
    Ycnv = tf.nn.conv2d(X, W, strides=[1, stride, stride, 1], padding='SAME')
    Y = tf.nn.relu(Ycnv + B)

and substitute it by:

conv1 = tf.layers.conv2d(X, filters=64, kernel_size=3,
                         strides=1, padding='SAME',
                         activation=tf.nn.relu, name="conv1")

Also the init = tf.global_variable_initializer() should be at the end of the graph construction becuase, if not, there will be variables it won't catch.

My final working code is:

def simple_nn():
    inp = 100*100*3
    batch_size = 2

    X = tf.placeholder(tf.float32, [batch_size, 100, 100, 3])
    Y_ = tf.placeholder(tf.float32, [None, 2])
    #Was:
    # W = tf.Variable(tf.zeros([input, 2]))
    # b = tf.Variable(tf.zeros([2]))
    #Now:



    # model
    #Was:
    # Y = tf.nn.softmax(tf.matmul(tf.reshape(X, [-1, input]), W) + b)
    #Now:
    stride = 1  # output is still 28x28

    conv1 = tf.layers.conv2d(X, filters=64, kernel_size=3,
                         strides=1, padding='SAME',
                         activation=tf.nn.relu, name="conv1")
    Y = tf.reshape(conv1, [1,-1])
    logits = tf.layers.dense(Y, units=2, activation=tf.nn.relu)
    # placeholder for correct labels



    # loss function
      cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(labels=Y_, logits=logits)
    loss = tf.reduce_mean(cross_entropy)

    # % of correct answers found in batch
    is_correct = tf.equal(tf.argmax(Y,1), tf.argmax(Y_,1))
    accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))

    learning_rate = 0.00001

    optimizer = tf.train.GradientDescentOptimizer(learning_rate)
    train_step = optimizer.minimize(cross_entropy)

    init = tf.global_variables_initializer()

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

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