TypeError: 预期 int32,得到 None 类型的 'NoneType' 代替

数据挖掘 Python 深度学习 美国有线电视新闻网 卷积神经网络
2022-02-26 13:08:31

我希望我的模型批量大小是动态形状,并且我没有指定任何批量大小,但这会导致错误。

在这里,在第一行中,我将批量大小指定为 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) 

胶囊层代码:

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()))
        

调用函数时的以下行CapsuleLayer,引发了错误:

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

错误:

TypeError: 预期 int32,得到 None 类型的 'NoneType' 代替。

当我为批量大小分配一个数字时,没有发生错误。

1个回答

引发错误是tf.zero()因为 shape 参数应该是一个整数列表。实际上,当您构建计算图时,批量大小(还)不知道,除非您明确指定 if。

有时您需要在使用 Tensorflow Keras API 时手动指定形状信息。

一种可能的解决方法是使用tf.shape()函数而不是shape属性:

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

这条线将毫无错误地运行,但现在批量维度b是由计算定义的。它是动态的,Keras 不再知道它等于批量大小。

也许因为这个softmax(b, axis=1)不再起作用了。有趣softmax()的是,默认轴设置有效。因此,作为一种解决方法,我们可以来回调整尺寸:

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

为了使整个代码工作,您还需要在代码的开头更精确地指定形状信息:

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

您还可能注意到,在 CapsuleLayer 之后,所有形状信息都丢失了。你可以用digitcaps.shape. 但是我们可以重新指定它:

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