In [ ]:
#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
Note: 이 문서는 텐서플로 커뮤니티에서 번역했습니다. 커뮤니티 번역 활동의 특성상 정확한 번역과 최신 내용을 반영하기 위해 노력함에도 불구하고 공식 영문 문서의 내용과 일치하지 않을 수 있습니다. 이 번역에 개선할 부분이 있다면 tensorflow/docs 깃헙 저장소로 풀 리퀘스트를 보내주시기 바랍니다. 문서 번역이나 리뷰에 참여하려면 docs-ko@tensorflow.org로 메일을 보내주시기 바랍니다.
이전 튜토리얼에서는 텐서(tensor)와 텐서의 연산에 대해서 알아보았습니다. 이번 튜토리얼에서는 머신러닝 모델을 최적화할 수 있는 주요 기술 중 하나인 자동 미분(automatic differentiation)에 대해 알아보겠습니다.
In [ ]:
import tensorflow.compat.v1 as tf
텐서플로는 자동 미분(주어진 입력 변수에 대한 연산의 그래디언트(gradient)를 계산하는 것)을 위한 tf.GradientTape API를 제공합니다. tf.GradientTape는 안에서 실행된 모든 연산을 테이프(tape)에 "기록"합니다. 그리고 후진 방식 자동 미분(reverse mode differentiation)을 사용하여 각각의 기록된 연산과 관련된 그래디언트와 테이프를 사용하여 기록된 연산의 그래디언트를 계산합니다.
예를 들면:
In [ ]:
x = tf.ones((2, 2))
with tf.GradientTape() as t:
t.watch(x)
y = tf.reduce_sum(x)
z = tf.multiply(y, y)
# 입력 텐서 x에 대한 z의 도함수
dz_dx = t.gradient(z, x)
for i in [0, 1]:
for j in [0, 1]:
assert dz_dx[i][j].numpy() == 8.0
또한 tf.GradientTape 컨텍스트 안에서 기록되는 동안 계산된 중간 값에 대한 그래디언트도 구할 수 있습니다.
In [ ]:
x = tf.ones((2, 2))
with tf.GradientTape() as t:
t.watch(x)
y = tf.reduce_sum(x)
z = tf.multiply(y, y)
# 테이프 사용하여 중간 값 y에 대한 도함수를 계산합니다.
dz_dy = t.gradient(z, y)
assert dz_dy.numpy() == 8.0
기본적으로 GradientTape.gradient() 메서드가 호출되면 GradientTape에 포함된 리소스가 해제됩니다. 동일한 연산 대해 여러 그래디언트를 계산하려면, 지속성있는(persistent) 그래디언트 테이프를 생성하면 됩니다. 이 그래디언트 테이프는 gradient() 메서드의 다중 호출을 허용합니다. 테이프 객체가 쓰레기 수집(garbage collection)될때 리소스는 해체됩니다.
예를 들면 다음과 같습니다:
In [ ]:
x = tf.constant(3.0)
with tf.GradientTape(persistent=True) as t:
t.watch(x)
y = x * x
z = y * y
dz_dx = t.gradient(z, x) # 108.0 (4*x^3 at x = 3)
dy_dx = t.gradient(y, x) # 6.0
del t # 테이프에 대한 참조를 삭제합니다.
In [ ]:
def f(x, y):
output = 1.0
for i in range(y):
if i > 1 and i < 5:
output = tf.multiply(output, x)
return output
def grad(x, y):
with tf.GradientTape() as t:
t.watch(x)
out = f(x, y)
return t.gradient(out, x)
x = tf.convert_to_tensor(2.0)
assert grad(x, 6).numpy() == 12.0
assert grad(x, 5).numpy() == 12.0
assert grad(x, 4).numpy() == 4.0
In [ ]:
x = tf.Variable(1.0) # 1.0으로 초기화된 텐서플로 변수를 생성합니다.
with tf.GradientTape() as t:
with tf.GradientTape() as t2:
y = x * x * x
# t 컨텍스트 매니저 안의 그래디언트를 계산합니다.
# 이것은 또한 그래디언트 연산 자체도 미분가능하다는것을 의미합니다.
dy_dx = t2.gradient(y, x)
d2y_dx2 = t.gradient(dy_dx, x)
assert dy_dx.numpy() == 3.0
assert d2y_dx2.numpy() == 6.0