Ошибка формы вывода в пользовательском слое Keras / TensorFlow - PullRequest
0 голосов
/ 15 апреля 2020

Я написал свой собственный слой Keras / Tensorflow. Передача изображений в него работает нормально, но использование его в сочетании с другими слоями дает основную ошибку. Каким-то образом выходная форма моего пользовательского слоя должна быть неправильной, или что-то вроде "Nonetype".

Короче говоря, пользовательский слой преобразует изображение из цветового пространства A в B, а затем создает гистограмму из некоторых каналов. Это уровень предварительной обработки для дискриминатора GAN, поэтому он должен быть частью модели обратного распространения генератора.

from keras import backend as K
from keras.layers import Layer

class Identity_Loss(Layer):

def __init__(self, output_dim, **kwargs):
    self.output_dim = output_dim
    super(Identity_Loss, self).__init__(**kwargs)

def build(self, input_shape):
    super(Identity_Loss, self).build(input_shape)  # Be sure to call this at the end

def call(self, x):

    assert isinstance(x, list)
    input_1,input_2=x

    # Transform BGR to RGB and than to HSV
    channels = tf.unstack (input_1, axis=-1)
    RGB    = tf.stack   ([channels[2], channels[1], channels[0]], axis=-1)
    RGB=tf.cast(tf.multiply(tf.truediv(tf.add(RGB,1.0),2.0),255.0),dtype=tf.int32)
    RGB=tf.cast(RGB,dtype=tf.float32)
    HSV=tf.image.rgb_to_hsv(RGB,name=None)

###########################################################
     SV=HSV[:,:,:,1:]
############################################################

 #make mask binary and multiply with image
        y=tf.math.greater(input_2, 0)
        y=tf.cast(y, tf.float32, name=None)
        HSV_mask = tf.math.multiply(HSV, y)
 #Count color occurences ###########################
        shape=tf.shape(HSV_mask)
        length=shape[1]*shape[2]

 #transform
        Hue=HSV_mask[:,:,:,:1]
        Hue=tf.cast(tf.multiply(Hue,255.0),dtype=tf.int32)
        Hue2 = tf.reshape(Hue, [length])

 #prevent that the shape changes
        filler=tf.range(0,length, 1,dtype=tf.int32) 
        filler = tf.reshape(filler, [length])
        Hue3 = tf.stack([Hue2,filler],axis=-1)
        Hue3 = tf.reshape(Hue3, [2*length])

 #Count Hue       
        y1, idx1, count1 = tf.unique_with_counts(Hue3)

        maximum=tf.cast(tf.math.reduce_max(count1[1:257]),dtype=tf.int32)
        diff=tf.reshape(count1[1:257],(16,16))
        diff=tf.expand_dims(diff, axis=-1)
        diff=tf.expand_dims(diff, axis=0)
        diff=tf.truediv(diff,maximum)
        diff=tf.cast(diff,dtype=tf.float32)

    return [SV,HSV_mask,diff]

def compute_output_shape(self, input_shape):
    assert isinstance(input_shape, list)
    return [[None,None,2],[None,None,3],[None,None,1]]

Это соответствующее сообщение об ошибке при передаче вывода пользовательского уровня в другой уровень CNN. например:

---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-89-3caaa8c77e0c> in <module>()
      5 c,d,e=mod([d,input_B])
      6 
----> 7 dd=model(d)
      8 
      9 bb = Model([input_A,input_B],[c,d,dd])

3 frames

/usr/local/lib/python3.6/dist-packages/keras/engine/base_layer.py in __call__(self, inputs, **kwargs)
    487             # Actually call the layer,
    488             # collecting output(s), mask(s), and shape(s).
--> 489             output = self.call(inputs, **kwargs)
    490             output_mask = self.compute_mask(inputs, previous_mask)
    491 

/usr/local/lib/python3.6/dist-packages/keras/engine/network.py in call(self, inputs, mask)
    581             return self._output_tensor_cache[cache_key]
    582         else:
--> 583             output_tensors, _, _ = self.run_internal_graph(inputs, masks)
    584             return output_tensors
    585 

/usr/local/lib/python3.6/dist-packages/keras/engine/network.py in run_internal_graph(self, inputs, masks)
    796                         input_shapes = unpack_singleton(
    797                             [x._keras_shape for x in computed_tensors])
--> 798                         shapes = to_list(layer.compute_output_shape(input_shapes))
    799                         uses_learning_phase = any(
    800                             [x._uses_learning_phase for x in computed_tensors])

/usr/local/lib/python3.6/dist-packages/keras/layers/convolutional.py in compute_output_shape(self, input_shape)
    191     def compute_output_shape(self, input_shape):
    192         if self.data_format == 'channels_last':
--> 193             space = input_shape[1:-1]
    194         elif self.data_format == 'channels_first':
    195             space = input_shape[2:]

TypeError: 'NoneType' object is not subscriptable

1 Ответ

1 голос
/ 15 апреля 2020

Краткий ответ: добавить размер партии к выходной форме слоя, возвращаемого методом compute_output_shape.

Длинный ответ: Модели Keras всегда работают с партией входные выборки и, следовательно, все значения входной формы и выходной формы в слое Keras содержат размерность пакета. Следовательно, вам также необходимо учитывать это при расчете формы вывода слоя:

def compute_output_shape(self, input_shape):
    return [
        [input_shape[0], None, None, 2],
        [input_shape[0], None, None, 3],
        [input_shape[0], None, None, 1]
    ]

Поскольку размер пакета не меняется от слоя к слою, поэтому вам просто нужно добавить input_shape[0] к возвращаемому формы, как указано выше.

...