Tensorflow 2.2.0 Keras Subclass Model can train and predict, but throws exception when save:Dimension size must be evenly divisible X

Viewed 90

This Model is a variety of CNN and uses Causal Dilational Convolution Layer.

I can train and predict with 0 error, but when I use model.save() to save model, it throws Exception.

So I use save_weights and load_weights to save and load model.

I wonder why this error appears:

model.save("path")

out:

ValueError: Dimension size must be evenly divisible by 2 but is 745 for '{{node conv1d_5/SpaceToBatchND}} = SpaceToBatchND[T=DT_FLOAT, Tblock_shape=DT_INT32, Tpaddings=DT_INT32](conv1d_5/Pad, conv1d_5/SpaceToBatchND/block_shape, conv1d_5/SpaceToBatchND/paddings)' with input shapes: [?,745,32], [1], [1,2] and with computed input tensors: input[1] = <2>, input[2] = <[0 0]>.

Input shape is (None,743,27)

Output shape is (None,24,1)

def slice(x, seq_length):
    return x[:, -seq_length:, :]

class ResidualBlock(tf.keras.layers.Layer):
    def __init__(self, n_filters, filter_width, dilation_rate):
        super(ResidualBlock, self).__init__()
        
        self.n_filters = n_filters
        self.filter_width = filter_width
        self.dilation_rate = dilation_rate

        # preprocessing - equivalent to time-distributed dense
        self.x = Conv1D(32, 1, padding='same', activation='relu')

        # filter convolution
        self.x_f = Conv1D(filters=n_filters,
                          kernel_size=filter_width,
                          padding='causal',
                          dilation_rate=dilation_rate,
                          activation='tanh')

        # gating convolution
        self.x_g = Conv1D(filters=n_filters,
                          kernel_size=filter_width,
                          padding='causal',
                          dilation_rate=dilation_rate,
                          activation='sigmoid')

        # postprocessing - equivalent to time-distributed dense
        self.z_p = Conv1D(32, 1, padding='same', activation='relu')

    def call(self, inputs):
        x = self.x(inputs)
        f = self.x_f(x)
        g = self.x_g(x)
        z = tf.multiply(f, g)
        z = self.z_p(z)

        return tf.add(x, z), z
    
    def get_config(self):
        config = super(ResidualBlock, self).get_config()
        config.update({"n_filters": self.n_filters,
                      "filter_width": self.filter_width,
                      "dilation_rate": self.dilation_rate})
        return config

class WaveNet(tf.keras.Model):
    def __init__(self, n_filters=32, filter_width=2, dilation_rates=None, drop_out=0.2, pred_length=24):

        super().__init__(name='WaveNet')

        # Layer Parameter
        self.n_filters = n_filters
        self.filter_width = filter_width
        self.drop_out = drop_out
        self.pred_length = pred_length
        if dilation_rates is None:
            self.dilation_rates = [2 ** i for i in range(8)]
        else:
            self.dilation_rates = dilation_rates

        # Layer
        self.residual_stacks = []
        for dilation_rate in self.dilation_rates:
            self.residual_stacks.append(ResidualBlock(self.n_filters, self.filter_width, dilation_rate))
        # self.add = Add()
        self.cut = Lambda(slice, arguments={'seq_length': pred_length})
        self.conv_1 = Conv1D(128, 1, padding='same')
        self.relu = Activation('relu')
        self.drop = Dropout(drop_out)
        self.skip = Lambda(lambda x: x[:, -2 * pred_length + 1:-pred_length + 1, :1])
        self.conv_2 = Conv1D(1, 1, padding='same')

    def _unroll(self, inputs, **kwargs):
        outputs = inputs

        skips = []
        for residual_block in self.residual_stacks:
            outputs, z = residual_block(outputs)
            skips.append(z)

        outputs = self.relu(Add()(skips))
        outputs = self.cut(outputs)
        outputs = self.conv_1(outputs)
        outputs = self.relu(outputs)
        outputs = self.drop(outputs)

        outputs = Concatenate()([outputs, self.skip(inputs)])
        outputs = self.conv_2(outputs)
        outputs = self.cut(outputs)

        return outputs         
    
    def _get_output(self, input_tensor):
        pass

    def call(self, inputs, training=False, **kwargs):
        if training:
            return self._unroll(inputs)
        else:
            return self._get_output(inputs)

Train step

model = WaveNet()
model.compile(Adam(), loss=loss)

# ok
history = model.fit(train_x, train_y,
                    batch_size=batch_size,
                    epochs=epochs,
                    callbacks=[cp_callback] if save else None)

# ok
result = model.predict(test_x)  

# error
model.save("path")
0 Answers
Related