Uylenburgh
Uylenburgh

Reputation: 1307

Reshaping tensor after max pooling ValueError: Shapes are not compatible

I am building CNN fitting my own data, based on this example

Basically, my data has 3640 features; I have a convolution layer followed by a pooling layer, that pools every other feature, so I end up with dimensions (?, 1, 1819, 1) because 3638 features after conv layer / 2 == 1819.

When I try to reshape my data after pooling to get it in the form [n_samples, n_fetures]

    print("pool_shape", pool_shape) #pool  (?, 1, 1819, 10)
    print("y_shape", y_shape) #y  (?,)

    pool.set_shape([pool_shape[0], pool_shape[2]*pool_shape[3]])
    y.set_shape([y_shape[0], 1])

I get an error:

ValueError: Shapes (?, 1, 1819, 10) and (?, 18190) are not compatible

My code:

N_FEATURES = 140*26
N_FILTERS = 1
WINDOW_SIZE = 3

def my_conv_model(x, y):

    x = tf.cast(x, tf.float32)
    y = tf.cast(y, tf.float32)

    print("x ", x.get_shape())
    print("y ", y.get_shape())

    # to form a 4d tensor of shape batch_size x 1 x N_FEATURES x 1
    x = tf.reshape(x, [-1, 1, N_FEATURES, 1])
    # this will give you sliding window of 1 x WINDOW_SIZE convolution.
    features = tf.contrib.layers.convolution2d(inputs=x,
                                               num_outputs=N_FILTERS,
                                               kernel_size=[1, WINDOW_SIZE],
                                               padding='VALID')

    print("features ", features.get_shape()) #features  (?, 1, 3638, 10)

    # Max pooling across output of Convolution+Relu.
    pool = tf.nn.max_pool(features, ksize=[1, 1, 2, 1],
                             strides=[1, 1, 2, 1], padding='SAME')

    pool_shape = pool.get_shape()
    y_shape = y.get_shape()
    print("pool_shape", pool_shape) #pool  (?, 1, 1819, 10)
    print("y_shape", y_shape) #y  (?,)

### here comes the error ###
    pool.set_shape([pool_shape[0], pool_shape[2]*pool_shape[3]])
    y.set_shape([y_shape[0], 1])

    pool_shape = pool.get_shape()
    y_shape = y.get_shape()
    print("pool_shape", pool_shape) #pool  (?, 1, 1819, 10)
    print("y_shape", y_shape) #y  (?,)

    prediction, loss = learn.models.logistic_regression(pool, y)
    return prediction, loss

How to reshape the data to get any meaningful representation of it and to later pass it to logistic regression layer?

Upvotes: 0

Views: 1286

Answers (1)

mrry
mrry

Reputation: 126154

This looks like a confusion between the Tensor.set_shape() method and the tf.reshape() operator. In this case, you should use tf.reshape() because you are changing the shape of the pool and y tensors:

  • The tf.reshape(tensor, shape) operator takes a tensor of any shape, and returns a tensor with the given shape, as long as they have the same number of elements. This operator should be used to change the shape of the input tensor.

  • The tensor.set_shape(shape) method takes a tensor that might have a partially known or unknown shape, and asserts to TensorFlow that it actually has the given shape. This method should be used to provide more information about the shape of a particular tensor.

    It can be used, e.g., when you take the output of an operator that has a data-dependent output shape (such as tf.image.decode_jpeg()) and assert that it has a static shape (e.g. based on knowledge about the sizes of images in your dataset).

In your program, you should replace the calls to set_shape() with something like the following:

pool_shape = tf.shape(pool)
pool = tf.reshape(pool, [pool_shape[0], pool_shape[2] * pool_shape[3]])

y_shape = tf.shape(y)
y = tf.reshape(y, [y_shape[0], 1])

# Or, more straightforwardly:
y = tf.expand_dims(y, 1)    

Upvotes: 1

Related Questions