CasiaFan / SSD_EfficientNet

SSD using TensorFlow object detection API with EfficientNet backbone
63 stars 10 forks source link

ValueError: name for name_scope must be a string when Building up a Model #12

Closed yourtheron closed 4 years ago

yourtheron commented 4 years ago

Hi,

I tried to follow tf's doc to build up a model as follows: https://www.tensorflow.org/guide/keras/custom_layers_and_models `

class SimpleUNet(tf.keras.Model, layers.Layer):
    '''
    Serialise basic units so as to build up a double-layered encoder-decoder U-Net
    Input:
        inDim: [mbSize, modaility/channel, tensor dimensions]
        classNum: background included
        name: name for the net
        inputs: 5D tf tensor of [mbSize, modaility/channel, tensor dimensions]. Inputs must be organised into channel first
    Returns:
        outputs: 5D tf tensor of [mbSize, classNum, tensor dimensions]
    '''
    def __init__(self, inDim, classNum, name='SimpleUNet', **kwargs):
        super(SimpleUNet, self).__init__(name=name, **kwargs)
        self.inDim = inDim
        self.classNum = classNum
        dimEnSt1End = np.array(inDim[1:])-2-2
        dimEnSt2Ed = dimEnSt1End/2-2-2
        dimBridgeEnd = (dimEnSt2Ed/2-2-2)*2
        dimDEStd1End = (dimBridgeEnd-2-2)*2
        outDim = dimDEStd1End-2-2-2
        temp = ((dimEnSt2Ed - dimBridgeEnd)/2).astype('int32')
        crop3d1 = tuple(np.tile(temp, (2, 1)).T)
        temp = ((dimEnSt1End - dimDEStd1End)/2).astype('int32')
        crop3d2 = tuple(np.tile(temp, (2, 1)).T)
        # list of basic units used in the model
        self.en_st1_cbr1 = CBR(32, 3, 1, 'valid')
        self.en_st1_cbr2 = CBR(64, 3, 1, 'valid')
        self.en_st2_mp = layers.MaxPooling3D(pool_size=(2, 2, 2), strides=(2, 2, 2), padding='valid', data_format='channels_first')
        self.en_st2_cbr1 = CBR(64, 3, 1, 'valid')
        self.en_st2_cbr2 = CBR(128, 3, 1, 'valid')
        self.bridge_mp = layers.MaxPooling3D(pool_size=(2, 2, 2), strides=(2, 2, 2), padding='valid', data_format='channels_first')
        self.bridge_cbr1 = CBR(128, 3, 1, 'valid')
        self.bridge_cbr2 = CBR(256, 3, 1, 'valid')    
        self.bridge_tconv1 = layers.Conv3DTranspose(256, 2, strides=2, padding='valid', data_format='channels_first')
        self.de_3dcrop1 = layers.Cropping3D(crop3d1, data_format='channels_first')
        self.de_st1_cbr1 = CBR(256, 3, 1, 'valid')
        self.de_st1_cbr2 = CBR(128, 3, 1, 'valid')    
        self.de_st1_tconv1 = layers.Conv3DTranspose(128, 2, strides=2, padding='valid', data_format='channels_first')
        self.de_3dcrop2 = layers.Cropping3D(crop3d2, data_format='channels_first')
        self.de_st2_cbr1 = CBR(64, 3, 1, 'valid')
        self.de_st2_cbr2 = CBR(64, 3, 1, 'valid') 
        self.final_conv3D = layers.Conv3D(filters=self.classNum, kernel_size=3, strides=1, padding='valid', data_format='channels_first')

    def call(self, inputs):
        x = self.en_st1_cbr1(inputs)
        xEnSt1End = self.en_st1_cbr2(x)
        x= self.en_st2_mp(xEnSt1End)
        x= self.en_st2_cbr1(x)
        xEnSt2Ed = self.en_st2_cbr2(x)
        x = self.bridge_mp(xEnSt2Ed)
        x = self.bridge_cbr1(x)
        x = self.bridge_cbr2(x)
        xBridgeEnd = self.bridge_tconv1(x)
        xCrop1 = self.de_3dcrop1(xEnSt2Ed)
        x = layers.Concatenate([xBridgeEnd, xCrop1], axis=1)
        x = self.de_st1_cbr1(x)
        x = self.de_st1_cbr2(x)
        xDeSt1End = self.de_st1_tconv1(x)
        xCrop2 = self.de_3dcrop2(xEnSt1End)
        x = layers.Concatenate([xDeSt1End, xCrop2], axis=1)
        x = self.de_st2_cbr1(x)
        x = self.de_st2_cbr2(x)
        x = self.final_conv3D(x)
        outputs = activations.softmax(x, axis=1)

        return outputs

class CBR(layers.Layer):
    def __int__(self, filterNum, kSize, strSize, padMode, name='cbr', **kwargs):
        super(CBR, self).__init__(name=name, **kwargs)
        self.conv3D = layers.Conv3D(filters=filterNum, kernel_size=kSize, strides=strSize, padding=padMode, data_format='channels_first')
        self.BN = layers.BatchNormalization(axis=1)
    def call(self, inputs):
        x = self.conv3D(inputs)
        x=self.BN(x)
        return layers.Relu(x)

`

Then I initialised it, and tried to build it by calling SUNet.build classNum = 3 mbSize = 16 inDim = [4, 64, 64, 64] SUNet = SimpleUNet(inDim, classNum) SUNet.build(input_shape=inDim) I strictly followed the example given in tf's doc, but an error was raised when building up it ValueError: name for name_scope must be a string. It occurred here when CBR is called for the first time: def __int__(self, filterNum, kSize, strSize, padMode, name='cbr', **kwargs): super(CBR, self).__init__(name=name, **kwargs)

I cannot figure out any syntactic mistake. Could anyone give me a hand? Thanks a lot. Or, is the model cannot be built at this moment until it is actually used when being called in the training?