tf.gradient와 tf.train.Optimizer.compute_gradient의 TensorFlow 공식 문서 설명을 번역하고, Stackoverflow를 참고하여 이들의 차이점을 정리합니다.
tf.gradient
xs
에 관한 ys
의 symbolic derivative를 계산합니다. 텐서 리스트를 반환(return)하며, 각 텐서는 sum(dy/dx)
의 계산 결과를 의미합니다.
tf.gradients(
ys, xs, grad_ys=None, name='gradients', colocate_gradients_with_ops=False,
gate_gradients=False, aggregation_method=None, stop_gradients=None,
unconnected_gradients=tf.UnconnectedGradients.NONE
)
ys
와 xs
는 텐서 혹은 텐서 리스트입니다. grad_ys
는 텐서 리스트 타입이며 ys
의 초기 gradient 값을 가집니다. 그러므로 ys
와 같은 길이 값을 갖습니다.
stop_gradients
는 xs
에 대해 Constant로 취급되어야 할 텐서 혹은 텐서 리스트입니다. 이 텐서 값들은 학습 과정 중에 역전파되지 않습니다.
a = tf.constant(0.)
b = 2 * a
g = tf.gradients(a + b, [a, b], stop_gradients=[a, b])
위의 예시에서는 g
는 [1.0, 1.0]의 계산 결과를 갖습니다. tf.gradients(a + b, [a, b])
라고 코드를 바꾼다면 [3.0, 1.0]의 계산 결과를 갖게 됩니다. 아래의 예시는 위의 예시와 동일한 의미를 가집니다.
a = tf.stop_gradient(tf.constant(0.))
b = tf.stop_gradient(2 * a)
g = tf.gradients(a + b, [a, b])
tf.stop_gradient
는 그래프를 빌드하는 과정에 있어서 사용하는 대신, stop_gradients
인자는 이미 그래프가 빌드된 이후에도 gradient 계산을 멈추는 방법을 제공합니다.
tf.train.Optimizer.compute_gradients
var_list
에 관한 loss
의 gradient를 계산합니다.
compute_gradients(
loss, var_list=None, gate_gradients=GATE_OP, aggregation_method=None,
colocate_gradients_with_ops=False, grad_loss=None
)
이 함수는 minimize()
의 첫 번째 파트로 사용되기도 합니다. var_list
내 variable에 대한 gradient를 (gradient, variable) 페어로 이루어진 리스트에 담아 반환(return)합니다.
차이점
tf.train.Optimizer.compute_gradients
(이하 compute_gradients
)는 tf.gradients
를 래핑합니다. 따라서 추가적인 asserts를 가지고 있습니다. compute_gradients
는 실제 코드상에서 tf.gradients
를 gradients.gradients
라는 이름으로 호출하여 사용하고, 추적 또는 디버깅과 같은 보조 목적으로의 서브클래스로 확장 가능한 기능을 허용합니다.
반환하는 값에 대해서 비교를 하자면 compute_gradients
는 (gradient, variable) 페어로 이루어진 리스트를 반환합니다. 이 때에 variable은 항상 존재하지만 gradient는 존재하지 않을 수 있습니다. 만약 variable에 대한 gradient 변화를 적용하려 한다면 compute_gradients
를 통해 반환된 리스트를 그대로 가져다가 가중치 업데이트에 사용하면 됩니다.
하지만 tf.gradients
는 오직 각 variable에 대한 sum(dy/dx)
계산 결과만을 반환하기 때문에 variable 리스트가 추가적으로 제공되어야 가중치 업데이트에 사용할 수 있습니다.
두 가지 방법은 아래 예시처럼 사용이 가능합니다.
### Approach 1 ###
variable_list = desired_list_of_variables
gradients = optimizer.compute_gradients(loss,var_list=variable_list)
optimizer.apply_gradients(gradients)
### Approach 2 ###
variable_list = desired_list_of_variables
gradients = tf.gradients(loss, var_list=variable_list)
optimizer.apply_gradients(zip(gradients, variable_list))