How to chain/compose layers in keras 2 functional API without specifying input (or input shape)

烈酒焚心 提交于 2019-12-24 00:36:43

问题


I would like be able to several layers together, but before specifying the input, something like the following:

# conv is just a layer, no application
conv = Conv2D(64, (3,3), activation='relu', padding='same', name='conv')
# this doesn't work:
bn = BatchNormalization()(conv)

Note that I don't want to specify the input nor its shape if it can be avoided, I want to use this as a shared layer for multiple inputs at a later point.

Is there a way to do that? The above gives the following error:

>>> conv = Conv2D(64, (3,3), activation='relu', padding='same', name='conv')
>>> bn = BatchNormalization()(conv)
Traceback (most recent call last):
  File "/home/mitchus/anaconda3/envs/tf/lib/python3.6/site-packages/keras/engine/topology.py", line 419, in assert_input_compatibility
    K.is_keras_tensor(x)
  File "/home/mitchus/anaconda3/envs/tf/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py", line 393, in is_keras_tensor
    raise ValueError('Unexpectedly found an instance of type `' + str(type(x)) + '`. '
ValueError: Unexpectedly found an instance of type `<class 'keras.layers.convolutional.Conv2D'>`. Expected a symbolic tensor instance.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/mitchus/anaconda3/envs/tf/lib/python3.6/site-packages/keras/engine/topology.py", line 552, in __call__
    self.assert_input_compatibility(inputs)
  File "/home/mitchus/anaconda3/envs/tf/lib/python3.6/site-packages/keras/engine/topology.py", line 425, in assert_input_compatibility
    str(inputs) + '. All inputs to the layer '
ValueError: Layer batch_normalization_4 was called with an input that isn't a symbolic tensor. Received type: <class 'keras.layers.convolutional.Conv2D'>. Full input: [<keras.layers.convolutional.Conv2D object at 0x7f3f6e54b748>]. All inputs to the layer should be tensors.

Grabbing the output of the conv layer doesn't do the trick either:

>>> bn = BatchNormalization()(conv.output)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/mitchus/anaconda3/envs/tf/lib/python3.6/site-packages/keras/engine/topology.py", line 941, in output
    ' has no inbound nodes.')
AttributeError: Layer conv has no inbound nodes.

回答1:


Try this:

def create_shared_layers():
    layers = [
        Conv2D(64, (3,3), activation='relu', padding='same', name='conv'),
        BatchNormalization()
    ]
    def shared_layers(x):
        for layer in layers:
            x = layer(x)
        return x
    return shared_layers

Later, you can do something like:

shared_layers = create_shared_layers()
...
h1 = shared_layers(x1)
h2 = shared_layers(x2)



回答2:


What about using a Lambda layer.

import functools
from typing import List

from tensorflow import keras


def compose_layers(layers: List[keras.layers.Layer], **kargs) -> keras.layers.Layer:
  return keras.layers.Lambda(
    lambda x: functools.reduce(lambda tensor, layer: layer(tensor), layers, x),
    **kargs,
  )

then you can just call the compose_layers method to get the composition.

layers = [
  Conv2D(64, (3,3), activation='relu', padding='same', name='conv'),
  BatchNormalization()
]

composed_layers = compose_layers(layers, name='composed_layers')


来源:https://stackoverflow.com/questions/45439492/how-to-chain-compose-layers-in-keras-2-functional-api-without-specifying-input

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!