Raymond Confidence
Raymond Confidence

Reputation: 31

model cannot be saved either because the input shape is not available or because the forward pass of the model is not defined

Hi guys I need help with this. was trying to modify pix2pix with some costume fusion blocks got this error after training.

ValueError: Model <_main.Pix2pix object at 0x7f03ac4a0640> cannot be saved either because the input shape is not available or because the forward pass of the model is not defined.To define a forward pass, please override Model.call(). To specify an input shape, either call build(input_shape) directly, or call the model on actual data using Model(), Model.fit(), or Model.predict(). If you have a custom training step, please make sure to invoke the forward pass in train step through Model.call_, i.e. model(inputs), as opposed to model.call().

import tensorflow as tf
from tensorflow.keras.layers import Layer
from tensorflow.keras import Model

from ssim2dmodule import similarityattention2d
from attention_module import SSCblockaddall

#act_fn3 = tf.keras.activations.tanh() #tf.ReLU()

class encode_block(tf.keras.layers.Layer):
def __init__(self, filter_num, BatchNorm2d=True):
    super(encode_block, self).__init__()
    
    self.init = tf.keras.initializers.RandomNormal(stddev=0.02)
    self.act_fn =tf.keras.layers.LeakyReLU(0.2)
   

    self.conv = tf.keras.layers.Conv2D(filter_num, kernel_size=4, 
                                strides=2, padding='same', kernel_initializer=self.init)
    
    self.BatchNorm2d =None
    if BatchNorm2d:
        self.BatchNorm2d = tf.keras.layers.BatchNormalization()
    
    
def call(self,x):
    x = self.conv(x)
    
    if self.BatchNorm2d != None:
        x = self.BatchNorm2d(x, training=True)
        
    x = self.act_fn(x)
    
    return x
   
class decode_block(tf.keras.layers.Layer):
def __init__(self, filter_num, dropout2d=True):
    super(decode_block, self).__init__()
    
    self.init = tf.keras.initializers.RandomNormal(stddev=0.02)
    self.act_fn =tf.keras.layers.ReLU(0.2)
    self.concat = tf.keras.layers.Concatenate()
    self.BatchNorm2d = tf.keras.layers.BatchNormalization()
   

    self.conv = tf.keras.layers.Conv2DTranspose(filter_num, kernel_size=4, 
                                strides=2, padding='same', kernel_initializer=self.init)
    
    self.dropout2d = None
    if dropout2d:
        self.dropout2d = tf.keras.layers.Dropout(0.5)
    
    
def call(self,x,concat_in):
    x = self.concat([x, concat_in])
    x = self.conv(x)
    x = self.BatchNorm2d(x, training=True)
    
    if self.dropout2d != None:
        x = self.dropout2d(x, training=True)
    
    x = self.act_fn(x)
    
    return x


class bottleneck(tf.keras.layers.Layer):
def __init__(self, filter_num):
    super(bottleneck, self).__init__()
    
    self.init = tf.keras.initializers.RandomNormal(stddev=0.02)
    self.act_fn =tf.keras.layers.ReLU(0.2)
   
    self.conv = tf.keras.layers.Conv2D(filter_num, kernel_size=4, 
                                strides=2, padding='same', kernel_initializer=self.init)
    
    self.dconv = tf.keras.layers.Conv2DTranspose(filter_num, kernel_size=4, 
                                strides=2, padding='same', kernel_initializer=self.init)

    
    
def call(self,x):
    x = self.conv(x)
        
    x = self.act_fn(x)
    
    x = self.dconv(x)
    
    x = self.act_fn(x)
    
    return x


class final_layer(tf.keras.layers.Layer):
def __init__(self):
    super(final_layer, self).__init__()
    
    self.init = tf.keras.initializers.RandomNormal(stddev=0.02)
    self.concat = tf.keras.layers.Concatenate()
    self.conv = tf.keras.layers.Conv2DTranspose(3, kernel_size=4, 
                                strides=2, padding='same', kernel_initializer=self.init)
    
    
def call(self,x, concat_in):
    x = self.concat([x, concat_in])
    x = self.conv(x)
    
    x = tf.keras.activations.tanh(x)
    
    return x
    


class MixedFusion_Block0(tf.keras.layers.Layer):

def __init__(self, inputs1, inputs2, filter_num):
    super(MixedFusion_Block0, self).__init__()

    self.input1 = inputs1
    self.input2 = inputs2
    self.filter_num  = filter_num

    self.ssim2d = similarityattention2d(inputs1, inputs2)
    self.encode = encode_block(filter_num, BatchNorm2d=False)

def call(self, x1, x2):
    
    # multi-style fusion
    ssim2d_out = self.ssim2d(x1,x2)
    encode_out =  self.encode(ssim2d_out)
    print(encode_out.shape)
    if not encode_out.get_shape()[1:] == (self.filter_num*2, self.filter_num*2, self.filter_num):
        encode_out = tf.keras.layers.Reshape((self.filter_num*2, self.filter_num*2, self.filter_num))(encode_out) #(tf.squeeze(encode_out, axis=[0]))
    
    return encode_out

class MixedFusion_Block1(tf.keras.layers.Layer):

def __init__(self, x, filter_num): #SSCblockaddall, SSCblocksam1dlast, SSCblocksamlast, SSCblockcamlast, SSCblockparallel, SSCblockRandom
    super(MixedFusion_Block1, self).__init__()

    self.filter_num  = filter_num
    self.block_name = SSCblockaddall()
    self.encode = encode_block(filter_num)
    

def call(self, x1, x2, x3):
    
    y1 = self.block_name(x1) 
    y2 = self.block_name(x2)
    y = tf.concat([y1, y2, x3], 3)
    
    
    encode_out = self.encode(y)
    print(encode_out.shape)

    return encode_out

class generator(Model):

def __init__(self, input_nc, layer_out, filter_num):
    super(generator,self).__init__()
    
    self.filters = filter_num
    self.in_dim = input_nc
    self.layer_out = layer_out

        # ~~~ Encoding Paths ~~~~~~ #
    # Encoder (Modality 1)
    
    #######################################################################
    # Encoder **Modality 1
    #######################################################################

    self.encode_1_0 = encode_block(self.filters*1, BatchNorm2d=False)

    self.encode_2_0 = encode_block(self.filters*2)

    self.encode_3_0 = encode_block(self.filters*4)

    self.encode_4_0 = encode_block(self.filters*8)

    self.encode_5_0 = encode_block(self.filters*8)

    self.encode_6_0 = encode_block(self.filters*8)

    self.encode_7_0 = encode_block(self.filters*8)
    
    #self.encode_8_0 = encode_block(self.filters*8)
    
    #######################################################################
    # Encoder **Modality 2
    #######################################################################

    self.encode_1_1 = encode_block(self.filters, BatchNorm2d=False)

    self.encode_2_1 = encode_block(self.filters*2)

    self.encode_3_1 = encode_block(self.filters*4)

    self.encode_4_1 = encode_block(self.filters*8)

    self.encode_5_1 = encode_block(self.filters*8)

    self.encode_6_1 = encode_block(self.filters*8)

    self.encode_7_1 = encode_block(self.filters*8)
    
    #self.encode_8_1 = encode_block(self.filters*8)
     
    #######################################################################
    # fusion block
    #######################################################################
    # --- fusion encoder
    self.fu_encoder_1 = MixedFusion_Block0(self.in_dim, self.in_dim, self.filters)
      
    self.fu_encoder_2 = MixedFusion_Block1(self.layer_out, self.filters*2)
    
    self.fu_encoder_3 = MixedFusion_Block1(self.layer_out*2, self.filters*4)

    self.fu_encoder_4 = MixedFusion_Block1(self.layer_out*4, self.filters*8)

    self.fu_encoder_5 = MixedFusion_Block1(self.layer_out*8, self.filters*8)

    self.fu_encoder_6 = MixedFusion_Block1(self.layer_out*8, self.filters*8)

    self.fu_encoder_7 = MixedFusion_Block1(self.layer_out*8, self.filters*8)
    
    #self.fu_encoder_8 = MixedFusion_Block1(self.layer_out*8, self.filters*8)
    
    # bottleneck layer
    self.bottleneck = bottleneck(self.filters*8)
 
    # ~~~ Decoding Path ~~~~~~ #
 
    self.decod_1_0 = decode_block(self.filters*8)
    self.decod_2_0 = decode_block(self.filters*8)
    self.decod_3_0 = decode_block(self.filters*8)
    self.decod_4_0 = decode_block(self.filters*4, dropout2d=False)  
    self.decod_5_0 = decode_block(self.filters*2, dropout2d=False)
    self.decod_6_0 = decode_block(self.filters*1, dropout2d=False)
    
    
    self.out        = final_layer()


            
def call(self,x,y):

    # ##############################
    
    # -----  First Level -------- 
    encoder_1_0 = self.encode_1_0(x) #(256, 256, input_size[-1])
    encoder_1_1 = self.encode_1_1(y) 


    # -----  Second Level --------
    
    encoder_2_0 = self.encode_2_0(encoder_1_0) # (128, 128, 64)
    encoder_2_1 = self.encode_2_1(encoder_1_1)
    
    
    # -----  Third Level --------
            
    encoder_3_0 = self.encode_3_0(encoder_2_0) # (64, 64, 128)
    encoder_3_1 = self.encode_3_1(encoder_2_1)

     # -----  Fourth Level --------
            
    encoder_4_0 = self.encode_4_0(encoder_3_0) # (32, 32, 256)
    encoder_4_1 = self.encode_4_1(encoder_3_1)

     # -----  Five Level --------
            
    encoder_5_0 = self.encode_5_0(encoder_4_0) # (16, 16, 512)
    encoder_5_1 = self.encode_5_1(encoder_4_1)

    # -----  sixth Level --------
            
    encoder_6_0 = self.encode_6_0(encoder_5_0) # (8, 8, 512)
    encoder_6_1 = self.encode_6_1(encoder_5_1)

    # -----  seventh Level --------
            
    encoder_7_0 = self.encode_7_0(encoder_6_0) # (4, 4, 512)
    encoder_7_1 = self.encode_7_1(encoder_6_1)
    
     
    # ----------------------------------------
    # fusion block -- f_block
    f_block_1   = self.encode_1_0(z) #self.fu_encoder_1(x,y) 
    
    f_block_2  = self.fu_encoder_2(encoder_1_0, encoder_1_1, f_block_1)
    
    f_block_3   = self.fu_encoder_3(encoder_2_0, encoder_2_1, f_block_2) 

    f_block_4  = self.fu_encoder_4(encoder_3_0, encoder_3_1, f_block_3)

    f_block_5  = self.fu_encoder_5(encoder_4_0, encoder_4_1, f_block_4)

    f_block_6  = self.fu_encoder_6(encoder_5_0, encoder_5_1, f_block_5)

    f_block_7  = self.fu_encoder_7(encoder_6_0, encoder_6_1, f_block_6)

    #f_block_8  = self.fu_encoder_8(encoder_7_0, encoder_7_1, f_block_7)
    
    #f_block_9  = self.fu_encoder_9(encoder_8_0, encoder_8_1, f_block_8)
    


    ####################################################################### 
    # ~~~~~~ Bottleneck
    btlnck = self.bottleneck(f_block_7)     # (1 x 1 x 512) and # (2 x 2 x 512)
    print(btlnck.shape)

    #######################################################################                                                                                                
    # ~~~~~~ Decoding 
    decoder_1_0 =  self.decod_1_0 (btlnck,f_block_7)  # (4, 4, 512)
    decoder_2_0 = self.decod_2_0(decoder_1_0,f_block_6)  # (8, 8, 512)
    decoder_3_0 = self.decod_3_0(decoder_2_0,f_block_5)  # (16, 16, 512)
    decoder_4_0 = self.decod_4_0(decoder_3_0,f_block_4)  # (32, 32, 256)
    decoder_5_0 = self.decod_5_0(decoder_4_0,f_block_3)  # (64, 64, 128)
    decoder_6_0 = self.decod_6_0(decoder_5_0,f_block_2)   # (128, 128, 64)
    
    
    decod_out     = self.out(decoder_6_0, f_block_1) # (256, 256, output_channels)
    
   
    # get three channels
    
    
                    
    return decod_out

class adversary(Model):

def __init__(self,filter_num):
    super(adversary,self).__init__()
    
    self.filters = filter_num
    
    self.init = tf.keras.initializers.RandomNormal(stddev=0.02)
    self.last = tf.keras.layers.Conv2D(1, (4,4), padding='same', kernel_initializer = self.init, 
                                        activation=tf.keras.activations.sigmoid)

    self.conv_1 = encode_block(self.filters*1)

    self.conv_2 = encode_block(self.filters*2)

    self.conv_3 = encode_block(self.filters*4)

    self.conv_4 = encode_block(self.filters*8)

    self.conv_5 = encode_block(self.filters*8)

    self.conv_6 = encode_block(self.filters*8)


def call(self,x,y):

    adv_1 = tf.keras.layers.concatenate([x, y]) # (256, 256, real_channels+fake_channels)

    adv_2 = self.conv_1(adv_1)                  # (128, 128,  64)
    
    adv_3 = self.conv_2(adv_2)                  # (64,  64, 128)
    
    adv_4 = self.conv_3(adv_3)                  # (32,  32, 256)
    
    adv_5 = self.conv_4(adv_4)                  # (16, 16, 512)
    
    adv_6 = self.conv_5(adv_5)                  #(8, 8, 512)
    
    adv_7 = self.conv_6(adv_6)                  #(4, 4, 512)
    
    adv_8 = self.last(adv_7)                    #(4, 4, 1)
    
    return adv_8

Upvotes: 3

Views: 4408

Answers (1)

plewand
plewand

Reputation: 176

I encountered this error when I tried to save a custom model just after it had been created. The problem was not in the model itself, but with the use of it. The clue is presented in the message of the error. I needed to add a forward pass before saving, so that Tensorflow can deduce the shape. In my case it was fit before saving.

model.compile(loss=tf.keras.losses.MeanSquaredError(),
              metrics=[tf.keras.metrics.MeanAbsoluteError()])

model.fit(self.window.train, epochs=1,
          validation_data=self.window.val)

model.save('custom_model')

Upvotes: 1

Related Questions