'How to save Keras model with custom layer that have dictionary variable

I have a custom layer , which has a dictionary variable called vmap. I implement the get_config() and from_config() method in the custom layer class and try to save the model using : model.save('model.h5') and loading the model using : new_model = tf.keras.models.load_model('model.h5',custom_objects = {"valuemaplayer": valuemaplayer})

This is my code for custom layer :

class valuemaplayer(keras.layers.Layer):
def init(self,vmap ={},compress = False, **kwargs):
kwargs["dynamic"] = True
super(valuemaplayer,self).init(**kwargs)
self._vmap = vmap
self._data = []
self._compression = compress
self._output_shape = None

def build(self, input_shape):
    pass

def enable_compression(self):
    value = list(self.get_values())
    vmap = self._vmap
    cnt = 0
    # FIXME right now only 2D input data is supported
    for v0 in value:
        for v1 in v0:
            for v2 in v1:
                for v3 in v2:
                    v = tuple(v3)
                    if v not in vmap:
                        vmap[v]=cnt
                        cnt+=1
    self._compression = True
    print(vmap)


@tf.function
def do_mapping(self,pixel):
    enumerated_value = self._vmap.get(pixel)
        # print(enumerated_value)
        # print(pixel)
    return enumerated_value

def call(self, inputs, training=True):#use eager execution or decorate with @tf.function
    if self._compression:
        elem = []
        for b in inputs:
            for h in b:
                for w in h:
                    x = self.do_mapping(pixel=tuple(w.numpy()))
                    elem.append(tf.convert_to_tensor(x, dtype='float32'))
        return tf.cast(tf.reshape(elem, self._output_shape), dtype='float32')


        # TODO check if channel axis gets mapped by tf.map_fn
     # else compression is disabled
     # in case we're training, we do not want to observe values
    if not training:
        self._data.append(inputs)
    return inputs

    # get values of the output of value map layer
def get_values(self):
    for d in self._data:
        try:
            d = d.numpy()
        except AttributeError:
            continue
        yield d

def get_config(self):
    config = super(valuemaplayer, self).get_config()
    config.update({"vmap": self._vmap.items(),
                   "compress": self._compression})
    return config

@classmethod
def from_config(cls, config):
    return cls(**config)

def compute_output_shape(self, input_shape):
    print("input shape of value map layer:", input_shape)
    self._output_shape=input_shape
    b, h, w, _ = input_shape
    if self._compression:
        # TODO did I set the channel axis? and does this work?
        print("channel axis is set")
        self._output_shape = tf.TensorShape((b, h, w, 1))
    return self._output_shape
#saving the model :
model.save('model.h5')
#load model :

new_model = tf.keras.models.load_model('model.h5',custom_objects = {"valuemaplayer": valuemaplayer})

In the config method if i do "vmap": self._vmap and try to save the model it is saved and loaded successfully. However, i need to save the dictionary vmap with its content so i do "vmap": self._vmap.items() in config method and try to retrain and save that retrained model but i get an error stating Type error: keys must be str,int,float,bool or None , not Tuple



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source