Как построить слой, объединяющий два изображения, в порядке, определяемом третьим параметром - PullRequest
2 голосов
/ 16 февраля 2020

Мне нужен слой, который принимает три тензора в качестве входных данных: два (n, m, k) тензора и один (1) тензор, т.е. одно единственное число. На выходе должен быть тензор (n, m, 2k), который достигается тем, что первые k каналов являются одним изображением, а остальные - другим. Теперь выгода заключается в том, что порядок их слияния - помещаем ли мы изображение одно поверх изображения два или наоборот - должен определяться тем, больше ли третий вход больше 0 или нет.

По моему мнению, это полностью статический c слой без каких-либо обучаемых параметров, поэтому я попытался сделать выбор упорядочения со слоем Lambda следующим образом:

def image_scrambler(inp): #inp = [im1, im2, aux_input]
    im1, im2, aux_input = inp[0],inp[1],inp[2]
    assert aux_input==1 or aux_input==0
    if aux_input==0:
        return [im1, im2]
    else:
        return [im2,im1]
paired_images = Lambda(image_scrambler)([image_input, decoder, aux_input])

Это не работает, потому что это протестует, что слой является Dynami c и должен быть построен с динамическим = True. Когда я пытаюсь это сделать, я получаю RecursionError следующим образом:

---------------------------------------------------------------------------
RecursionError                            Traceback (most recent call last)
<ipython-input-15-a40adb50e97d> in <module>
      7         return [im2,im1]
      8 aux_input = Input(shape=(1))
----> 9 paired_images = Lambda(image_scrambler,dynamic=True)([image_input, decoder, aux_input])

c:\users\vilhelm\appdata\local\programs\python\python36\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py in __call__(self, inputs, *args, **kwargs)
    791             # TODO(fchollet): consider py_func as an alternative, which
    792             # would enable us to run the underlying graph if needed.
--> 793             outputs = self._symbolic_call(inputs)
    794 
    795           if outputs is None:

c:\users\vilhelm\appdata\local\programs\python\python36\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py in _symbolic_call(self, inputs)
   2126   def _symbolic_call(self, inputs):
   2127     input_shapes = nest.map_structure(lambda x: x.shape, inputs)
-> 2128     output_shapes = self.compute_output_shape(input_shapes)
   2129 
   2130     def _make_placeholder_like(shape):

c:\users\vilhelm\appdata\local\programs\python\python36\lib\site-packages\tensorflow_core\python\keras\utils\tf_utils.py in wrapper(instance, input_shape)
    304     if input_shape is not None:
    305       input_shape = convert_shapes(input_shape, to_tuples=True)
--> 306     output_shape = fn(instance, input_shape)
    307     # Return shapes from `fn` as TensorShapes.
    308     if output_shape is not None:

c:\users\vilhelm\appdata\local\programs\python\python36\lib\site-packages\tensorflow_core\python\keras\layers\core.py in compute_output_shape(self, input_shape)
    808       with context.eager_mode():
    809         try:
--> 810           return super(Lambda, self).compute_output_shape(input_shape)
    811         except NotImplementedError:
    812           raise NotImplementedError(

c:\users\vilhelm\appdata\local\programs\python\python36\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py in compute_output_shape(self, input_shape)
    552           try:
    553             if self._expects_training_arg:
--> 554               outputs = self(inputs, training=False)
    555             else:
    556               outputs = self(inputs)

... last 5 frames repeated, from the frame below ...

c:\users\vilhelm\appdata\local\programs\python\python36\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py in __call__(self, inputs, *args, **kwargs)
    791             # TODO(fchollet): consider py_func as an alternative, which
    792             # would enable us to run the underlying graph if needed.
--> 793             outputs = self._symbolic_call(inputs)
    794 
    795           if outputs is None:

RecursionError: maximum recursion depth exceeded while calling a Python object

Так что на самом деле это ничего не говорит мне о том, почему это не сработало, оно просто рухнуло.

I ' я предпочел бы не возиться с созданием класса слоя, унаследованного от Layer, если есть какой-нибудь способ заставить работать менее сложный метод.

1 Ответ

0 голосов
/ 16 февраля 2020

Всегда работайте с «тензорными функциями», а не с «Python functions»:

import keras.backend as K

def image_scrambler(inp): #inp = [im1, im2, aux_input]
    im1, im2, aux_input = inp[0],inp[1],inp[2]

    is_greater = K.greater(aux_input, 0.5)
    return K.switch(is_greater,                     #this is a keras "if"
                    K.concatenate([img2, img1]),    #result if true
                    K.concatenate([img1, img2]))    #result if false

paired_images = Lambda(image_scrambler)([image_input, decoder, aux_input])

Я не думаю, что утверждение было бы хорошей идеей, вы должны сделать это при проверке ваших данных, не в модели.

Хотя вы говорите, что оно не обучаемо, возможно, вы ожидаете, что оно будет обучаемо каким-то образом? Что решает, каким будет значение aux_input? Если вы ожидаете, что это будет изучено в другом месте, я сомневаюсь, что это сработает. Возможно, это должно быть непрерывное значение, заданное сигмоидом где-то. Тогда он «может» иметь шанс на работу, хотя часть if нарушает (но не нарушает) обратное распространение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...