Repository: keras-team/keras

Issue:
YAML serialization throws exception with Regularizers
If a model contains a regularizer, YAML serialization throws an exception. Using latest Keras 1.0.3.

Compare:

``` python
>>> model = Sequential([LSTM(20, input_shape=(2,3))])
>>> model.to_yaml()
'class_name: Sequential\nconfig:\n- class_name: LSTM\n  config:\n    U_regularizer: null\n    W_regularizer: null\n    activation: tanh\n    b_regularizer: null\n    batch_input_shape: !!python/tuple [null, 2, 3]\n    consume_less: cpu\n    dropout_U: 0.0\n    dropout_W: 0.0\n    forget_bias_init: one\n    go_backwards: false\n    init: glorot_uniform\n    inner_activation: hard_sigmoid\n    inner_init: orthogonal\n    input_dim: 3\n    input_dtype: float32\n    input_length: null\n    name: lstm_3\n    output_dim: 20\n    return_sequences: false\n    stateful: false\n    trainable: true\n    unroll: false\n'
>>> model = Sequential([LSTM(20, input_shape=(2,3), W_regularizer=l2())])
>>> model.to_yaml()
/usr/lib64/python3.4/site-packages/yaml/representer.py:135: FutureWarning: comparison to `None` will result in an elementwise object comparison in the future.
  if data in [None, ()]:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python3.4/site-packages/keras/engine/topology.py", line 2391, in to_yaml
    return yaml.dump(model_config, **kwargs)
  File "/usr/lib64/python3.4/site-packages/yaml/__init__.py", line 200, in dump
    return dump_all([data], stream, Dumper=Dumper, **kwds)
  File "/usr/lib64/python3.4/site-packages/yaml/__init__.py", line 188, in dump_all
    dumper.represent(data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 26, in represent                                                                                                                                                       
    node = self.represent_data(data)                                                                                                                                                                                                         
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 47, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 203, in represent_dict
    return self.represent_mapping('tag:yaml.org,2002:map', data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 116, in represent_mapping
    node_value = self.represent_data(item_value)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 47, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 195, in represent_list
    return self.represent_sequence('tag:yaml.org,2002:seq', data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 91, in represent_sequence
    node_item = self.represent_data(item)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 47, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 203, in represent_dict
    return self.represent_mapping('tag:yaml.org,2002:map', data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 116, in represent_mapping
    node_value = self.represent_data(item_value)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 47, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 203, in represent_dict
    return self.represent_mapping('tag:yaml.org,2002:map', data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 116, in represent_mapping
    node_value = self.represent_data(item_value)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 47, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 203, in represent_dict
    return self.represent_mapping('tag:yaml.org,2002:map', data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 116, in represent_mapping
    node_value = self.represent_data(item_value)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 51, in represent_data
    node = self.yaml_multi_representers[data_type](self, data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 352, in represent_object
    return self.represent_mapping(tag+function_name, value)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 116, in represent_mapping
    node_value = self.represent_data(item_value)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 47, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 282, in represent_tuple
    return self.represent_sequence('tag:yaml.org,2002:python/tuple', data)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 91, in represent_sequence
    node_item = self.represent_data(item)
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 33, in represent_data
    if self.ignore_aliases(data):
  File "/usr/lib64/python3.4/site-packages/yaml/representer.py", line 135, in ignore_aliases
    if data in [None, ()]:
TypeError: data type not understood
```

Tested with LSTM & Embedding layer, W_regularizer and U_regularizer, l1 and l2. Always throws. `.to_json()` works fine. Is there some serialization code missing for l1/l2?



Discussion:
Hum... I also confirmed the same problem in both Python 3.5 and 2.7.11.

``` python
from keras.layers import LSTM
from keras.models import Sequential
from keras.regularizers import l2
model = Sequential([LSTM(20, input_shape=(2,3), W_regularizer=l2())])
model.to_yaml()
```


Resolving patch:
diff --git a/keras/regularizers.py b/keras/regularizers.py
--- a/keras/regularizers.py
+++ b/keras/regularizers.py
@@ -41,8 +41,8 @@ def __call__(self, loss):
 
     def get_config(self):
         return {'name': self.__class__.__name__,
-                'l1': self.l1,
-                'l2': self.l2}
+                'l1': float(self.l1),
+                'l2': float(self.l2)}
 
 
 class ActivityRegularizer(Regularizer):
@@ -68,8 +68,8 @@ def __call__(self, loss):
 
     def get_config(self):
         return {'name': self.__class__.__name__,
-                'l1': self.l1,
-                'l2': self.l2}
+                'l1': float(self.l1),
+                'l2': float(self.l2)}
 
 
 def l1(l=0.01):


Test patch: