keras: Lambda Layer doesn't serialize to JSON or YAML
It appears networks with Lambda Layers can’t be saved though the to_json
or to_yaml
methods
To implement graves style skip connections for a classification problem I’m using a lambda layer to get the results from the last time step
Lambda(lambda x: x[:,-1,:], output_shape=last_step_shape)
where
def last_step_shape(input_shape):
shape = list(input_shape)
assert len(shape) == 3
return tuple((shape[0], shape[2]))
This model does successfully start training, but I can’t save the architecture specification. The model is defined using the Graph API. Looks something like
model = Graph()
model.add_input(name='input', batch_input_shape=(batchsize, maxlen), dtype='int')
model.add_node(Embedding(257, embed_size, input_length=maxlen, name='embedding', input='input')
prev_name = 'embedding'
#add intermediate hidden LSTM layers, they need to return their sequences.
for l in range(num_layers-1):
ls = str(l)
if l > 0:
model.add_node(LSTM(lstm_layer_size, return_sequences=True),
name='_f'+ls, inputs=[prev_name, 'embedding'])
model.add_node(Lambda(lambda x: x[:,-1,:], output_shape=last_step_shape), name='f'+ls, input='_f'+ls)
else:
model.add_node(LSTM(lstm_layer_size, return_sequences=True),
name='_f'+ls, input=prev_name)
model.add_node(Lambda(lambda x: x[:,-1,:], output_shape=last_step_shape), name='f'+ls, input='_f'+ls)
prev_name = '_f'+ls
#add last LSTM layer
ls = str(num_layers-1)
if num_layers > 1:
model.add_node(LSTM(lstm_layer_size), name='f'+ls, inputs=[prev_name, 'embedding'])
model.add_node(Dense(1, activation='sigmoid'), name='sigmoid', inputs=['f'+str(x) for x in range(num_layers)], merge_mode='concat')
else:
model.add_node(LSTM(lstm_layer_size, dropout_W=0.5, dropout_U=0.5, W_regularizer=l2(1e-5)), name='f'+ls, input=prev_name)
model.add_node(Dense(1, activation='sigmoid'), name='sigmoid', input='f'+ls, merge_mode='concat')
model.add_output(name='output', input='sigmoid')
# try using different optimizers and different optimizer configs
optimizer = Adam(lr=0.001, clipnorm=grad_clip)
model.compile(optimizer, {'output': 'binary_crossentropy'})
I get the error
---------------------------------------------------------------------------
UnicodeDecodeError Traceback (most recent call last)
<ipython-input-25-e4d9f49c02c8> in <module>()
----> 5 json_string = model.to_json()
6 # open(name+'.json', 'w').write(json_string)
7
/usr/local/lib/python2.7/dist-packages/keras/engine/topology.pyc in to_json(self, **kwargs)
2375 'config': config,
2376 }
-> 2377 return json.dumps(model_config, default=get_json_type, **kwargs)
2378
2379 def to_yaml(self, **kwargs):
/usr/lib/python2.7/json/__init__.pyc in dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, encoding, default, sort_keys, **kw)
248 check_circular=check_circular, allow_nan=allow_nan, indent=indent,
249 separators=separators, encoding=encoding, default=default,
--> 250 sort_keys=sort_keys, **kw).encode(obj)
251
252
/usr/lib/python2.7/json/encoder.pyc in encode(self, o)
205 # exceptions aren't as detailed. The list call should be roughly
206 # equivalent to the PySequence_Fast that ''.join() would do.
--> 207 chunks = self.iterencode(o, _one_shot=True)
208 if not isinstance(chunks, (list, tuple)):
209 chunks = list(chunks)
/usr/lib/python2.7/json/encoder.pyc in iterencode(self, o, _one_shot)
268 self.key_separator, self.item_separator, self.sort_keys,
269 self.skipkeys, _one_shot)
--> 270 return _iterencode(o, 0)
271
272 def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
UnicodeDecodeError: 'utf8' codec can't decode byte 0x83 in position 28: invalid start byte
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 27 (5 by maintainers)
Commits related to this issue
- Fix json serialization in Lambda layer Fix #2582 — committed to henry0312/keras by henry0312 8 years ago
- Fix json serialization in Lambda layer Fix #2582 Fix #3001 — committed to henry0312/keras by henry0312 8 years ago
- Fix json serialization in Lambda layer (#3012) Fix #2582 Fix #3001 — committed to keras-team/keras by henry0312 8 years ago
- Merge original repo into personal repo. (#1) * Fix generators methods when passing data as dicts * Callback style fix * Fix callback issue with Sequential model * Allow 'tf' ordering in Imag... — committed to bryan-lunt/keras by bryan-lunt 8 years ago
Are Lambda layers serialized to Python bytecode? We have a GSoC student trying to read in the Keras models that have been serialized to JSON and running into issues with Lambda layers - I would guess the function in the JSON is serialized to Python bytecode and that crossing the language barrier would not be possible (without doing some sophisticated compiler-ish type things)
Hi, i found a way how to solve my issue: I was reading the dimension of a layer to parametrize the next layer:
curr_seq_length = x._shape[1] kernel_size = curr_seq_length - self._sequence_length + 1 x = Conv1D(self._nr_features, kernel_size=[kernel_size], activation='relu', padding='valid')(x)
the problem was that curr_seq_length was from type Dimension - and it seems that there something changed in the lastest tensorflow-integrated keras version. And the json serializer doesn’t know how to deal with the Dimension object.
Changing the line to
curr_seq_length = x._shape[1].value
solves the problem…I also have the same problem with Lambda layer. I am trying to add temperature to my softmax by:
model.add(Lambda(lambda x: x / temp))
but getting the error that Lambda object is not JSON serializable. Any suggestion to solve this or any suggestion to add the temperature to softmax?
Keras: 2.1.3 Tensorflow: 1.5 No GPU.