{"action":"created","issue":{"url":"https://api.github.com/repos/fchollet/keras/issues/2582","repository_url":"https://api.github.com/repos/fchollet/keras","labels_url":"https://api.github.com/repos/fchollet/keras/issues/2582/labels{/name}","comments_url":"https://api.github.com/repos/fchollet/keras/issues/2582/comments","events_url":"https://api.github.com/repos/fchollet/keras/issues/2582/events","html_url":"https://github.com/fchollet/keras/issues/2582","id":152612173,"number":2582,"title":"Lambda Layer doesn't serialize to JSON or YAML","user":{"login":"RaffEdwardBAH","id":5190184,"avatar_url":"https://avatars.githubusercontent.com/u/5190184?v=3","gravatar_id":"","url":"https://api.github.com/users/RaffEdwardBAH","html_url":"https://github.com/RaffEdwardBAH","followers_url":"https://api.github.com/users/RaffEdwardBAH/followers","following_url":"https://api.github.com/users/RaffEdwardBAH/following{/other_user}","gists_url":"https://api.github.com/users/RaffEdwardBAH/gists{/gist_id}","starred_url":"https://api.github.com/users/RaffEdwardBAH/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RaffEdwardBAH/subscriptions","organizations_url":"https://api.github.com/users/RaffEdwardBAH/orgs","repos_url":"https://api.github.com/users/RaffEdwardBAH/repos","events_url":"https://api.github.com/users/RaffEdwardBAH/events{/privacy}","received_events_url":"https://api.github.com/users/RaffEdwardBAH/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-05-02T18:23:57Z","updated_at":"2016-05-02T18:41:40Z","closed_at":null,"body":"It appears networks with Lambda Layers can't be saved though the `to_json` or `to_yaml` methods\r\n\r\nTo implement graves style skip connections for a classification problem I'm using a lambda layer to get the results from the last time step \r\n\r\n`Lambda(lambda x: x[:,-1,:], output_shape=last_step_shape)` \r\n\r\nwhere\r\n\r\n```python\r\ndef last_step_shape(input_shape):\r\n    shape = list(input_shape)\r\n    assert len(shape) == 3\r\n    return tuple((shape[0], shape[2]))\r\n```\r\n\r\nThis model does successfully start training, but I can't save the architecture specification. The model is defined using the Graph API. Looks something like\r\n\r\n```python\r\nmodel = Graph()\r\nmodel.add_input(name='input', batch_input_shape=(batchsize, maxlen), dtype='int')\r\nmodel.add_node(Embedding(257, embed_size, input_length=maxlen, name='embedding', input='input')\r\n\r\nprev_name = 'embedding'\r\n\r\n#add intermediate hidden LSTM layers, they need to return their sequences. \r\nfor l in range(num_layers-1):\r\n    ls = str(l)\r\n    if l > 0:\r\n        model.add_node(LSTM(lstm_layer_size, return_sequences=True), \r\n                       name='_f'+ls, inputs=[prev_name, 'embedding'])\r\n        model.add_node(Lambda(lambda x: x[:,-1,:], output_shape=last_step_shape), name='f'+ls, input='_f'+ls)\r\n    else:\r\n        model.add_node(LSTM(lstm_layer_size, return_sequences=True), \r\n                       name='_f'+ls, input=prev_name)\r\n        model.add_node(Lambda(lambda x: x[:,-1,:], output_shape=last_step_shape), name='f'+ls, input='_f'+ls)\r\n    prev_name = '_f'+ls\r\n\r\n#add last LSTM layer\r\nls = str(num_layers-1)\r\nif num_layers > 1:\r\n    model.add_node(LSTM(lstm_layer_size), name='f'+ls, inputs=[prev_name, 'embedding'])\r\n    model.add_node(Dense(1, activation='sigmoid'), name='sigmoid', inputs=['f'+str(x) for x in range(num_layers)], merge_mode='concat')\r\nelse:\r\n    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)\r\n    model.add_node(Dense(1, activation='sigmoid'), name='sigmoid', input='f'+ls, merge_mode='concat')\r\n    \r\nmodel.add_output(name='output', input='sigmoid')\r\n\r\n# try using different optimizers and different optimizer configs\r\noptimizer = Adam(lr=0.001, clipnorm=grad_clip)\r\n\r\nmodel.compile(optimizer, {'output': 'binary_crossentropy'})\r\n```\r\n\r\nI get the error\r\n\r\n```\r\n\r\n---------------------------------------------------------------------------\r\nUnicodeDecodeError                        Traceback (most recent call last)\r\n<ipython-input-25-e4d9f49c02c8> in <module>()\r\n----> 5 json_string = model.to_json()\r\n      6 # open(name+'.json', 'w').write(json_string)\r\n      7 \r\n\r\n/usr/local/lib/python2.7/dist-packages/keras/engine/topology.pyc in to_json(self, **kwargs)\r\n   2375             'config': config,\r\n   2376         }\r\n-> 2377         return json.dumps(model_config, default=get_json_type, **kwargs)\r\n   2378 \r\n   2379     def to_yaml(self, **kwargs):\r\n\r\n/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)\r\n    248         check_circular=check_circular, allow_nan=allow_nan, indent=indent,\r\n    249         separators=separators, encoding=encoding, default=default,\r\n--> 250         sort_keys=sort_keys, **kw).encode(obj)\r\n    251 \r\n    252 \r\n\r\n/usr/lib/python2.7/json/encoder.pyc in encode(self, o)\r\n    205         # exceptions aren't as detailed.  The list call should be roughly\r\n    206         # equivalent to the PySequence_Fast that ''.join() would do.\r\n--> 207         chunks = self.iterencode(o, _one_shot=True)\r\n    208         if not isinstance(chunks, (list, tuple)):\r\n    209             chunks = list(chunks)\r\n\r\n/usr/lib/python2.7/json/encoder.pyc in iterencode(self, o, _one_shot)\r\n    268                 self.key_separator, self.item_separator, self.sort_keys,\r\n    269                 self.skipkeys, _one_shot)\r\n--> 270         return _iterencode(o, 0)\r\n    271 \r\n    272 def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,\r\n\r\nUnicodeDecodeError: 'utf8' codec can't decode byte 0x83 in position 28: invalid start byte\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/fchollet/keras/issues/comments/216323398","html_url":"https://github.com/fchollet/keras/issues/2582#issuecomment-216323398","issue_url":"https://api.github.com/repos/fchollet/keras/issues/2582","id":216323398,"user":{"login":"fchollet","id":710255,"avatar_url":"https://avatars.githubusercontent.com/u/710255?v=3","gravatar_id":"","url":"https://api.github.com/users/fchollet","html_url":"https://github.com/fchollet","followers_url":"https://api.github.com/users/fchollet/followers","following_url":"https://api.github.com/users/fchollet/following{/other_user}","gists_url":"https://api.github.com/users/fchollet/gists{/gist_id}","starred_url":"https://api.github.com/users/fchollet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fchollet/subscriptions","organizations_url":"https://api.github.com/users/fchollet/orgs","repos_url":"https://api.github.com/users/fchollet/repos","events_url":"https://api.github.com/users/fchollet/events{/privacy}","received_events_url":"https://api.github.com/users/fchollet/received_events","type":"User","site_admin":false},"created_at":"2016-05-02T18:41:40Z","updated_at":"2016-05-02T18:41:40Z","body":"You're probably using an outdated version of Keras. Lambdas can be\nserialized as of 1.0. Also I recommend not using \"Graph\" (which is\ndeprecated) and use the functional API instead.\n\nOn 2 May 2016 at 11:24, RaffEdwardBAH <notifications@github.com> wrote:\n\n> It appears networks with Lambda Layers can't be saved though the to_json\n> or to_yaml methods\n>\n> To implement graves style skip connections for a classification problem\n> I'm using a lambda layer to get the results from the last time step\n>\n> Lambda(lambda x: x[:,-1,:], output_shape=last_step_shape)\n>\n> where\n>\n> def last_step_shape(input_shape):\n>     shape = list(input_shape)\n>     assert len(shape) == 3\n>     return tuple((shape[0], shape[2]))\n>\n> This model does successfully start training, but I can't save the\n> architecture specification. The model is defined using the Graph API. Looks\n> something like\n>\n> model = Graph()\n> model.add_input(name='input', batch_input_shape=(batchsize, maxlen), dtype='int')\n> model.add_node(Embedding(257, embed_size, input_length=maxlen, name='embedding', input='input')\n> prev_name = 'embedding'\n> #add intermediate hidden LSTM layers, they need to return their sequences. for l in range(num_layers-1):\n>     ls = str(l)\n>     if l > 0:\n>         model.add_node(LSTM(lstm_layer_size, return_sequences=True),\n>                        name='_f'+ls, inputs=[prev_name, 'embedding'])\n>         model.add_node(Lambda(lambda x: x[:,-1,:], output_shape=last_step_shape), name='f'+ls, input='_f'+ls)\n>     else:\n>         model.add_node(LSTM(lstm_layer_size, return_sequences=True),\n>                        name='_f'+ls, input=prev_name)\n>         model.add_node(Lambda(lambda x: x[:,-1,:], output_shape=last_step_shape), name='f'+ls, input='_f'+ls)\n>     prev_name = '_f'+ls\n> #add last LSTM layerls = str(num_layers-1)if num_layers > 1:\n>     model.add_node(LSTM(lstm_layer_size), name='f'+ls, inputs=[prev_name, 'embedding'])\n>     model.add_node(Dense(1, activation='sigmoid'), name='sigmoid', inputs=['f'+str(x) for x in range(num_layers)], merge_mode='concat')else:\n>     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)\n>     model.add_node(Dense(1, activation='sigmoid'), name='sigmoid', input='f'+ls, merge_mode='concat')\n>\n> model.add_output(name='output', input='sigmoid')\n> # try using different optimizers and different optimizer configsoptimizer = Adam(lr=0.001, clipnorm=grad_clip)\n>\n> model.compile(optimizer, {'output': 'binary_crossentropy'})\n>\n> I get the error\n>\n>\n> ---------------------------------------------------------------------------\n> UnicodeDecodeError                        Traceback (most recent call last)\n> <ipython-input-25-e4d9f49c02c8> in <module>()\n> ----> 5 json_string = model.to_json()\n>       6 # open(name+'.json', 'w').write(json_string)\n>       7\n>\n> /usr/local/lib/python2.7/dist-packages/keras/engine/topology.pyc in to_json(self, **kwargs)\n>    2375             'config': config,\n>    2376         }\n> -> 2377         return json.dumps(model_config, default=get_json_type, **kwargs)\n>    2378\n>    2379     def to_yaml(self, **kwargs):\n>\n> /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)\n>     248         check_circular=check_circular, allow_nan=allow_nan, indent=indent,\n>     249         separators=separators, encoding=encoding, default=default,\n> --> 250         sort_keys=sort_keys, **kw).encode(obj)\n>     251\n>     252\n>\n> /usr/lib/python2.7/json/encoder.pyc in encode(self, o)\n>     205         # exceptions aren't as detailed.  The list call should be roughly\n>     206         # equivalent to the PySequence_Fast that ''.join() would do.\n> --> 207         chunks = self.iterencode(o, _one_shot=True)\n>     208         if not isinstance(chunks, (list, tuple)):\n>     209             chunks = list(chunks)\n>\n> /usr/lib/python2.7/json/encoder.pyc in iterencode(self, o, _one_shot)\n>     268                 self.key_separator, self.item_separator, self.sort_keys,\n>     269                 self.skipkeys, _one_shot)\n> --> 270         return _iterencode(o, 0)\n>     271\n>     272 def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,\n>\n> UnicodeDecodeError: 'utf8' codec can't decode byte 0x83 in position 28: invalid start byte\n>\n> —\n> You are receiving this because you are subscribed to this thread.\n> Reply to this email directly or view it on GitHub\n> <https://github.com/fchollet/keras/issues/2582>\n>\n"}}