반응형

관련 Tensorflow.org의 [링크] 내용을 정리함.


tf.GradientTape

    자동미분을 위한 연산 기록(Record operations for automatic differentiation)


Aliases

  • Main aliases

    tf.autodiff.GradientTape
  • Compact aliases for migration [참고]

    tf.compact.v1.GradientTape

tf.GradientTape(
  persistent=False, watch_accessed_variables=True
)

Args

  • persistent

      : GradientTape이 영구적으로 생성될지를 제어하는 Boolean값.
      기본값은 False로 이는 많아봐야 한번만 gradient() 메서드를 호출할 수 있음을 의미.

  • watch_accessed_variables

      : tape이 활성화되어 있는 동안, 접근하는 어떠한 (훈련가능한) 변수라도 자동적으로 watch할 것인지를 제어하는 Boolean값.
      기본값은 True로 이는 graident가 훈련 가능한 변수를 읽는 것으로부터 미분된 tape에서 계산된 어떤 결과로부터 요청되어 질 수 있음을 의미.

    만약 context manager내에서 실행되고 적어오 하나의 입력이 'watched'되어지고 있다면, 연산은 기록된다.

    훈련가능한 변수(tf.Variable 또는 tf.compat.v1.get_variable로 생성된, 여기서 trainable=True는 양쪽 경우 모두 기본값이다.)는 자동적으로 watch되어 진다. 텐서는 context manager에서 watch 메서드를 호출하여 수동적으로 watch할 수 있다.

    예를 들어, $y = x \times x$ 함수를 사용하면 $x = 3.0$에서의 기울기는 아래처럼 계산할 수 있다.

Source>>

    x = tf.constant(3.0)
    with tf.GradientTape() as g:
        g.watch(x)
        y = x * x
    dy_dx = g.gradient(y, x) # Will compute to 6.0

    GradientTape은 고차미분계산을 위해 내포(nested)될 수 있다.

Source>>

    x = tf.constant(3.0)
    with tf.GradientTape() as g:
        g.watch(x)
        with tf.GradientTape() as gg:
            gg.watch(x)
            y = x * x
        dy_dx = gg.gradient(y, x)       # Will compute to 6.0
    d2y_dx2 = g.gradient(dy_dx, x)      # Will compute to 2.0

    기본적으로, GradientTape에 의해 잡혀있는(hold) 리소스는 GradientTape.gradient() 메서드가 호출되면 바로 릴리즈된다. 동일 계산에서 여러개의 gradient를 계산하려면, 영구(persistent) gradient tape을 생성한다. 이는 tape 객체가 가비지 처리될 때, 리소스를 해제(release)함으로써 gradient() 메서드 다중 호출을 가능하게 한다.

Source>>

    x = tf.constant(3.0)
    with tf.GradientTape(persistent=True) as g:
        g.watch(x)
        y = x * x
        z = y * y
    dz_dx = g.gradient(z, x)  # 108.0 (4*x^3 at x = 3)
    dy_dx = g.gradient(y, x)  # 6.0
    del g  # Drop the reference to the tape

    기본적으로 GradientTape은 자동적으로 컨텍스트 내부에서 접근한 훈련 가능한 어떤 변수라도 watch한다. 만약 watch되는 변수 전반에 걸쳐 세밀한 제어를 원한다면, 'watch_accessed_variables=False'를 tape 생성자에 전달하여 자동 추적(auto tracting)을 비활성화 할 수 있다.

Source>>

    with tf.GradientTape(watch_accessed_variables=False) as tape:
        tape.watch(variable_a)
        y = variable_a ** 2  # Gradients will be available for `variable_a`.
        z = variable_b ** 3  # No gradients will be available since `variable_b` is
                             # not being watched.

    모델을 사용할 때는 'watch_accessed_variables=False'를 사용할때 변수가 존재해야한다는 것을 명심하자. 그렇지 않으면 어떠한 gradient도 갖지 않는 첫번째 반복을 만드는 것이 쉽다.

Source>>

    a = tf.keras.layers.Dense(32)
    b = tf.keras.layers.Dense(32)

    with tf.GradientTape(watch_accessed_variables=False) as tape:
        tape.watch(a.variables)    # Since `a.build` has not been called at this point
                                   # `a.variables` will return an empty list and the
                                   # tape will not be watching anything.
        result = b(a(inputs))
        tape.gradient(result, a.variables)  # The result of this computation will be
                                            # a list of `None`s since a's variables
                                            # are not being watched.

    오로지 실수 또는 복소수를 갖는 텐서만 미분가능하다는 것을 명심하자.


Methods

gradient


gradient(
   target, sources, output_gradients=None,
   unconnected_gradients=tf.UnconnectedGradients.NONE
)

tape의 컨텍스트에 기록된 연산을 산용하여 기울기를 계산

Args

  • target
      : 미분 가능한 텐서 또는 변수의 list 또는 중첩 구조(nested structure)
  • sources
      : 텐서또는 변수의 list 또는 중첩구조
      target은 source내 요소에 대응하여 미분
  • output_gradients
      : 기울기 list
      기본값 - None
      target의 각 요소에 대해 하나임
  • unconnected_gradients
      : 기본값 - 'none'
      'none' 또는 'zero'를 갖고 타겟과 소스가 연결되지 않을 때 반환되는 값을 대신할 수 있는 값.
      가능한 값과 효과는 'UnconnectedGradients' 참조

Returns

    텐서(또는 IndexedSlices 또는 None)의 list 도는 중첩 구조
    source내 각 요소에 대해 하나임
    반환된 구조는 source의 구조와 동일함

Raises

  • RuntimeError
      : tape의 컨텍스트 내부에서 호출되었거나 영구적이지 않은 tape에서 한번이상 호출되었을 경우 발생
  • ValueError
      : target이 변수이거나 unconnected gradient가 unknown value로 호출되었을 경우 발생

reset


reset()

tape내 저장된 정보 모두를 지운다.

새로운 tape으로 tape context manager를 나가고 다시 들어오는 것과 동일하다.

예를 들면, 아래 두 예제 블록은 동일하다.


with tf.GradientTape() as t:
  loss = loss_fn()
with tf.GradientTape() as t:
  loss += other_loss_fn()
t.gradient(loss, ...)  # Only differentiates other_loss_fn, not loss_fn


# The following is equivalent to the above
with tf.GradientTape() as t:
  loss = loss_fn()
  t.reset()
  loss += other_loss_fn()
t.gradient(loss, ...)  # Only differentiates other_loss_fn, not loss_fn

이 기능은 만약 tape에 대한 context manager를 빠져나가는 것을 원치 않거나, 희망하는 리셋 지점이 제어 흐름 구조내에 있기때문에 빠져나갈 수 없는 경우 유용하다.


with tf.GradientTape() as t:
  loss = ...
  if loss > k:
      t.reset()

watch


watch(
   tensor
)

tape이 텐서를 추적하도록 한다.

Args

  • tensor
      텐서 또는 텐서 list
  • Raises*
  • ValueError
      텐서가 아닌 것이 있는 경우 발생

watched_variables


watched_variables()

생성을 위해 tape에 의해 관찰(watch)되고 있는 변수를 반환한다.


stop_recording


@tf_contextlib.contextmanager
stop_recording()

임시로 tape에서 연산을 기록하는 것을 중단한다.

이 컨텍스트 매니져가 활성화된 동안 실행된 연산은 tape에 기록되지 않는다. 이는 모든 연산을 추적하기 위해 사용되는 메모리를 줄이는데 유용하다.

Yields

    None

Raises

  • RuntimeError
      : tape이 현재 기록중이지 않은 경우 발생

Example


with tf.GradientTape(persistent=True) as t:
  loss = compute_loss(model)
  with t.stop_recording():
      # The gradient computation below is not traced, saving memory.
      grads = t.gradient(loss, model.variables)


batch_jacobian


batch_jacobian(
   target, source, unconnected_gradients=tf.UnconnectedGradients.NONE,
   parallel_iterations=None, experimental_use_pfor=True
)

예제별 야코비안(jacobian)[wiki]을 계산하고 스택으로 만든다.

이 함수는 본질적으로 다음의 효과적인 구현이다.


tf.stack([self.jacobian(y[i], x[i]) for i in range(x.shape[0])])

각 입력값에 관해서 각 출력 값의 기울기(gradient)를 계산하는 GradientTape.jacobian에 비교하면, 이 함수는 target[i,...]이 j != i에 대해 source[j,...]이 독립일 때 유용하다. 이 추정(assumption)은 GradientTape.jacobian에 비해 더 효과적인 계산이 가능하다. 출력 - 중간 활성화 뿐 아니라 -은 더 낮은 차원이고 독립 추정을 기본으로 야코비안 계산의 결과인 불필요한 0의 묶음을 필할 수 있다.

Args

  • target
      : 랭크가 2이상이고 [b, y1, ..., y_n] 모양의 텐서
      target[i, ...]은 오로지 source[i, ...]에 의존.
  • source
      : 랭크가 2이상이고 [b, x1, ..., x_m] 모양의 텐서
  • unconnected_gradients
      : 기본값 - 'none'
      'none' 또는 'zero'를 갖고 타겟과 소스가 연결되지 않을 때 반환되는 값을 대신할 수 있는 값.
      가능한 값과 효과는 'UnconnectedGradients' 참조
  • parallel_iterations
      : 얼마나 많은 반복이 병렬로 처리되어야 할지 결정
      이 값은 전체 메모리 사용을 제어하기 위해 사용될 수 있음.
  • experimental_use_pfor
      : true - 야코비안 계산을 위해 pfor를 사용
      false - while-loop 사용

Returns

    [b, y_1, ...,y_n, x1, ...,x_m] 모양의 텐서 t.
    여기서, t[i, ...]는 source[i, ...]에 관한 target[i, ...]의 야코비안이다.
    즉, 예제별로 야코비안이 쌓인다.(stack)

Raises

  • RuntimeError
      : 즉시 실행(eager execution)이 가능하고 experimental_use_pfor가 가능하지 않은 상태로 영구적이지 않은 tape에서 호출 되는 경우 발생
  • ValueError
      : 야코비안 벡터화의 계산이 실패하거나 target과 source의 첫번째 차원이 일치하지 않는 경우 발생

Example usage


with tf.GradientTape() as g:
  x = tf.constant([[1., 2.], [3., 4.]], dtype=tf.float32)
  g.watch(x)
  y = x * x
batch_jacobian = g.batch_jacobian(y, x)
# batch_jacobian is [[[2,  0], [0,  4]], [[6,  0], [0,  8]]]


jacobian


jacobian(
   target, sources, unconnected_gradients=tf.UnconnectedGradients.NONE,
   parallel_iterations=None, experimental_use_pfor=True
)

tape의 컨텍스트내 기록된 연산을 사용하여 야코비안을 계산

Args

  • target
      : 미분가능한 텐서
  • sources
      : 텐서 또는 변수의 list 또는 중첩 구조
      target은 source의 요소에 대응하여 미분
  • unconnected_gradients
      : 기본값 - 'none'
      'none' 또는 'zero'를 갖고 타겟과 소스가 연결되지 않을 때 반환되는 값을 대신할 수 있는 값.
      가능한 값과 효과는 'UnconnectedGradients' 참조
  • parallel_iterations
      : 얼마나 많은 반복이 병렬로 처리되어야 할지 결정
      이 값은 전체 메모리 사용을 제어하기 위해 사용될 수 있음.
  • experimental_use_pfor
      : true - 야코비안 계산을 벡터화
      false - 순차적(sequential) while-loop
      벡터화는 때때로 실패하거나 메모리 사용 초과로 이어질 수 있음. 이 옵션은 그런 경우 벡터화를 비활성화하기 위해 사용할 수 있음

Returns

    텐서(또는 None)의 list 또는 중첩 구조

    source내 각 요소에 대해 하나임

    반환 구조는 source의 구조와 동일

    만약 어떤 기울기가 sparse(IndexedSlices)라면, 야코비안 함수는 이를 dense로 만들고 대신 텐서를 반환한다.

Raises

  • RuntimeError
      : 즉시 실행(eager execution)이 가능하고 experimental_use_pfor가 가능하지 않은 상태로 영구적이지 않은 tape에서 호출 되는 경우 발생
  • ValueError
      야코비안 계산의 벡터화가 실패하면 발생

Example usage


with tf.GradientTape() as g:
  x  = tf.constant([1.0, 2.0])
  g.watch(x)
  y = x * x
jacobian = g.jacobian(y, x)
# jacobian value is [[2., 0.], [0., 4.]]


__enter__


__enter__()

tape에 연산이 기록되는 컨텍스트 내부로 들어간다.


__exit__


__exit__(
   typ, value, traceback
)

기록중인 컨텍스트를 빠져나가고 더이상 연산이 추적되지 않는다.

반응형

+ Recent posts