Ошибка Keras: у операции есть `None` для градиента - PullRequest
0 голосов
/ 16 апреля 2020

Предположим, что вы хотите построить GAN в keras. Генератор преобразует изображение из domain A to domain B. Обычно изображение B теперь передается в discriminator, чтобы получить обратную связь для generator, например, например: (да, ваше сгенерированное изображение B (назовем его B`) почти так же хорошо, как настоящий B).

Предположим, что мы хотим различить guish spartial information, потому что области A и B там слишком разные, и дискриминатор может легко найти шаблоны в этой пространственной области. Поэтому он должен просто использовать данные гистограммы (HSV, или информацию о текстуре, например, LBP), чтобы различаться между B и B´.

Теперь проблема в том, что вам нужно использовать custom-keras-layer для преобразования B´ изображения из RGB в HSV и извлеките текстуру, например LBP, перед передачей изображений в дискриминатор. Этот пользовательский слой не имеет весов, очевидно, потому что он в основном только подсчитывает и изменяет форму (кроме HSV-преобразования).

Но у Кераса есть проблемы со слоями без весов после использования генератора. Каким-то образом график не может быть построен правильно, и некоторые градиенты не могут быть найдены. Любые идеи, почему и как я могу исправить эту ошибку?

Пользовательский слой

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

class Identity_Loss(Layer):

    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 [[input_shape[0],None,None,2],[input_shape[0],None,None,3],[input_shape[0],None,None,1]]

Оборачивание слоя в такую ​​структуру:

def Combined_model():

  input_A = Input(shape=[None,None,3])
  input_B = Input(shape=[None,None,1])

  fake_A=generator(input_A)

  SV,HSV_mask,diff=custom_layer([fake_A,input_B])

  dis1= discriminator_1(diff)

  model = Model([input_A,input_B],[dis1])
  model.summary()

  return model

Combined= Combined_model()
dis1=Combined.predict([x,grtr])

# just for testing
generator.compile(loss="mse", optimizer="adam")
generator.train_on_batch([x,grtr],[dis1])

Вызов комбинации приводит к этой ошибке:

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

ValueError                                Traceback (most recent call last)

<ipython-input-39-6930bbb3352b> in <module>()
     32 generator.compile(loss="mse", optimizer="adam")
     33 
---> 34 generator.train_on_batch([x,grtr],[gt_iso,fake_HIS,SV])

4 frames

/usr/local/lib/python3.6/dist-packages/keras/engine/training.py in train_on_batch(self, x, y, sample_weight, class_weight, reset_metrics)
   1511         else:
   1512             ins = x + y + sample_weights
-> 1513         self._make_train_function()
   1514         outputs = self.train_function(ins)
   1515 

/usr/local/lib/python3.6/dist-packages/keras/engine/training.py in _make_train_function(self)
    314                     training_updates = self.optimizer.get_updates(
    315                         params=self._collected_trainable_weights,
--> 316                         loss=self.total_loss)
    317                 updates = self.updates + training_updates
    318 

/usr/local/lib/python3.6/dist-packages/keras/legacy/interfaces.py in wrapper(*args, **kwargs)
     89                 warnings.warn('Update your `' + object_name + '` call to the ' +
     90                               'Keras 2 API: ' + signature, stacklevel=2)
---> 91             return func(*args, **kwargs)
     92         wrapper._original_function = func
     93         return wrapper

/usr/local/lib/python3.6/dist-packages/keras/optimizers.py in get_updates(self, loss, params)
    502     @K.symbolic
    503     def get_updates(self, loss, params):
--> 504         grads = self.get_gradients(loss, params)
    505         self.updates = [K.update_add(self.iterations, 1)]
    506 

/usr/local/lib/python3.6/dist-packages/keras/optimizers.py in get_gradients(self, loss, params)
     91         grads = K.gradients(loss, params)
     92         if any(x is None for x in grads):
---> 93             raise ValueError('An operation has `None` for gradient. '
     94                              'Please make sure that all of your ops have a '
     95                              'gradient defined (i.e. are differentiable). '

ValueError: An operation has `None` for gradient. Please make sure that all of your ops have a gradient defined (i.e. are differentiable). Common ops without gradient: K.argmax, K.round, K.eval.

Каким-то образом keras пытается вычислить градиенты на слоях без весов. Очевидно, что это не удается, потому что их нет. В основном я пытался перестроить структуру пользовательского примера keras " Antirectifier ", без метода build и использования super, чтобы не инициализировать какие-либо веса.

Есть ли возможность пропустить обратное распространение через пользовательский слой мгновенно к генератору?

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