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?
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 `
`
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 itValueError: 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?