2
$\begingroup$

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)
conv1=L.Conv2D(filters=256,kernel_size=(2,2),activation='relu',padding='valid')(inp)
maxpool1=L.MaxPooling2D(pool_size=(1,1))(conv1)
conv2=L.Conv2D(filters=128,kernel_size=(9,9),activation='relu',padding='valid')(maxpool1)
conv2=L.Conv2D(filters=8*16,kernel_size=(9,9),strides=2,padding='valid',activation=None)(conv2)
# Adding the squash activation
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.W= self.add_weight(shape=[self.num_capsule,self.input_num_capsule,self.dim_capsule,self.input_dim_capsule],initializer=self.kernel_initializer,name='w')
        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.

$\endgroup$
0
$\begingroup$

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) 
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.