2017-07-14 77 views
0

繼這個paper on domain adaptation之後,我試圖在Tensorflow中實現以下漸變反轉圖層(在Thera後端編寫Keras,在Keras issue中找到),因爲我的模型與Theano運行不佳。在Tensorflow中實現Theano操作

class GradientReversalLayer(Layer): 
    """ Reverse a gradient 
    <feedforward> return input x 
    <backward> return -lambda * delta 
    """ 
    def __init__(self, hp_lambda, **kwargs): 
     super(GradientReversalLayer, self).__init__(**kwargs) 
     self.hp_lambda = hp_lambda 
     self.gr_op = ReverseGradient(self.hp_lambda) 

    def build(self, input_shape): 
     self.trainable_weights = [] 

    def call(self, x, mask=None): 
     return self.gr_op(x) 

    def get_output_shape_for(self, input_shape): 
     return input_shape 

    def get_config(self): 
     config = {"name": self.__class__.__name__, 
         "lambda": self.hp_lambda} 
     base_config = super(GradientReversalLayer, self).get_config() 
     return dict(list(base_config.items()) + list(config.items())) 

層執行此操作:

import theano 
    from keras.engine import Layer 

    class ReverseGradient(theano.Op): 
     """ theano operation to reverse the gradients 
     Introduced in http://arxiv.org/pdf/1409.7495.pdf 
     """ 

     view_map = {0: [0]} 

     __props__ = ('hp_lambda',) 

     def __init__(self, hp_lambda): 
      super(ReverseGradient, self).__init__() 
      self.hp_lambda = hp_lambda 

     def make_node(self, x): 
      assert hasattr(self, '_props'), "Your version of theano is too old to support __props__." 
      x = theano.tensor.as_tensor_variable(x) 
      return theano.Apply(self, [x], [x.type()]) 

     def perform(self, node, inputs, output_storage): 
      xin, = inputs 
      xout, = output_storage 
      xout[0] = xin 

     def grad(self, input, output_gradients): 
      return [-self.hp_lambda * output_gradients[0]] 

     def infer_shape(self, node, i0_shapes): 
      return i0_shapes 

我爲什麼不能這樣使用它?

如果我跑我的模型與TF後端以及與此功能寫在Theano我得到以下錯誤:

theano.tensor.var.AsTensorError: ('Cannot convert Tensor("concatenate_1/concat:0", shape=(?, ?, 128), dtype=float32) to TensorType', <class 'tensorflow.python.framework.ops.Tensor'>) 

調用它像這樣經過:

lstm_concat = concatenate([hidden_out_1, hidden_out_2]) 
lstm_concat = FlipGradientKeras.GradientReversalLayer(0.31)(lstm_concat) 

怎麼辦我將此操作轉換爲TF operation

文檔約adding a new operation只是建議來實現它在C++中。

ops codes顯示了一般框架,但我想確保我正在實施Theano op所做的一切。

我會以爲這將是對的東西的行:

def ReverseGradient(input_tensor, hp_lambda): 

    with ops.name_scope(name, "ReverseGradient", [input_tensor, hp_lambda]) as name: 
     input_tensor = ops.convert_to_tensor(input_tensor, name="input_tensor") 

但我真的不知道休息。

在此先感謝!

回答

2

我通過擴大上完成here的工作解決了這個問題。

這裏的工作代碼:

import tensorflow as tf 
from keras.engine import Layer 
import keras.backend as K 

def reverse_gradient(X, hp_lambda): 
    '''Flips the sign of the incoming gradient during training.''' 
    try: 
     reverse_gradient.num_calls += 1 
    except AttributeError: 
     reverse_gradient.num_calls = 1 

    grad_name = "GradientReversal%d" % reverse_gradient.num_calls 

    @tf.RegisterGradient(grad_name) 
    def _flip_gradients(op, grad): 
     return [tf.negative(grad) * hp_lambda] 

    g = K.get_session().graph 
    with g.gradient_override_map({'Identity': grad_name}): 
     y = tf.identity(X) 

    return y 

class GradientReversal(Layer): 
    '''Flip the sign of gradient during training.''' 
    def __init__(self, hp_lambda, **kwargs): 
     super(GradientReversal, self).__init__(**kwargs) 
     self.supports_masking = False 
     self.hp_lambda = hp_lambda 

    def build(self, input_shape): 
     self.trainable_weights = [] 

    def call(self, x, mask=None): 
     return reverse_gradient(x, self.hp_lambda) 

    def get_output_shape_for(self, input_shape): 
     return input_shape 

    def get_config(self): 
     config = {} 
     base_config = super(GradientReversal, self).get_config() 
     return dict(list(base_config.items()) + list(config.items()))