텐서와 연산

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

이 노트북은 텐서플로를 사용하기 위한 입문 튜토리얼입니다. 다음 내용을 다룹니다 :

  • 필요한 패키지를 가져옵니다.
  • 텐서를 만들고 사용합니다.
  • GPU 가속을 사용합니다.
  • tf.data.Dataset로 데이터 파이프라인을 구축합니다.

TensorFlow 가져오기

시작하려면 tensorflow 모듈을 가져옵니다. TensorFlow 2부터 즉시 실행이 기본적으로 켜져 있습니다. 즉시 실행은 TensorFlow에 대한 보다 대화식의 프론트엔드를 가능하게 하며 나중에 더 자세히 살펴볼 것입니다.

import tensorflow as tf
2022-12-14 22:24:03.262589: 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 22:24:03.262699: 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 22:24:03.262710: 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.

텐서

텐서는 다차원 배열입니다. NumPy ndarray 객체와 유사하게 tf.Tensor 객체에는 데이터 유형과 형상이 있습니다. 또한 tf.Tensor는 가속기 메모리(예: GPU)에 상주할 수 있습니다. TensorFlow는 tf.Tensor를 소비하고 생성하는 풍부한 연산 라이브러리를 제공합니다(tf.math.add, tf.linalg.matmul, tf.linalg.inv 등). 이러한 연산은 기본 Python 유형을 자동으로 변환합니다. 예를 들면 다음과 같습니다.

print(tf.math.add(1, 2))
print(tf.math.add([1, 2], [3, 4]))
print(tf.math.square(5))
print(tf.math.reduce_sum([1, 2, 3]))

# Operator overloading is also supported
print(tf.math.square(2) + tf.math.square(3))
tf.Tensor(3, shape=(), dtype=int32)
tf.Tensor([4 6], shape=(2,), dtype=int32)
tf.Tensor(25, shape=(), dtype=int32)
tf.Tensor(6, shape=(), dtype=int32)
tf.Tensor(13, shape=(), dtype=int32)

각각의 tf.Tensor는 크기와 데이터 타입을 가지고 있습니다.

x = tf.linalg.matmul([[1]], [[2, 3]])
print(x)
print(x.shape)
print(x.dtype)
tf.Tensor([[2 3]], shape=(1, 2), dtype=int32)
(1, 2)
<dtype: 'int32'>

NumPy 배열과 tf.Tensor의 가장 확연한 차이는 다음과 같습니다:

  1. 텐서는 가속기 메모리(GPU, TPU와 같은)에서 사용할 수 있습니다.
  2. 텐서는 불변성(immutable)을 가집니다.

NumPy 호환성

TensorFlow tf.Tensor와 NumPy ndarray 사이의 변환은 간단합니다.

  • 텐서플로 연산은 자동으로 NumPy 배열을 텐서로 변환합니다.
  • NumPy 연산은 자동으로 텐서를 NumPy 배열로 변환합니다.

텐서는 .numpy() 메서드(method)를 호출하여 NumPy 배열로 변환할 수 있습니다. 가능한 경우, tf.Tensor와 배열은 메모리 표현을 공유하기 때문에 이러한 변환은 일반적으로 간단(저렴)합니다. 그러나 tf.Tensor는 GPU 메모리에 저장될 수 있고, NumPy 배열은 항상 호스트 메모리에 저장되므로, 이러한 변환이 항상 가능한 것은 아닙니다. 따라서 GPU에서 호스트 메모리로 복사가 필요합니다.

import numpy as np

ndarray = np.ones([3, 3])

print("TensorFlow operations convert numpy arrays to Tensors automatically")
tensor = tf.math.multiply(ndarray, 42)
print(tensor)


print("And NumPy operations convert Tensors to NumPy arrays automatically")
print(np.add(tensor, 1))

print("The .numpy() method explicitly converts a Tensor to a numpy array")
print(tensor.numpy())
TensorFlow operations convert numpy arrays to Tensors automatically
tf.Tensor(
[[42. 42. 42.]
 [42. 42. 42.]
 [42. 42. 42.]], shape=(3, 3), dtype=float64)
And NumPy operations convert Tensors to NumPy arrays automatically
[[43. 43. 43.]
 [43. 43. 43.]
 [43. 43. 43.]]
The .numpy() method explicitly converts a Tensor to a numpy array
[[42. 42. 42.]
 [42. 42. 42.]
 [42. 42. 42.]]

GPU 가속

대부분의 TensorFlow 연산은 GPU를 사용하여 가속화됩니다. 어떠한 코드를 명시하지 않아도, TensorFlow는 연산을 위해 CPU 또는 GPU를 사용할 것인지를 자동으로 결정합니다. 필요 시 텐서를 CPU와 GPU 메모리 사이에서 복사합니다. 연산에 의해 생성된 텐서는 전형적으로 연산이 실행된 장치의 메모리에 의해 실행됩니다. 예를 들면 다음과 같습니다.

x = tf.random.uniform([3, 3])

print("Is there a GPU available: "),
print(tf.config.list_physical_devices("GPU"))

print("Is the Tensor on GPU #0:  "),
print(x.device.endswith('GPU:0'))
Is there a GPU available: 
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU'), PhysicalDevice(name='/physical_device:GPU:1', device_type='GPU'), PhysicalDevice(name='/physical_device:GPU:2', device_type='GPU'), PhysicalDevice(name='/physical_device:GPU:3', device_type='GPU')]
Is the Tensor on GPU #0:  
True

장치 이름

Tensor.device는 텐서를 구성하고 있는 호스트 장치의 풀네임을 제공합니다. 이러한 이름은 프로그램이 실행중인 호스트의 네트워크 주소 및 해당 호스트 내의 장치와 같은 많은 세부 정보를 인코딩하며, 이것은 텐서플로 프로그램의 분산 실행에 필요합니다. 텐서가 호스트의 N번째 GPU에 놓여지면 문자열은 GPU:<N>으로 끝납니다.

명시적 장치 배치

TensorFlow에서 배치는 개별 연산이 실행을 위해 장치에 할당(배치)되는 방식을 나타냅니다. 언급했듯이 명시적인 지침이 제공되지 않으면 TensorFlow는 연산을 실행할 장치를 자동으로 결정하고 필요한 경우 해당 장치에 텐서를 복사합니다.

그러나 TensorFlow 연산은 tf.device 컨텍스트 관리자를 사용하여 특정 장치에 명시적으로 배치할 수 있습니다. 예를 들면 다음과 같습니다.

import time

def time_matmul(x):
  start = time.time()
  for loop in range(10):
    tf.linalg.matmul(x, x)

  result = time.time()-start

  print("10 loops: {:0.2f}ms".format(1000*result))

# Force execution on CPU
print("On CPU:")
with tf.device("CPU:0"):
  x = tf.random.uniform([1000, 1000])
  assert x.device.endswith("CPU:0")
  time_matmul(x)

# Force execution on GPU #0 if available
if tf.config.list_physical_devices("GPU"):
  print("On GPU:")
  with tf.device("GPU:0"): # Or GPU:1 for the 2nd GPU, GPU:2 for the 3rd etc.
    x = tf.random.uniform([1000, 1000])
    assert x.device.endswith("GPU:0")
    time_matmul(x)
On CPU:
10 loops: 48.46ms
On GPU:
10 loops: 329.81ms

데이터세트

이 섹션에서는 tf.data.Dataset API를 사용하여 모델에 데이터를 공급하기 위한 파이프라인을 구축합니다. tf.data.Dataset는 모델의 훈련 또는 평가 루프에 데이터를 제공할 단순하고 재사용 가능한 부분으로부터 성능이 뛰어나고 복잡한 입력 파이프라인을 구축하는 데 사용됩니다. 자세한 내용은 tf.data: TensorFlow 입력 파이프라인 빌드 가이드를 참조하세요.

소스 데이터세트 생성하기

tf.data.Dataset.from_tensors, tf.data.Dataset.from_tensor_slices 등의 팩토리 함수 중 하나를 사용하거나 tf.data.TextLineDataset 또는 tf.data.TFRecordDataset와 같은 파일에서 읽는 객체를 사용하여 소스 데이터세트를 생성합니다. 자세한 내용은 tf.data: TensorFlow 입력 파이프라인 구축 가이드의 입력 데이터 읽기 섹션을 참조하세요.

ds_tensors = tf.data.Dataset.from_tensor_slices([1, 2, 3, 4, 5, 6])

# Create a CSV file
import tempfile
_, filename = tempfile.mkstemp()

with open(filename, 'w') as f:
  f.write("""Line 1
Line 2
Line 3
  """)

ds_file = tf.data.TextLineDataset(filename)

변환 적용

tf.data.Dataset.map, tf.data.Dataset.batchtf.data.Dataset.shuffle과 같은 변환 함수를 사용하여 데이터세트 레코드에 변환을 적용합니다.

ds_tensors = ds_tensors.map(tf.math.square).shuffle(2).batch(2)

ds_file = ds_file.batch(2)

반복

tf.data.Dataset는 레코드 순회를 지원하는 반복 가능한 객체입니다.

print('Elements of ds_tensors:')
for x in ds_tensors:
  print(x)

print('\nElements in ds_file:')
for x in ds_file:
  print(x)
Elements of ds_tensors:
tf.Tensor([4 1], shape=(2,), dtype=int32)
tf.Tensor([ 9 16], shape=(2,), dtype=int32)
tf.Tensor([36 25], shape=(2,), dtype=int32)

Elements in ds_file:
tf.Tensor([b'Line 1' b'Line 2'], shape=(2,), dtype=string)
tf.Tensor([b'Line 3' b'  '], shape=(2,), dtype=string)