텐서 소개

TensorFlow.org에서 보기 Google Colab에서 실행 GitHub에서소스 보기 노트북 다운로드
import tensorflow as tf
import numpy as np
2022-12-14 20:10:18.874280: 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 20:10:18.874386: 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 20:10:18.874396: 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.

텐서는 일관된 유형(dtype이라고 불림)을 가진 다차원 배열입니다. 지원되는 모든 dtypestf.dtypes.DType에서 볼 수 있습니다.

NumPy에 익숙하다면 텐서가 (일종의) np.arrays와 유사하다는 것을 참고해 주시기 바랍니다.

모든 텐서는 Python 숫자 및 문자열과 같이 변경할 수 없습니다. 텐서의 내용을 업데이트할 수 없으며 새로운 텐서를 만들 수만 있습니다.

기초

먼저, 기본 텐서를 생성해 봅니다.

다음은 "스칼라" 또는 "순위-0" 텐서입니다. 스칼라는 단일 값을 포함하며 "축"은 없습니다.

# This will be an int32 tensor by default; see "dtypes" below.
rank_0_tensor = tf.constant(4)
print(rank_0_tensor)
tf.Tensor(4, shape=(), dtype=int32)

"벡터" 또는 "순위-1" 텐서는 값의 목록과 같습니다. 벡터에는 하나의 축이 있습니다.

# Let's make this a float tensor.
rank_1_tensor = tf.constant([2.0, 3.0, 4.0])
print(rank_1_tensor)
tf.Tensor([2. 3. 4.], shape=(3,), dtype=float32)

"행렬" 또는 "순위-2" 텐서에는 두 개의 축이 있습니다.

# If you want to be specific, you can set the dtype (see below) at creation time
rank_2_tensor = tf.constant([[1, 2],
                             [3, 4],
                             [5, 6]], dtype=tf.float16)
print(rank_2_tensor)
tf.Tensor(
[[1. 2.]
 [3. 4.]
 [5. 6.]], shape=(3, 2), dtype=float16)
스칼라, 형상: [] 벡터, 형상: [3] 행렬, 형상: [3, 2]
A scalar, the number 4 The line with 3 sections, each one containing a number. A 3x2 grid, with each cell containing a number.

텐서에는 더 많은 축이 있을 수 있습니다. 여기에는 세 개의 축이 있는 텐서가 사용됩니다.

# There can be an arbitrary number of
# axes (sometimes called "dimensions")
rank_3_tensor = tf.constant([
  [[0, 1, 2, 3, 4],
   [5, 6, 7, 8, 9]],
  [[10, 11, 12, 13, 14],
   [15, 16, 17, 18, 19]],
  [[20, 21, 22, 23, 24],
   [25, 26, 27, 28, 29]],])

print(rank_3_tensor)
tf.Tensor(
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]]

 [[10 11 12 13 14]
  [15 16 17 18 19]]

 [[20 21 22 23 24]
  [25 26 27 28 29]]], shape=(3, 2, 5), dtype=int32)

축이 두 개 이상인 텐서를 시각화하는 방법에는 여러 가지가 있습니다.

3축 텐서, 형상: [3, 2, 5]

np.array 또는 tensor.numpy 메서드를 사용하여 텐서를 NumPy 배열로 변환할 수 있습니다.

np.array(rank_2_tensor)
array([[1., 2.],
       [3., 4.],
       [5., 6.]], dtype=float16)
rank_2_tensor.numpy()
array([[1., 2.],
       [3., 4.],
       [5., 6.]], dtype=float16)

텐서에는 종종 float와 int가 포함되지만, 다음과 같은 다른 유형도 있습니다.

  • 복소수
  • 문자열

기본 tf.Tensor 클래스에서는 텐서가 "직사각형"이어야 합니다. 즉, 각 축을 따라 모든 요소의 크기가 같습니다. 그러나 다양한 형상을 처리할 수 있는 특수 유형의 텐서가 있습니다.

덧셈, 요소별 곱셈 및 행렬 곱셈을 포함하여 텐서에 대한 기본 산술을 수행할 수 있습니다.

a = tf.constant([[1, 2],
                 [3, 4]])
b = tf.constant([[1, 1],
                 [1, 1]]) # Could have also said `tf.ones([2,2])`

print(tf.add(a, b), "\n")
print(tf.multiply(a, b), "\n")
print(tf.matmul(a, b), "\n")
tf.Tensor(
[[2 3]
 [4 5]], shape=(2, 2), dtype=int32) 

tf.Tensor(
[[1 2]
 [3 4]], shape=(2, 2), dtype=int32) 

tf.Tensor(
[[3 3]
 [7 7]], shape=(2, 2), dtype=int32)
print(a + b, "\n") # element-wise addition
print(a * b, "\n") # element-wise multiplication
print(a @ b, "\n") # matrix multiplication
tf.Tensor(
[[2 3]
 [4 5]], shape=(2, 2), dtype=int32) 

tf.Tensor(
[[1 2]
 [3 4]], shape=(2, 2), dtype=int32) 

tf.Tensor(
[[3 3]
 [7 7]], shape=(2, 2), dtype=int32)

텐서는 모든 종류의 연산(ops)에 사용합니다.

c = tf.constant([[4.0, 5.0], [10.0, 1.0]])

# Find the largest value
print(tf.reduce_max(c))
# Find the index of the largest value
print(tf.math.argmax(c))
# Compute the softmax
print(tf.nn.softmax(c))
tf.Tensor(10.0, shape=(), dtype=float32)
tf.Tensor([1 0], shape=(2,), dtype=int64)
tf.Tensor(
[[2.6894143e-01 7.3105854e-01]
 [9.9987662e-01 1.2339458e-04]], shape=(2, 2), dtype=float32)

참고: 일반적으로 TensorFlow 함수가 Tensor를 입력으로 받을 것을 예상하는 경우 이 함수는 tf.convert_to_tensor를 사용하여 Tensor로 변환할 수 있는 모든 항목을 허용하게 됩니다.

tf.convert_to_tensor([1,2,3])
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([1, 2, 3], dtype=int32)>
tf.reduce_max([1,2,3])
<tf.Tensor: shape=(), dtype=int32, numpy=3>
tf.reduce_max(np.array([1,2,3]))
<tf.Tensor: shape=(), dtype=int64, numpy=3>

형상 정보

텐서는 형상이 있습니다. 사용되는 일부 용어는 다음과 같습니다.

  • 형상: 텐서의 각 차원의 길이(요소의 수)
  • 순위: 텐서 축의 수입니다. 스칼라는 순위가 0이고 벡터의 순위는 1이며 행렬의 순위는 2입니다.
  • 또는 차원: 텐서의 특정 차원
  • 크기: 텐서의 총 항목 수, 형상 벡터 요소의 곱

참고: "2차원 텐서"에 대한 참조가 있을 수 있지만, 순위-2 텐서는 일반적으로 2D 공간을 설명하지 않습니다.

텐서 및 tf.TensorShape 객체에는 다음에 액세스하기 위한 편리한 속성이 있습니다.

rank_4_tensor = tf.zeros([3, 2, 4, 5])
순위-4 텐서, 형상: [3, 2, 4, 5]
A tensor shape is like a vector. A 4-axis tensor
print("Type of every element:", rank_4_tensor.dtype)
print("Number of axes:", rank_4_tensor.ndim)
print("Shape of tensor:", rank_4_tensor.shape)
print("Elements along axis 0 of tensor:", rank_4_tensor.shape[0])
print("Elements along the last axis of tensor:", rank_4_tensor.shape[-1])
print("Total number of elements (3*2*4*5): ", tf.size(rank_4_tensor).numpy())
Type of every element: <dtype: 'float32'>
Number of axes: 4
Shape of tensor: (3, 2, 4, 5)
Elements along axis 0 of tensor: 3
Elements along the last axis of tensor: 5
Total number of elements (3*2*4*5):  120

하지만 Tensor.ndimTensor.shape 속성은 Tensor 객체를 반환하지 않음에 유의해야 합니다. Tensor가 필요한 경우 tf.rank 또는 tf.shape 함수를 사용해야 합니다. 이 둘의 차이는 미묘하지만 그래프를 작성할 때 중요할 수 있습니다(나중에).

tf.rank(rank_4_tensor)
<tf.Tensor: shape=(), dtype=int32, numpy=4>
tf.shape(rank_4_tensor)
<tf.Tensor: shape=(4,), dtype=int32, numpy=array([3, 2, 4, 5], dtype=int32)>

축은 종종 인덱스로 참조하지만, 항상 각 축의 의미를 추적해야 합니다. 축이 전역에서 로컬로 정렬되는 경우가 종종 있습니다. 배치 축이 먼저 오고 그 다음에 공간 차원과 각 위치의 특성이 마지막에 옵니다. 이러한 방식으로 특성 벡터는 연속적인 메모리 영역입니다.

일반적인 축 순서
Keep track of what each axis is. A 4-axis tensor might be: Batch, Width, Height, Features

인덱싱

단일 축 인덱싱

TensorFlow는 Python의 목록 또는 문자열 인덱싱과 마찬가지로 표준 Python 인덱싱 규칙과 NumPy 인덱싱의 기본 규칙을 따릅니다.

  • 인덱스는 0에서 시작합니다.
  • 음수 인덱스는 끝에서부터 거꾸로 계산합니다.
  • 콜론, :start:stop:step 슬라이스에 사용됩니다.
rank_1_tensor = tf.constant([0, 1, 1, 2, 3, 5, 8, 13, 21, 34])
print(rank_1_tensor.numpy())
[ 0  1  1  2  3  5  8 13 21 34]

스칼라를 사용하여 인덱싱하면 축이 제거됩니다.

print("First:", rank_1_tensor[0].numpy())
print("Second:", rank_1_tensor[1].numpy())
print("Last:", rank_1_tensor[-1].numpy())
First: 0
Second: 1
Last: 34

: 슬라이스를 사용하여 인덱싱하면 축이 유지됩니다.

print("Everything:", rank_1_tensor[:].numpy())
print("Before 4:", rank_1_tensor[:4].numpy())
print("From 4 to the end:", rank_1_tensor[4:].numpy())
print("From 2, before 7:", rank_1_tensor[2:7].numpy())
print("Every other item:", rank_1_tensor[::2].numpy())
print("Reversed:", rank_1_tensor[::-1].numpy())
Everything: [ 0  1  1  2  3  5  8 13 21 34]
Before 4: [0 1 1 2]
From 4 to the end: [ 3  5  8 13 21 34]
From 2, before 7: [1 2 3 5 8]
Every other item: [ 0  1  3  8 21]
Reversed: [34 21 13  8  5  3  2  1  1  0]

다축 인덱싱

더 높은 순위의 텐서는 여러 인덱스를 전달하여 인덱싱됩니다.

단일 축의 경우에서와 정확히 같은 규칙이 각 축에 독립적으로 적용됩니다.

print(rank_2_tensor.numpy())
[[1. 2.]
 [3. 4.]
 [5. 6.]]

각 인덱스에 정수를 전달하면 결과는 스칼라입니다.

# Pull out a single value from a 2-rank tensor
print(rank_2_tensor[1, 1].numpy())
4.0

정수와 슬라이스의 조합을 사용하여 인덱싱할 수 있습니다.

# Get row and column tensors
print("Second row:", rank_2_tensor[1, :].numpy())
print("Second column:", rank_2_tensor[:, 1].numpy())
print("Last row:", rank_2_tensor[-1, :].numpy())
print("First item in last column:", rank_2_tensor[0, -1].numpy())
print("Skip the first row:")
print(rank_2_tensor[1:, :].numpy(), "\n")
Second row: [3. 4.]
Second column: [2. 4. 6.]
Last row: [5. 6.]
First item in last column: 2.0
Skip the first row:
[[3. 4.]
 [5. 6.]]

다음은 3축 텐서의 예입니다.

print(rank_3_tensor[:, :, 4])
tf.Tensor(
[[ 4  9]
 [14 19]
 [24 29]], shape=(3, 2), dtype=int32)
배치에서 각 예의 모든 위치에서 마지막 특성 선택하기
A 3x2x5 tensor with all the values at the index-4 of the last axis selected. The selected values packed into a 2-axis tensor.

텐서 슬라이싱 가이드에서 인덱싱을 적용하여 텐서의 개별 요소를 조작하는 방법을 알아보세요.

형상 조작하기

텐서의 형상을 바꾸는 것은 매우 유용합니다.

# Shape returns a `TensorShape` object that shows the size along each axis
x = tf.constant([[1], [2], [3]])
print(x.shape)
(3, 1)
# You can convert this object into a Python list, too
print(x.shape.as_list())
[3, 1]

텐서를 새로운 형상으로 바꿀 수 있습니다. 기본 데이터를 복제할 필요가 없으므로 tf.reshape 연산은 빠르고 저렴합니다.

# You can reshape a tensor to a new shape.
# Note that you're passing in a list
reshaped = tf.reshape(x, [1, 3])
print(x.shape)
print(reshaped.shape)
(3, 1)
(1, 3)

데이터의 레이아웃은 메모리에서 유지되고 요청된 형상이 같은 데이터를 가리키는 새 텐서가 작성됩니다. TensorFlow는 C 스타일 "행 중심" 메모리 순서를 사용합니다. 여기에서 가장 오른쪽에 있는 인덱스를 증가시키면 메모리의 단일 단계에 해당합니다.

print(rank_3_tensor)
tf.Tensor(
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]]

 [[10 11 12 13 14]
  [15 16 17 18 19]]

 [[20 21 22 23 24]
  [25 26 27 28 29]]], shape=(3, 2, 5), dtype=int32)

텐서를 평평하게 하면 어떤 순서로 메모리에 배치되어 있는지 확인할 수 있습니다.

# A `-1` passed in the `shape` argument says "Whatever fits".
print(tf.reshape(rank_3_tensor, [-1]))
tf.Tensor(
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 24 25 26 27 28 29], shape=(30,), dtype=int32)

일반적으로, tf.reshape의 합리적인 용도는 인접한 축을 결합하거나 분할하는 것뿐입니다(또는 1을 추가/제거).

이 3x2x5 텐서의 경우, 슬라이스가 혼합되지 않으므로 (3x2)x5 또는 3x (2x5)로 재구성하는 것이 합리적입니다.

print(tf.reshape(rank_3_tensor, [3*2, 5]), "\n")
print(tf.reshape(rank_3_tensor, [3, -1]))
tf.Tensor(
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]
 [25 26 27 28 29]], shape=(6, 5), dtype=int32) 

tf.Tensor(
[[ 0  1  2  3  4  5  6  7  8  9]
 [10 11 12 13 14 15 16 17 18 19]
 [20 21 22 23 24 25 26 27 28 29]], shape=(3, 10), dtype=int32)
몇 가지 좋은 재구성
A 3x2x5 tensor The same data reshaped to (3x2)x5 The same data reshaped to 3x(2x5)

형상을 변경하면 같은 총 요소 수를 가진 새로운 형상에 대해 "작동"하지만, 축의 순서를 고려하지 않으면 별로 쓸모가 없습니다.

tf.reshape에서 축 교환이 작동하지 않으면, tf.transpose를 수행해야 합니다.

# Bad examples: don't do this

# You can't reorder axes with reshape.
print(tf.reshape(rank_3_tensor, [2, 3, 5]), "\n") 

# This is a mess
print(tf.reshape(rank_3_tensor, [5, 6]), "\n")

# This doesn't work at all
try:
  tf.reshape(rank_3_tensor, [7, -1])
except Exception as e:
  print(f"{type(e).__name__}: {e}")
tf.Tensor(
[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]
  [10 11 12 13 14]]

 [[15 16 17 18 19]
  [20 21 22 23 24]
  [25 26 27 28 29]]], shape=(2, 3, 5), dtype=int32) 

tf.Tensor(
[[ 0  1  2  3  4  5]
 [ 6  7  8  9 10 11]
 [12 13 14 15 16 17]
 [18 19 20 21 22 23]
 [24 25 26 27 28 29]], shape=(5, 6), dtype=int32) 

InvalidArgumentError: { {function_node __wrapped__Reshape_device_/job:localhost/replica:0/task:0/device:GPU:0} } Input to reshape is a tensor with 30 values, but the requested shape requires a multiple of 7 [Op:Reshape]
몇 가지 잘못된 재구성
You can't reorder axes, use tf.transpose for that Anything that mixes the slices of data together is probably wrong. The new shape must fit exactly.

완전히 지정되지 않은 형상 전체에 걸쳐 실행할 수 있습니다. 형상에 None(축 길이를 알 수 없음)이 포함되거나 전체 형상이 None(텐서의 순위를 알 수 없음)입니다.

tf.RaggedTensor를 제외하고 이러한 형상은 TensorFlow의 상징적인 그래프 빌딩 API 컨텍스트에서만 발생합니다.

  • tf.function
  • keras 함수형 API

DTypes에 대한 추가 정보

tf.Tensor의 데이터 유형을 검사하려면, Tensor.dtype 속성을 사용합니다.

Python 객체에서 tf.Tensor를 만들 때 선택적으로 데이터 유형을 지정할 수 있습니다.

그렇지 않으면, TensorFlow는 데이터를 나타낼 수 있는 데이터 유형을 선택합니다. TensorFlow는 Python 정수를 tf.int32로, 파이썬 부동 소수점 숫자를 tf.float32로 변환합니다. 그렇지 않으면, TensorFlow는 NumPy가 배열로 변환할 때 사용하는 것과 같은 규칙을 사용합니다.

유형별로 캐스팅할 수 있습니다.

the_f64_tensor = tf.constant([2.2, 3.3, 4.4], dtype=tf.float64)
the_f16_tensor = tf.cast(the_f64_tensor, dtype=tf.float16)
# Now, cast to an uint8 and lose the decimal precision
the_u8_tensor = tf.cast(the_f16_tensor, dtype=tf.uint8)
print(the_u8_tensor)
tf.Tensor([2 3 4], shape=(3,), dtype=uint8)

브로드캐스팅

브로드캐스팅은 NumPy의 해당 특성에서 빌린 개념입니다. 요컨대, 특정 조건에서 작은 텐서는 결합된 연산을 실행할 때 더 큰 텐서에 맞게 자동으로 "확장(streched)"됩니다.

가장 간단하고 가장 일반적인 경우는 스칼라에 텐서를 곱하거나 추가하려고 할 때입니다. 이 경우, 스칼라는 다른 인수와 같은 형상으로 브로드캐스트됩니다.

x = tf.constant([1, 2, 3])

y = tf.constant(2)
z = tf.constant([2, 2, 2])
# All of these are the same computation
print(tf.multiply(x, 2))
print(x * y)
print(x * z)
tf.Tensor([2 4 6], shape=(3,), dtype=int32)
tf.Tensor([2 4 6], shape=(3,), dtype=int32)
tf.Tensor([2 4 6], shape=(3,), dtype=int32)

마찬가지로, 크기가 1인 축은 다른 인수와 일치하도록 확장할 수 있습니다. 두 인수 모두 같은 계산으로 확장할 수 있습니다.

이 경우, 3x1 행렬에 요소별로 1x4 행렬을 곱하여 3x4 행렬을 만듭니다. 선행 1이 선택 사항인 점에 유의하세요. y의 형상은 [4]입니다.

# These are the same computations
x = tf.reshape(x,[3,1])
y = tf.range(1, 5)
print(x, "\n")
print(y, "\n")
print(tf.multiply(x, y))
tf.Tensor(
[[1]
 [2]
 [3]], shape=(3, 1), dtype=int32) 

tf.Tensor([1 2 3 4], shape=(4,), dtype=int32) 

tf.Tensor(
[[ 1  2  3  4]
 [ 2  4  6  8]
 [ 3  6  9 12]], shape=(3, 4), dtype=int32)
추가 시 브로드캐스팅: [1, 4][3, 1]의 곱하기는 [3,4]입니다.
Adding a 3x1 matrix to a 4x1 matrix results in a 3x4 matrix

브로드캐스팅이 없는 같은 연산이 여기 있습니다.

x_stretch = tf.constant([[1, 1, 1, 1],
                         [2, 2, 2, 2],
                         [3, 3, 3, 3]])

y_stretch = tf.constant([[1, 2, 3, 4],
                         [1, 2, 3, 4],
                         [1, 2, 3, 4]])

print(x_stretch * y_stretch)  # Again, operator overloading
tf.Tensor(
[[ 1  2  3  4]
 [ 2  4  6  8]
 [ 3  6  9 12]], shape=(3, 4), dtype=int32)

대부분의 경우 브로드캐스팅은 브로드캐스트 연산으로 메모리에서 확장된 텐서를 구체화하지 않으므로 시간과 공간 효율적입니다.

tf.broadcast_to를 사용하여 브로드캐스팅이 어떤 모습인지 알 수 있습니다.

print(tf.broadcast_to(tf.constant([1, 2, 3]), [3, 3]))
tf.Tensor(
[[1 2 3]
 [1 2 3]
 [1 2 3]], shape=(3, 3), dtype=int32)

예를 들어, broadcast_to는 수학적인 op와 달리 메모리를 절약하기 위해 특별한 연산을 수행하지 않습니다. 여기에서 텐서를 구체화합니다.

훨씬 더 복잡해질 수 있습니다. Jake VanderPlas의 저서 Python Data Science Handbook해당 섹션{:.external}에 더 많은 브로드캐스팅 트릭이 소개되어 있습니다(이번에도 NumPy에서).

tf.convert_to_tensor

tf.matmultf.reshape와 같은 대부분의 ops는 클래스 tf.Tensor의 인수를 사용합니다. 그러나 위의 경우, 텐서 형상의 Python 객체가 수용됨을 알 수 있습니다.

전부는 아니지만 대부분의 ops는 텐서가 아닌 인수에 대해 convert_to_tensor를 호출합니다. 변환 레지스트리가 있어 NumPy의 ndarray, TensorShape , Python 목록 및 tf.Variable과 같은 대부분의 객체 클래스는 모두 자동으로 변환됩니다.

자세한 내용은 tf.register_tensor_conversion_function을 참조하세요. 자신만의 유형이 있으면 자동으로 텐서로 변환할 수 있습니다.

비정형 텐서

어떤 축을 따라 다양한 수의 요소를 가진 텐서를 "비정형(ragged)"이라고 합니다. 비정형 데이터에는 tf.ragged.RaggedTensor를 사용합니다.

예를 들어, 비정형 텐서는 정규 텐서로 표현할 수 없습니다.

tf.RaggedTensor, 형상: [4, None]
A 2-axis ragged tensor, each row can have a different length.
ragged_list = [
    [0, 1, 2, 3],
    [4, 5],
    [6, 7, 8],
    [9]]
try:
  tensor = tf.constant(ragged_list)
except Exception as e:
  print(f"{type(e).__name__}: {e}")
ValueError: Can't convert non-rectangular Python sequence to Tensor.

대신 tf.ragged.constant를 사용하여 tf.RaggedTensor를 작성합니다.

ragged_tensor = tf.ragged.constant(ragged_list)
print(ragged_tensor)
<tf.RaggedTensor [[0, 1, 2, 3], [4, 5], [6, 7, 8], [9]]>

tf.RaggedTensor의 형상에는 알 수 없는 길이의 일부 축이 포함됩니다.

print(ragged_tensor.shape)
(4, None)

문자열 텐서

tf.stringdtype이며, 텐서에서 문자열(가변 길이의 바이트 배열)과 같은 데이터를 나타낼 수 있습니다.

문자열은 원자성이므로 Python 문자열과 같은 방식으로 인덱싱할 수 없습니다. 문자열의 길이는 텐서의 축 중의 하나가 아닙니다. 문자열을 조작하는 함수에 대해서는 tf.strings를 참조하세요.

다음은 스칼라 문자열 텐서입니다.

# Tensors can be strings, too here is a scalar string.
scalar_string_tensor = tf.constant("Gray wolf")
print(scalar_string_tensor)
tf.Tensor(b'Gray wolf', shape=(), dtype=string)

문자열의 벡터는 다음과 같습니다.

문자열의 벡터, 형상: [3,]
The string length is not one of the tensor's axes.
# If you have three string tensors of different lengths, this is OK.
tensor_of_strings = tf.constant(["Gray wolf",
                                 "Quick brown fox",
                                 "Lazy dog"])
# Note that the shape is (3,). The string length is not included.
print(tensor_of_strings)
tf.Tensor([b'Gray wolf' b'Quick brown fox' b'Lazy dog'], shape=(3,), dtype=string)

위의 출력에서 b 접두사는 tf.string dtype이 유니코드 문자열이 아니라 바이트 문자열임을 나타냅니다. TensorFlow에서 유니코드 텍스트를 처리하는 자세한 내용은 유니코드 튜토리얼을 참조하세요.

유니코드 문자를 전달하면 UTF-8로 인코딩됩니다.

tf.constant("🥳👍")
<tf.Tensor: shape=(), dtype=string, numpy=b'\xf0\x9f\xa5\xb3\xf0\x9f\x91\x8d'>

문자열이 있는 일부 기본 함수는 tf.strings을 포함하여 tf.strings.split에서 찾을 수 있습니다.

# You can use split to split a string into a set of tensors
print(tf.strings.split(scalar_string_tensor, sep=" "))
tf.Tensor([b'Gray' b'wolf'], shape=(2,), dtype=string)
# ...but it turns into a `RaggedTensor` if you split up a tensor of strings,
# as each string might be split into a different number of parts.
print(tf.strings.split(tensor_of_strings))
<tf.RaggedTensor [[b'Gray', b'wolf'], [b'Quick', b'brown', b'fox'], [b'Lazy', b'dog']]>
세 개의 분할된 문자열, 형상: [3, None]
Splitting multiple strings returns a tf.RaggedTensor

tf.string.to_number:

text = tf.constant("1 10 100")
print(tf.strings.to_number(tf.strings.split(text, " ")))
tf.Tensor([  1.  10. 100.], shape=(3,), dtype=float32)

tf.cast를 사용하여 문자열 텐서를 숫자로 변환할 수는 없지만, 바이트로 변환한 다음 숫자로 변환할 수 있습니다.

byte_strings = tf.strings.bytes_split(tf.constant("Duck"))
byte_ints = tf.io.decode_raw(tf.constant("Duck"), tf.uint8)
print("Byte strings:", byte_strings)
print("Bytes:", byte_ints)
Byte strings: tf.Tensor([b'D' b'u' b'c' b'k'], shape=(4,), dtype=string)
Bytes: tf.Tensor([ 68 117  99 107], shape=(4,), dtype=uint8)
# Or split it up as unicode and then decode it
unicode_bytes = tf.constant("アヒル 🦆")
unicode_char_bytes = tf.strings.unicode_split(unicode_bytes, "UTF-8")
unicode_values = tf.strings.unicode_decode(unicode_bytes, "UTF-8")

print("\nUnicode bytes:", unicode_bytes)
print("\nUnicode chars:", unicode_char_bytes)
print("\nUnicode values:", unicode_values)
Unicode bytes: tf.Tensor(b'\xe3\x82\xa2\xe3\x83\x92\xe3\x83\xab \xf0\x9f\xa6\x86', shape=(), dtype=string)

Unicode chars: tf.Tensor([b'\xe3\x82\xa2' b'\xe3\x83\x92' b'\xe3\x83\xab' b' ' b'\xf0\x9f\xa6\x86'], shape=(5,), dtype=string)

Unicode values: tf.Tensor([ 12450  12498  12523     32 129414], shape=(5,), dtype=int32)

tf.string dtype은 TensorFlow의 모든 원시 바이트 데이터에 사용됩니다. tf.io 모듈에는 이미지 디코딩 및 csv 구문 분석을 포함하여 데이터를 바이트로 변환하거나 바이트에서 변환하는 함수가 포함되어 있습니다.

희소 텐서

때로는 매우 넓은 임베드 공간과 같이 데이터가 희소합니다. TensorFlow는 tf.sparse.SparseTensor 및 관련 연산을 지원하여 희소 데이터를 효율적으로 저장합니다.

tf.SparseTensor, 형상: [3, 4]
An 3x4 grid, with values in only two of the cells.
# Sparse tensors store values by index in a memory-efficient manner
sparse_tensor = tf.sparse.SparseTensor(indices=[[0, 0], [1, 2]],
                                       values=[1, 2],
                                       dense_shape=[3, 4])
print(sparse_tensor, "\n")

# You can convert sparse tensors to dense
print(tf.sparse.to_dense(sparse_tensor))
SparseTensor(indices=tf.Tensor(
[[0 0]
 [1 2]], shape=(2, 2), dtype=int64), values=tf.Tensor([1 2], shape=(2,), dtype=int32), dense_shape=tf.Tensor([3 4], shape=(2,), dtype=int64)) 

tf.Tensor(
[[1 0 0 0]
 [0 0 2 0]
 [0 0 0 0]], shape=(3, 4), dtype=int32)