# TypeError: Expected int32, got None of type 'NoneType' instead

I want my model batch size to be a dynamic shape, and I've assigned none as batch size, but that's causing an error.

Here, in the first line, I specified batch size as None:

inp=L.Input(shape=(28,28,1),batch_size=None)
maxpool1=L.MaxPooling2D(pool_size=(1,1))(conv1)
reshape2=L.Reshape([-1,8])(conv2)
squashed_output=L.Lambda(squash)(reshape2)


CapsuleLayer code:

class CapsuleLayer(L.Layer):
def __init__(self,num_capsule,dim_capsule,routing=3,kernel_initializer='glorot_uniform',**kwargs):
super(CapsuleLayer,self).__init__(**kwargs)
self.num_capsule=num_capsule
self.dim_capsule=dim_capsule
self.routing=routing
self.kernel_initializer=kernel_initializer
def build(self,input_shape):
assert len(input_shape) >= 3
self.input_num_capsule=input_shape[1]
self.input_dim_capsule=input_shape[2]

#transforming the matrix
self.built=True
def call(self,inputs,training=None):
input_expand=tf.expand_dims(tf.expand_dims(inputs,1),-1)
inputs_tiled=K.tile(input_expand,[1,self.num_capsule,1,1,1])
input_hat=tf.squeeze(tf.map_fn(lambda x: tf.matmul(self.W,x),elems=inputs_tiled))
b=tf.zeros(shape=[inputs.shape[0] ,self.num_capsule,1,self.input_num_capsule])
assert self.routing > 0
for i in range(self.routing):
c=tf.nn.softmax(b,axis=1)
output=squash(tf.matmul(c,input_hat))
if i<self.routing-1:
b+=tf.matmul(output,input_hat,transpose_b=True)
return tf.squeeze(output)
def compute_output_shape(self,input_shape):
return tuple([None,self.num_capsule,self.dim_capsule])
def get_config(self):
config = {
'num_capsule': self.num_capsule,
'dim_capsule': self.dim_capsule,
'routings': self.routings
}
base_config = super(CapsuleLayer, self).get_config()
return dict(list(base_config.items()) + list(config.items()))



The following line when CapsuleLayer function called, the error raised:

digitcaps = CapsuleLayer(num_capsule=3, dim_capsule=16, routing=3, name='digitcaps')(squashed_output)


The error:

TypeError: Expected int32, got None of type 'NoneType' instead.

When I assign a number to the batch size, no error occurred.

The error is raised by tf.zero() because the shape parameter should be a list of ints. Indeed, as you build the computation graph, batch size is not (yet) know, unless you explicitly specify if.

Sometimes you need to specify shape information manually when working with Tensorflow Keras API.

One possible fix is to use tf.shape() function instead of shape attribute:

   b=tf.zeros(shape=[tf.shape(inputs)[0] ,self.num_capsule,1,self.input_num_capsule])


This line will run without error, but now the batch dimension of b is defined by a computation. It is dynamic and Keras doesn't know anymore, that it equals the batch size.

Maybe because of this softmax(b, axis=1) does not work anymore. Interestingly softmax() with the default axis setting works. So as a workaround we can juggle dimensions back and forth:

    c=tf.transpose(tf.nn.softmax(tf.transpose(b,perm=[0,2,3,1])),perm=[0,3,1,2])


To make the whole code work, you also need to specify shape information more precisely at the beginning of the code:

    reshape2=L.Reshape([6*6*128//8,8])(conv2)


Also you might notice, that all shape information is lost after the CapsuleLayer. You can check it with digitcaps.shape. But we can re-specify it:

    digitcaps = L.Reshape([3,16])(digitcaps)