Предположим, что вы хотите построить 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
, чтобы не инициализировать какие-либо веса.
Есть ли возможность пропустить обратное распространение через пользовательский слой мгновенно к генератору?