nengo-dl icon indicating copy to clipboard operation
nengo-dl copied to clipboard

Converter KeyError when using Keras Sequential API to create the input

Open arvoelke opened this issue 4 years ago • 2 comments

Minimal Reproducer:


import nengo_dl
import tensorflow as tf

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(16, input_shape=(1,), activation="relu"))
model.summary()

nengo_converter = nengo_dl.Converter(
    model,
    swap_activations={
        tf.keras.activations.relu: nengo.RectifiedLinear(),
    },
    synapse=None,
)

assert model.input is model.layers[0].input

print(model.input, list(nengo_converter.inputs)[0])
nengo_input = nengo_converter.inputs[model.input]

Output:

Model: "sequential_10"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_18 (Dense)             (None, 16)                32        
=================================================================
Total params: 32
Trainable params: 32
Non-trainable params: 0
_________________________________________________________________
Tensor("dense_18_input:0", shape=(None, 1), dtype=float32) Tensor("input_10:0", shape=(None, 1), dtype=float32)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-61-95be1111e3ee> in <module>
     14 print(model.input, list(nengo_converter.inputs)[0])
     15 
---> 16 nengo_input = nengo_converter.inputs[model.input]

~/anaconda3/envs/*/lib/python3.7/site-packages/nengo_dl/converter.py in __getitem__(self, key)
    399 
    400         def __getitem__(self, key):
--> 401             return self.dict[self._get_key(key)]
    402 
    403         def __iter__(self):

KeyError: <Reference wrapping <tf.Tensor 'dense_18_input:0' shape=(None, 1) dtype=float32>>

Expected Behaviour: Expected to be able to grab the converted input by looking up model.input, analogous to how it's done here: https://www.nengo.ai/nengo-loihi/examples/keras-to-loihi.html, but instead using the Sequential() API. It looks like the issue is that the name in the sequential model ("dense_18_input:0") doesn't match the one in the converter ("input_10:0")?

Current Workaround:

assert len(nengo_converter.inputs) == 1
nengo_input = list(nengo_converter.inputs)[0]

arvoelke avatar Jul 16 '20 21:07 arvoelke

When you pass in a Sequential model the Converter automatically converts it to a Functional model for you, and then that functional model is what is used for the actual conversion process. So all the converter data structures will be with respect to that functional model, not the sequential one. If you change your code to nengo_input = nengo_converter.inputs[nengo_converter.model.input] (note, using nengo_converter.model instead of model), then everything should work as expected.

I'll add a sentence to the warning that gets raised when you pass in a Sequential model to make this more obvious.

drasmuss avatar Jul 16 '20 22:07 drasmuss

Thanks! That worked. As a quick note I was also seeing this when similarly trying to lookup a particular layer, e.g., via nengo_converter.layers[model.get_layer("layer_name").output]. I also tried nengo_converter.model instead of model. As well as model.layers[index]. Just mentioning this as a nice-to-have or in case I'm doing the wrong thing.

arvoelke avatar Jul 17 '20 14:07 arvoelke