변수 소개

TensorFlow.org에서 보기 Google Colab에서 실행 GitHub에서 소스 보기 노트북 다운로드

TensorFlow 변수는 프로그램이 조작하는 공유 영구 상태를 나타내는 권장 방법입니다. 이 가이드는 TensorFlow에서 tf.Variable 인스턴스를 작성, 업데이트 및 관리하는 방법을 설명합니다.

변수는 tf.Variable 클래스를 통해 생성 및 추적됩니다. tf.Variable은 ops를 실행하여 값을 변경할 수 있는 텐서를 나타냅니다. 특정 ops를 사용하면 이 텐서의 값을 읽고 수정할 수 있습니다. tf.keras와 같은 상위 수준의 라이브러리는 tf.Variable을 사용하여 모델 매개변수를 저장합니다.

설정

변수 배치에 대해 설명하는 노트북입니다. 변수가 어떤 기기에 배치되었는지 보려면 이 줄의 주석을 해제하세요.

import tensorflow as tf

# Uncomment to see where your variables get placed (see below)
# tf.debugging.set_log_device_placement(True)
2022-12-14 21:07:24.023879: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory
2022-12-14 21:07:24.023977: W tensorflow/compiler/xla/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory
2022-12-14 21:07:24.023986: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.

변수 만들기

변수를 작성하려면 초기값을 제공합니다. tf.Variable은 초기화 값과 같은 dtype을 갖습니다.

my_tensor = tf.constant([[1.0, 2.0], [3.0, 4.0]])
my_variable = tf.Variable(my_tensor)

# Variables can be all kinds of types, just like tensors
bool_variable = tf.Variable([False, False, False, True])
complex_variable = tf.Variable([5 + 4j, 6 + 1j])

변수는 텐서처럼 보이고 작동하며, 실제로 tf.Tensor에서 지원되는 데이터 구조입니다. 텐서와 마찬가지로, dtype과 형상을 가지며 NumPy로 내보낼 수 있습니다.

print("Shape: ", my_variable.shape)
print("DType: ", my_variable.dtype)
print("As NumPy: ", my_variable.numpy())
Shape:  (2, 2)
DType:  <dtype: 'float32'>
As NumPy:  [[1. 2.]
 [3. 4.]]

변수를 재구성할 수는 없지만, 대부분의 텐서 연산은 예상대로 변수에 대해 작동합니다.

print("A variable:", my_variable)
print("\nViewed as a tensor:", tf.convert_to_tensor(my_variable))
print("\nIndex of highest value:", tf.math.argmax(my_variable))

# This creates a new tensor; it does not reshape the variable.
print("\nCopying and reshaping: ", tf.reshape(my_variable, [1,4]))
A variable: <tf.Variable 'Variable:0' shape=(2, 2) dtype=float32, numpy=
array([[1., 2.],
       [3., 4.]], dtype=float32)>

Viewed as a tensor: tf.Tensor(
[[1. 2.]
 [3. 4.]], shape=(2, 2), dtype=float32)

Index of highest value: tf.Tensor([1 1], shape=(2,), dtype=int64)

Copying and reshaping:  tf.Tensor([[1. 2. 3. 4.]], shape=(1, 4), dtype=float32)

위에서 언급했듯이, 변수는 텐서에 의해 지원됩니다. tf.Variable.assign을 사용하여 텐서를 재할당할 수 있습니다. assign을 호출해도 (일반적으로) 새로운 텐서를 할당하지 않고, 대신 기존 텐서의 메모리가 재사용됩니다.

a = tf.Variable([2.0, 3.0])
# This will keep the same dtype, float32
a.assign([1, 2]) 
# Not allowed as it resizes the variable: 
try:
  a.assign([1.0, 2.0, 3.0])
except Exception as e:
  print(f"{type(e).__name__}: {e}")
ValueError: Cannot assign value to variable ' Variable:0': Shape mismatch.The variable shape (2,), and the assigned value shape (3,) are incompatible.

연산에서 텐서와 같은 변수를 사용하는 경우, 일반적으로 지원 텐서에서 작동합니다.

기존 변수에서 새 변수를 만들면 지원 텐서가 복제됩니다. 두 변수는 같은메모리를 공유하지 않습니다.

a = tf.Variable([2.0, 3.0])
# Create b based on the value of a
b = tf.Variable(a)
a.assign([5, 6])

# a and b are different
print(a.numpy())
print(b.numpy())

# There are other versions of assign
print(a.assign_add([2,3]).numpy())  # [7. 9.]
print(a.assign_sub([7,9]).numpy())  # [0. 0.]
[5. 6.]
[2. 3.]
[7. 9.]
[0. 0.]

수명 주기, 이름 지정 및 감시

파이썬 기반 TensorFlow에서 tf.Variable 인스턴스는 다른 Python 객체와 같은 수명 주기를 갖습니다. 변수에 대한 참조가 없으면 자동으로 할당이 해제됩니다.

변수를 추적하고 디버그하는 데 도움이 되는 변수의 이름을 지정할 수도 있습니다. 두 변수에 같은 이름을 지정할 수 있습니다.

# Create a and b; they will have the same name but will be backed by
# different tensors.
a = tf.Variable(my_tensor, name="Mark")
# A new variable with the same name, but different value
# Note that the scalar add is broadcast
b = tf.Variable(my_tensor + 1, name="Mark")

# These are elementwise-unequal, despite having the same name
print(a == b)
tf.Tensor(
[[False False]
 [False False]], shape=(2, 2), dtype=bool)

모델을 저장하고 로드할 때 변수 이름이 유지됩니다. 기본적으로 모델의 변수는 고유한 변수 이름이 자동으로 지정되므로 원치 않는 한 직접 할당할 필요가 없습니다.

변수는 구별을 위해 중요하지만, 일부 변수는 구별할 필요가 없습니다. 생성 시 trainable을 false로 설정하여 변수의 그래디언트를 끌 수 있습니다. 그래디언트가 필요하지 않은 변수의 예는 훈련 단계 카운터입니다.

step_counter = tf.Variable(1, trainable=False)

변수 및 텐서 배치하기

더 나은 성능을 위해 TensorFlow는 dtype과 호환되는 가장 빠른 기기에 텐서 및 변수를 배치하려고 시도합니다. 이는 대부분의 변수가 GPU(사용 가능한 경우)에 배치됨을 의미합니다.

그러나 우리는 이것을 재정의할 수 있습니다. 이 코드에서, GPU가 사용가능함에서도 우리는 부동 텐서와 변수를 CPU에 배치할 수 있습니다. 기기배치에 로그인을 함으로써 ( Setup 참조), 변수가 어디에 위치해있는지 확인할 수 있습니다.

참고: 수동 배치도 가능하지만, 분배 전략을 사용하여 더 편리하고 확장 가능하게 계산을 최적화 할 수 있습니다.

GPU가 있거나 없는 서로 다른 백엔드에서 이 노트북을 실행하면 서로 다른 로깅이 표시됩니다. 세션 시작 시 기기 배치 로깅을 켜야 합니다.

with tf.device('CPU:0'):

  # Create some tensors
  a = tf.Variable([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
  b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
  c = tf.matmul(a, b)

print(c)
tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32)

한 기기에서 변수 또는 텐서의 위치를 설정하고 다른 기기에서 계산을 수행할 수 있습니다. 이 경우, 기기 간에 데이터를 복사해야 하므로 지연이 발생합니다.

GPU 작업자가 여러 개이지만 변수의 사본이 하나만 필요한 경우에 수행할 수 있습니다.

with tf.device('CPU:0'):
  a = tf.Variable([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
  b = tf.Variable([[1.0, 2.0, 3.0]])

with tf.device('GPU:0'):
  # Element-wise multiply
  k = a * b

print(k)
tf.Tensor(
[[ 1.  4.  9.]
 [ 4. 10. 18.]], shape=(2, 3), dtype=float32)

주의: tf.config.set_soft_device_placement 이 기본적으로 항상 켜져있기 때문에, GPU가 없는 기기에서 이 코드를 실행하더라도 코드는 계속 실행됩니다. 곱셈 단계는 CPU에서 실행됩니다.

분산 훈련에 대한 자세한 내용은 가이드를 참조하세요.

다음 단계

변수들이 일반적으로 사용되는 방식을 이해하려면, automatic differentiation에서 우리의 가이드를 참조하세요.