#@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.

"""
Explanation: Copyright 2020 The TensorFlow Authors.
End of explanation
"""


import tensorflow as tf
import numpy as np

"""
Explanation: 텐서 소개
<table class="tfo-notebook-buttons" align="left">
  <td>     <a target="_blank" href="https://www.tensorflow.org/guide/tensor"><img src="https://www.tensorflow.org/images/tf_logo_32px.png">TensorFlow.org에서 보기</a>   </td>
  <td><a target="_blank" href="https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ko/guide/tensor.ipynb"><img src="https://www.tensorflow.org/images/colab_logo_32px.png">Google Colab에서 실행</a></td>
  <td><a target="_blank" href="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/tensor.ipynb"><img src="https://www.tensorflow.org/images/GitHub-Mark-32px.png">GitHub에서소스 보기</a></td>
  <td><a href="https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/ko/guide/tensor.ipynb"><img src="https://www.tensorflow.org/images/download_logo_32px.png">노트북 다운로드</a></td>
</table>
End of explanation
"""


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

"""
Explanation: 텐서는 일관된 유형(dtype이라고 불림)을 가진 다차원 배열입니다. 지원되는 모든 dtypes은 tf.dtypes.DType에서 볼 수 있습니다.
NumPy에 익숙하다면, 텐서는 일종의 np.arrays와 같습니다.
모든 텐서는 Python 숫자 및 문자열과 같이 변경할 수 없습니다. 텐서의 내용을 업데이트할 수 없으며 새로운 텐서를 만들 수만 있습니다.
기초
기본 텐서를 만들어 봅시다.
다음은 "스칼라" 또는 "순위-0" 텐서입니다. 스칼라는 단일 값을 포함하며 "축"은 없습니다.
End of explanation
"""


# Let's make this a float tensor.
rank_1_tensor = tf.constant([2.0, 3.0, 4.0])
print(rank_1_tensor)

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


# If we want to be specific, we 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)

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


# 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)

"""
Explanation: <table>
<tr>
  <th>스칼라, 형상: <code>[]</code> </th>
  <th>벡터, 형상: <code>[3]</code> </th>
  <th>행렬, 형상: <code>[3, 2]</code> </th>
</tr>
<tr>
  <td>    <img src="images/tensor/scalar.png" alt="A scalar, the number 4">
</td>
  <td>    <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/vector.png?raw=true" alt="The line with 3 sections, each one containing a number.">   </td>
  <td>    <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/matrix.png?raw=true" alt="A 3x2 grid, with each cell containing a number.">   </td>
</tr>
</table>

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


np.array(rank_2_tensor)

rank_2_tensor.numpy()

"""
Explanation: 축이 두 개 이상인 텐서를 시각화하는 방법에는 여러 가지가 있습니다.
<table>
<tr>
  <th colspan="3">3축 텐서, 형상: <code>[3, 2, 5]</code> </th>
</tr>
<tr>
</tr>
<tr>
  <td>    <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/3-axis_numpy.png?raw=true">   </td>
  <td>    <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/3-axis_front.png?raw=true">   </td>
  <td>    <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/3-axis_block.png?raw=true">   </td>
</tr>
</table>

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


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")

print(a + b, "\n") # element-wise addition
print(a * b, "\n") # element-wise multiplication
print(a @ b, "\n") # matrix multiplication

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

복소수
문자열

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

비정형(아래의 RaggedTensor 참조)
희소(아래의 SparseTensor 참조)

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


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.argmax(c))
# Compute the softmax
print(tf.nn.softmax(c))

"""
Explanation: 텐서는 모든 종류의 연산(ops)에 사용됩니다.
End of explanation
"""


rank_4_tensor = tf.zeros([3, 2, 4, 5])

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

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

참고: "2차원 텐서"에 대한 참조가 있을 수 있지만, 순위-2 텐서는 일반적으로 2D 공간을 설명하지 않습니다.
텐서 및 tf.TensorShape 객체에는 다음에 액세스하기 위한 편리한 속성이 있습니다.
End of explanation
"""


print("Type of every element:", rank_4_tensor.dtype)
print("Number of dimensions:", 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())

"""
Explanation: <table>
<tr>
  <th colspan="2">순위-4 텐서, 형상: <code>[3, 2, 4, 5]</code> </th>
</tr>
<tr>
  <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/shape.png?raw=true" alt="A tensor shape is like a vector.">     </td>
<td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/4-axis_block.png?raw=true" alt="A 4-axis tensor">   </td>
  </tr>
</table>
End of explanation
"""


rank_1_tensor = tf.constant([0, 1, 1, 2, 3, 5, 8, 13, 21, 34])
print(rank_1_tensor.numpy())

"""
Explanation: 축은 종종 인덱스로 참조하지만, 항상 각 축의 의미를 추적해야 합니다. 축이 전역에서 로컬로 정렬되는 경우가 종종 있습니다. 배치 축이 먼저 오고 그 다음에 공간 차원과 각 위치의 특성이 마지막에 옵니다. 이러한 방식으로 특성 벡터는 연속적인 메모리 영역입니다.
<table>
<tr>
<th>일반적인 축 순서</th>
</tr>
<tr>
    <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/shape2.png?raw=true" alt="Keep track of what each axis is. A 4-axis tensor might be: Batch, Width, Height, Features">   </td>
</tr>
</table>

인덱싱
단일 축 인덱싱
TensorFlow는 파이썬의 목록 또는 문자열 인덱싱과 마찬가지로 표준 파이썬 인덱싱 규칙과 numpy 인덱싱의 기본 규칙을 따릅니다.

인덱스는 0에서 시작합니다.
음수 인덱스는 끝에서부터 거꾸로 계산합니다.
콜론, :은 슬라이스 start:stop:step에 사용됩니다.
End of explanation
"""


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

"""
Explanation: 스칼라를 사용하여 인덱싱하면 축이 제거됩니다.
End of explanation
"""


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())

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


print(rank_2_tensor.numpy())

"""
Explanation: 다축 인덱싱
더 높은 순위의 텐서는 여러 인덱스를 전달하여 인덱싱됩니다.
단일 축의 경우에서와 정확히 같은 규칙이 각 축에 독립적으로 적용됩니다.
End of explanation
"""


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

"""
Explanation: 각 인덱스에 정수를 전달하면 결과는 스칼라입니다.
End of explanation
"""


# 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")

"""
Explanation: 정수와 슬라이스를 조합하여 인덱싱할 수 있습니다.
End of explanation
"""


print(rank_3_tensor[:, :, 4])

"""
Explanation: 다음은 3축 텐서의 예입니다.
End of explanation
"""


# Shape returns a `TensorShape` object that shows the size on each dimension
var_x = tf.Variable(tf.constant([[1], [2], [3]]))
print(var_x.shape)

# You can convert this object into a Python list, too
print(var_x.shape.as_list())

"""
Explanation: <table>
<tr>
<th colspan="2">배치에서 각 예의 모든 위치에서 마지막 특성 선택하기</th>
</tr>
<tr>
    <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/index1.png?raw=true" alt="A 3x2x5 tensor with all the values at the index-4 of the last axis selected.">   </td>
      <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/index2.png?raw=true" alt="The selected values packed into a 2-axis tensor.">   </td>
</tr>
</table>

텐서 슬라이싱 가이드에서 인덱싱을 적용하여 텐서의 개별 요소를 조작하는 방법을 알아보세요.
형상 조작하기
텐서의 형상을 바꾸는 것은 매우 유용합니다.
End of explanation
"""


# We can reshape a tensor to a new shape.
# Note that we're passing in a list
reshaped = tf.reshape(var_x, [1, 3])

print(var_x.shape)
print(reshaped.shape)

"""
Explanation: 텐서를 새로운 형상으로 바꿀 수 있습니다. 기본 데이터를 복제할 필요가 없으므로 재구성이 빠르고 저렴합니다.
End of explanation
"""


print(rank_3_tensor)

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


# A `-1` passed in the `shape` argument says "Whatever fits".
print(tf.reshape(rank_3_tensor, [-1]))

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


print(tf.reshape(rank_3_tensor, [3*2, 5]), "\n")
print(tf.reshape(rank_3_tensor, [3, -1]))

"""
Explanation: 일반적으로, tf.reshape의 합리적인 용도는 인접한 축을 결합하거나 분할하는 것뿐입니다(또는 1을 추가/제거).
이 3x2x5 텐서의 경우, 슬라이스가 혼합되지 않으므로 (3x2)x5 또는 3x (2x5)로 재구성하는 것이 합리적입니다.
End of explanation
"""


# 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}")

"""
Explanation: <table>
<th colspan="3">몇 가지 좋은 재구성</th>
<tr>
  <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/reshape-before.png?raw=true" alt="A 3x2x5 tensor">   </td>
  <td>   <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/reshape-good1.png?raw=true" alt="The same data reshaped to (3x2)x5">   </td>
  <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/reshape-good2.png?raw=true" alt="The same data reshaped to 3x(2x5)">   </td>
</tr>
</table>

형상을 변경하면 같은 총 요소 수를 가진 새로운 형상에 대해 "작동"하지만, 축의 순서를 고려하지 않으면 별로 쓸모가 없습니다.
tf.reshape에서 축 교환이 작동하지 않으면, tf.transpose를 수행해야 합니다.
End of explanation
"""


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, let's cast to an uint8 and lose the decimal precision
the_u8_tensor = tf.cast(the_f16_tensor, dtype=tf.uint8)
print(the_u8_tensor)

"""
Explanation: <table>
<th colspan="3">몇 가지 잘못된 재구성</th>
<tr>
  <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/reshape-bad.png?raw=true" alt="You can't reorder axes, use tf.transpose for that">   </td>
  <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/reshape-bad4.png?raw=true" alt="Anything that mixes the slices of data together is probably wrong.">   </td>
  <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/reshape-bad2.png?raw=true" alt="The new shape must fit exactly.">   </td>
</tr>
</table>

완전히 지정되지 않은 형상 전체에 걸쳐 실행할 수 있습니다. 형상에 None(축 길이를 알 수 없음)이 포함되거나 전체 형상이 None(텐서의 순위를 알 수 없음)입니다.
tf.RaggedTensor를 제외하고, TensorFlow의 상징적인 그래프 빌딩 API의 컨텍스트에서만 발생합니다.

tf.function
keras 함수형 API

DTypes에 대한 추가 정보
tf.Tensor의 데이터 유형을 검사하려면, Tensor.dtype 속성을 사용합니다.
Python 객체에서 tf.Tensor를 만들 때 선택적으로 데이터 유형을 지정할 수 있습니다.
그렇지 않으면, TensorFlow는 데이터를 나타낼 수 있는 데이터 유형을 선택합니다. TensorFlow는 Python 정수를 tf.int32로, Python 부동 소수점 숫자를 tf.float32로 변환합니다. 그렇지 않으면, TensorFlow는 NumPy가 배열로 변환할 때 사용하는 것과 같은 규칙을 사용합니다.
유형별로 캐스팅할 수 있습니다.
End of explanation
"""


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)

"""
Explanation: 브로드캐스팅
브로드캐스팅은 NumPy의 해당 특성에서 빌린 개념입니다. 요컨대, 특정 조건에서 작은 텐서는 결합된 연산을 실행할 때 더 큰 텐서에 맞게 자동으로 "확장(streched)"됩니다.
가장 간단하고 가장 일반적인 경우는 스칼라에 텐서를 곱하거나 추가하려고 할 때입니다. 이 경우, 스칼라는 다른 인수와 같은 형상으로 브로드캐스트됩니다.
End of explanation
"""


# 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))

"""
Explanation: 마찬가지로, 크기가 1인 축은 다른 인수와 일치하도록 확장할 수 있습니다. 두 인수 모두 같은 계산으로 확장할 수 있습니다.
이 경우, 3x1 행렬에 요소별로 1x4 행렬을 곱하여 3x4 행렬을 만듭니다. 선행 1이 선택 사항인 점에 유의하세요. y의 형상은 [4]입니다.
End of explanation
"""


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

"""
Explanation: <table>
<tr>
  <th>추가 시 브로드캐스팅: <code>[1, 4]</code>와 <code>[3, 1]</code>의 곱하기는 <code>[3,4]</code>입니다.</th>
</tr>
<tr>
  <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/broadcasting.png?raw=true" alt="Adding a 3x1 matrix to a 4x1 matrix results in a 3x4 matrix">   </td>
</tr>
</table>

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


print(tf.broadcast_to(tf.constant([1, 2, 3]), [3, 3]))

"""
Explanation: 대부분의 경우 브로드캐스팅은 브로드캐스트 연산으로 메모리에서 확장된 텐서를 구체화하지 않으므로 시간과 공간 효율적입니다.
tf.broadcast_to를 사용하여 브로드캐스팅이 어떤 모습인지 알 수 있습니다.
End of explanation
"""


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}")

"""
Explanation: 예를 들어, broadcast_to는 수학적인 op와 달리 메모리를 절약하기 위해 특별한 연산을 수행하지 않습니다. 여기에서 텐서를 구체화합니다.
훨씬 더 복잡해질 수 있습니다. Jake VanderPlas의 저서 Python Data Science Handbook의 해당 섹션에서는 더 많은 브로드캐스팅 트릭을 보여줍니다(NumPy에서).
tf.convert_to_tensor
tf.matmul 및 tf.reshape와 같은 대부분의 ops는 클래스 tf.Tensor의 인수를 사용합니다. 그러나 위의 경우, 텐서 형상의 Python 객체가 수용됨을 알 수 있습니다.
전부는 아니지만 대부분의 ops는 텐서가 아닌 인수에 대해 convert_to_tensor를 호출합니다. 변환 레지스트리가 있어 NumPy의 ndarray, TensorShape , Python 목록 및 tf.Variable과 같은 대부분의 객체 클래스는 모두 자동으로 변환됩니다.
자세한 내용은 tf.register_tensor_conversion_function을 참조하세요. 자신만의 유형이 있으면 자동으로 텐서로 변환할 수 있습니다.
비정형 텐서
어떤 축을 따라 다양한 수의 요소를 가진 텐서를 "비정형(ragged)"이라고 합니다. 비정형 데이터에는 tf.ragged.RaggedTensor를 사용합니다.
예를 들어, 비정형 텐서는 정규 텐서로 표현할 수 없습니다.
<table>
<tr>
  <th>`tf.RaggedTensor`, 형상: <code>[4, None]</code> </th>
</tr>
<tr>
  <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/ragged.png?raw=true" alt="A 2-axis ragged tensor, each row can have a different length.">   </td>
</tr>
</table>
End of explanation
"""


ragged_tensor = tf.ragged.constant(ragged_list)
print(ragged_tensor)

"""
Explanation: 대신 tf.ragged.constant를 사용하여 tf.RaggedTensor를 작성합니다.
End of explanation
"""


print(ragged_tensor.shape)

"""
Explanation: tf.RaggedTensor의 형상에는 알 수 없는 길이의 일부 축이 포함됩니다.
End of explanation
"""


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

"""
Explanation: 문자열 텐서
tf.string은 dtype이며, 텐서에서 문자열(가변 길이의 바이트 배열)과 같은 데이터를 나타낼 수 있습니다.
문자열은 원자성이므로 Python 문자열과 같은 방식으로 인덱싱할 수 없습니다. 문자열의 길이는 텐서의 축 중의 하나가 아닙니다. 문자열을 조작하는 함수에 대해서는 tf.strings를 참조하세요.
다음은 스칼라 문자열 텐서입니다.
End of explanation
"""


# 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)

"""
Explanation: 문자열의 벡터는 다음과 같습니다.
<table>
<tr>
  <th>문자열의 벡터, 형상: <code>[3,]</code> </th>
</tr>
<tr>
  <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/strings.png?raw=true" alt="The string length is not one of the tensor's axes.">   </td>
</tr>
</table>
End of explanation
"""


tf.constant("🥳👍")

"""
Explanation: 위의 출력에서 b 접두사는 tf.string dtype이 유니코드 문자열이 아니라 바이트 문자열임을 나타냅니다. TensorFlow에서 유니코드 텍스트를 처리하는 자세한 내용은 유니코드 튜토리얼을 참조하세요.
유니코드 문자를 전달하면 UTF-8로 인코딩됩니다.
End of explanation
"""


# We can use split to split a string into a set of tensors
print(tf.strings.split(scalar_string_tensor, sep=" "))

# ...but it turns into a `RaggedTensor` if we 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))

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


text = tf.constant("1 10 100")
print(tf.strings.to_number(tf.strings.split(text, " ")))

"""
Explanation: <table>
<tr>
  <th>세 개의 분할된 문자열, 형상: <code>[3, None]</code> </th>
</tr>
<tr>
  <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/string-split.png?raw=true" alt="Splitting multiple strings returns a tf.RaggedTensor">   </td>
</tr>
</table>

tf.string.to_number:
End of explanation
"""


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)

# 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)

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


# 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")

# We can convert sparse tensors to dense
print(tf.sparse.to_dense(sparse_tensor))

"""
Explanation: tf.string dtype은 TensorFlow의 모든 원시 바이트 데이터에 사용됩니다. tf.io 모듈에는 이미지 디코딩 및 csv 구문 분석을 포함하여 데이터를 바이트로 변환하거나 바이트에서 변환하는 함수가 포함되어 있습니다.
희소 텐서
때로는 매우 넓은 임베드 공간과 같이 데이터가 희소합니다. TensorFlow는 tf.sparse.SparseTensor 및 관련 연산을 지원하여 희소 데이터를 효율적으로 저장합니다.
<table>
<tr>
  <th>`tf.SparseTensor`, 형상: <code>[3, 4]</code> </th>
</tr>
<tr>
  <td> <img src="https://github.com/tensorflow/docs-l10n/blob/master/site/ko/guide/images/tensor/sparse.png?raw=true" alt="An 3x4 grid, with values in only two of the cells.">   </td>
</tr>
</table>
End of explanation
"""


