The last dimesion of the output of tf.boolean_mask is None

Viewed 63

I want to get the flatten form of upper triangle part of a matrix and feed it to a fully_connected network. I tried to use tf.boolean_mask to get the upper triangle part but it seems that the last dimension of the output is always None, which is invalid for the fully_connected layer. Is there any approach to solve this problem?

Code:

import tensorflow as tf
import tensorflow.contrib.slim as slim


sess = tf.Session()
inputs = tf.constant(
   [[[1, 2, 3], [3, 4, 5], [6, 7, 8]],
    [[5, 6, 7], [7, 8, 9], [0, 0, 1]]])
ones = tf.ones([3, 3])
mask = tf.cast(
   tf.matrix_band_part(ones, 0, -1),
   dtype=tf.bool)
hidden = tf.boolean_mask(inputs, mask, axis=1)
print(hidden.shape)
output_1 = slim.fully_connected(hidden, 1, activation_fn=None, scope="test")
sess.run(output)

It yields the Exception:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-32-db6775f9feed> in <module>
     9 hidden = tf.boolean_mask(inputs, mask, axis=1)
    10 print(hidden.shape)
---> 11 output_1 = slim.fully_connected(hidden, 1, activation_fn=None, scope="test")
    12 sess.run(output)

~/.pyenv/versions/anaconda3-5.3.1/envs/tensorflow/lib/python3.7/site-packages/tensorflow/contrib/framework/python/ops/arg_scope.py in func_with_args(*args, **kwargs)
   180       current_args = current_scope[key_func].copy()
   181       current_args.update(kwargs)
--> 182     return func(*args, **current_args)
   183 
   184   _add_op(func)

~/.pyenv/versions/anaconda3-5.3.1/envs/tensorflow/lib/python3.7/site-packages/tensorflow/contrib/layers/python/layers/layers.py in fully_connected(inputs, num_outputs, activation_fn, normalizer_fn, normalizer_params, weights_initializer, weights_regularizer, biases_initializer, biases_regularizer, reuse, variables_collections, outputs_collections, trainable, scope)
  1853         _scope=sc,
  1854         _reuse=reuse)
-> 1855     outputs = layer.apply(inputs)
  1856 
  1857     # Add variables to collections.

~/.pyenv/versions/anaconda3-5.3.1/envs/tensorflow/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py in apply(self, inputs, *args, **kwargs)
  1225       Output tensor(s).
  1226     """
-> 1227     return self.__call__(inputs, *args, **kwargs)
  1228 
  1229   @doc_controls.for_subclass_implementers

~/.pyenv/versions/anaconda3-5.3.1/envs/tensorflow/lib/python3.7/site-packages/tensorflow/python/layers/base.py in __call__(self, inputs, *args, **kwargs)
   528 
   529       # Actually call layer
--> 530       outputs = super(Layer, self).__call__(inputs, *args, **kwargs)
   531 
   532     if not context.executing_eagerly():

~/.pyenv/versions/anaconda3-5.3.1/envs/tensorflow/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py in __call__(self, inputs, *args, **kwargs)
   536       if not self.built:
   537         # Build layer if applicable (if the `build` method has been overridden).
--> 538         self._maybe_build(inputs)
   539         # We must set self.built since user defined build functions are not
   540         # constrained to set self.built.

~/.pyenv/versions/anaconda3-5.3.1/envs/tensorflow/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py in _maybe_build(self, inputs)
  1601     # Only call `build` if the user has manually overridden the build method.
  1602     if not hasattr(self.build, '_is_default'):
-> 1603       self.build(input_shapes)
  1604 
  1605   def __setattr__(self, name, value):

~/.pyenv/versions/anaconda3-5.3.1/envs/tensorflow/lib/python3.7/site-packages/tensorflow/python/keras/layers/core.py in build(self, input_shape)
   935     input_shape = tensor_shape.TensorShape(input_shape)
   936     if tensor_shape.dimension_value(input_shape[-1]) is None:
--> 937       raise ValueError('The last dimension of the inputs to `Dense` '
   938                        'should be defined. Found `None`.')
   939     last_dim = tensor_shape.dimension_value(input_shape[-1])

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

Trying setting the shape with set_shape()

Example:

import tensorflow as tf
import tensorflow.contrib.slim as slim


inputs = tf.constant(
    [[[1, 2, 3], [3, 4, 5], [6, 7, 8]],
     [[5, 6, 7], [7, 8, 9], [0, 0, 1]]], tf.float32)

ones = tf.ones([3, 3])

mask = tf.cast(
    tf.matrix_band_part(ones, 0, -1),
    dtype=tf.bool)
hidden = tf.boolean_mask(inputs, mask, axis=1)

# use the shape of the input to get the new hidden shape
b, t, h = inputs.get_shape().as_list()
new_shp = (b, t + h)

# explicitly set the shape of `hidden`
hidden.set_shape(new_shp)

print(hidden.shape)
# (2, 6)

# forward pass through FC layer
output = slim.fully_connected(hidden, 1, activation_fn=None, scope="test")

# initialize network weights
init_op = tf.global_variables_initializer()

# test
with tf.Session() as sess:
    sess.run(init_op)
    print(output.eval().shape)
    # (2, 1)
Related