josteinb
josteinb

Reputation: 2172

Custom filters in convolutional network with keras

I am attempting to create a convolutional network with keras in which

from keras.layers import Input, LSTM, concatenate
from keras.models import Model
from keras.utils.vis_utils import model_to_dot
from IPython.display import display, SVG


inputs = Input(shape=(None, 4))
filter_unit = LSTM(1)
conv = concatenate([filter_unit(inputs[..., 0:2]),
                    filter_unit(inputs[..., 2:4])])
model = Model(inputs=inputs, outputs=conv)
SVG(model_to_dot(model, show_shapes=True).create(prog='dot', format='svg'))

I have attempted to slice the input tensor along the feature dimension to split the (artificially small) input for use with two units of the filter. In the example, the filter is a single LSTM unit. My hope is that I will be able to use arbitrary models in place of the LSTM.

However, this fails on the model = ... line:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-a9f7f2ffbe17> in <module>()
      9 conv = concatenate([filter_unit(inputs[..., 0:2]),
     10                     filter_unit(inputs[..., 2:4])])
---> 11 model = Model(inputs=inputs, outputs=conv)
     12 SVG(model_to_dot(model, show_shapes=True).create(prog='dot', format='svg'))

~/.local/opt/anaconda3/envs/trafficprediction/lib/python3.6/site-packages/keras/legacy/interfaces.py in wrapper(*args, **kwargs)
     86                 warnings.warn('Update your `' + object_name +
     87                               '` call to the Keras 2 API: ' + signature, stacklevel=2)
---> 88             return func(*args, **kwargs)
     89         wrapper._legacy_support_signature = inspect.getargspec(func)
     90         return wrapper

~/.local/opt/anaconda3/envs/trafficprediction/lib/python3.6/site-packages/keras/engine/topology.py in __init__(self, inputs, outputs, name)
   1703         nodes_in_progress = set()
   1704         for x in self.outputs:
-> 1705             build_map_of_graph(x, finished_nodes, nodes_in_progress)
   1706 
   1707         for node in reversed(nodes_in_decreasing_depth):

~/.local/opt/anaconda3/envs/trafficprediction/lib/python3.6/site-packages/keras/engine/topology.py in build_map_of_graph(tensor, finished_nodes, nodes_in_progress, layer, node_index, tensor_index)
   1693                 tensor_index = node.tensor_indices[i]
   1694                 build_map_of_graph(x, finished_nodes, nodes_in_progress,
-> 1695                                    layer, node_index, tensor_index)
   1696 
   1697             finished_nodes.add(node)

~/.local/opt/anaconda3/envs/trafficprediction/lib/python3.6/site-packages/keras/engine/topology.py in build_map_of_graph(tensor, finished_nodes, nodes_in_progress, layer, node_index, tensor_index)
   1693                 tensor_index = node.tensor_indices[i]
   1694                 build_map_of_graph(x, finished_nodes, nodes_in_progress,
-> 1695                                    layer, node_index, tensor_index)
   1696 
   1697             finished_nodes.add(node)

~/.local/opt/anaconda3/envs/trafficprediction/lib/python3.6/site-packages/keras/engine/topology.py in build_map_of_graph(tensor, finished_nodes, nodes_in_progress, layer, node_index, tensor_index)
   1663             """
   1664             if not layer or node_index is None or tensor_index is None:
-> 1665                 layer, node_index, tensor_index = tensor._keras_history
   1666             node = layer.inbound_nodes[node_index]
   1667 

AttributeError: 'Tensor' object has no attribute '_keras_history'

The same problem occurs if LSTM is replaced by Dense. It is far from clear to me what this error message means. What am I doing wrong?

There is one question on the same error (link below), but it is not clear to me how a Lambda layer should be used, or if that is even the right solution.

AttributeError: 'Tensor' object has no attribute '_keras_history'

Upvotes: 0

Views: 543

Answers (1)

rll
rll

Reputation: 5587

The problem lies in the way the inputs are sliced. The LSTM Layers are expecting a Layer object as input and you are feeding a Tensor object. You could try to add a lambda layer (or two in the example) that slices the inputs in order to feed the LSTM layers. Something like:

y = Lambda(lambda x: x[:,0,:,:], output_shape=(1,) + input_shape[2:])(x)

And this y layer would be the (sliced) input to the following layers.

Upvotes: 1

Related Questions