Gradient Reverse Layer

April 20, 2019    Domain Adaptation

GRL

  • 일반적으로 SGD는 $-\alpha \times grad$ 로 파라미터가 업데이트 된다. 그런데 domain adapation에 특정 부분의 layer가 받는 gradient의 방향을 반대로 ($+ \alpha \times grad$) 바꿔주고 싶을 때 GRL이 사용된다.


코드

import tensorflow as tf
import numpy as np
from tensorflow.python.framework import ops
class FlipGradientBuilder(object):
    def __init__(self):
        self.num_calls = 0

    def __call__(self, x, lr=1.0):
        
        grad_name = "FlipGradient%d" % self.num_calls
        
        @ops.RegisterGradient(grad_name)
        def _flip_gradients(op, grad):
            return [tf.negative(grad) * lr]
        
        g = tf.get_default_graph()
        with g.gradient_override_map({"Identity": grad_name}):
            y = tf.identity(x) # copy for assign op
            
        self.num_calls += 1
        return y


예시

_flip_gradient = FlipGradientBuilder()
_flip_gradient.num_calls
0


_X = tf.constant(np.random.random([2,3]))

# as a feature
_W1 = tf.constant(np.random.random([3,2]))
_feature = tf.matmul(_X,_W1)


_W2 = tf.constant(np.random.random([2,5]))
_output = tf.matmul(_feature,_W2)


tf.InteractiveSession()
<tensorflow.python.client.session.InteractiveSession at 0x7f63f3675940>


  • 아무런 변화를 시키지않은 layer의 gradient 출력
_feature
<tf.Tensor 'MatMul:0' shape=(2, 2) dtype=float64>
tf.gradients(_feature, _W1)[0].eval()
array([[1.44770713, 1.44770713],
       [0.30008724, 0.30008724],
       [0.57832454, 0.57832454]])


  • reverse gradient를 적용한 layer의 gradient 출력
grad_flip_feature = _flip_gradient(_feature, 1.0)
grad_flip_feature
<tf.Tensor 'Identity:0' shape=(2, 2) dtype=float64>
tf.gradients(grad_flip_feature, _W1)[0].eval()
array([[-1.44770713, -1.44770713],
       [-0.30008724, -0.30008724],
       [-0.57832454, -0.57832454]])


_flip_gradient.num_calls
1


Reference

https://github.com/TGISer/tf-dann


DSBA