{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "Tce3stUlHN0L" }, "source": [ "##### Copyright 2020 The TensorFlow Authors." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "cellView": "form", "execution": { "iopub.execute_input": "2022-12-14T20:10:17.927860Z", "iopub.status.busy": "2022-12-14T20:10:17.927283Z", "iopub.status.idle": "2022-12-14T20:10:17.931163Z", "shell.execute_reply": "2022-12-14T20:10:17.930600Z" }, "id": "tuOe1ymfHZPu" }, "outputs": [], "source": [ "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ] }, { "cell_type": "markdown", "metadata": { "id": "qFdPvlXBOdUN" }, "source": [ "# 텐서 소개" ] }, { "cell_type": "markdown", "metadata": { "id": "MfBg1C5NB3X0" }, "source": [ "\n", " \n", " \n", " \n", " \n", "
TensorFlow.org에서 보기 Google Colab에서 실행GitHub에서소스 보기노트북 다운로드
" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:17.934316Z", "iopub.status.busy": "2022-12-14T20:10:17.934072Z", "iopub.status.idle": "2022-12-14T20:10:19.820992Z", "shell.execute_reply": "2022-12-14T20:10:19.820239Z" }, "id": "AL2hzxorJiWy" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "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\n", "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\n", "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.\n" ] } ], "source": [ "import tensorflow as tf\n", "import numpy as np" ] }, { "cell_type": "markdown", "metadata": { "id": "VQ3s2J8Vgowq" }, "source": [ "텐서는 일관된 유형(`dtype`이라고 불림)을 가진 다차원 배열입니다. 지원되는 모든 `dtypes`은 `tf.dtypes.DType`에서 볼 수 있습니다.\n", "\n", "[NumPy](https://numpy.org/devdocs/user/quickstart.html){:.external}에 익숙하다면 텐서가 (일종의) `np.arrays`와 유사하다는 것을 참고해 주시기 바랍니다.\n", "\n", "모든 텐서는 Python 숫자 및 문자열과 같이 변경할 수 없습니다. 텐서의 내용을 업데이트할 수 없으며 새로운 텐서를 만들 수만 있습니다.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "DRK5-9EpYbzG" }, "source": [ "## 기초\n", "\n", "먼저, 기본 텐서를 생성해 봅니다." ] }, { "cell_type": "markdown", "metadata": { "id": "uSHRFT6LJbxq" }, "source": [ "다음은 \"스칼라\" 또는 \"순위-0\" 텐서입니다. 스칼라는 단일 값을 포함하며 \"축\"은 없습니다." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:19.825234Z", "iopub.status.busy": "2022-12-14T20:10:19.824856Z", "iopub.status.idle": "2022-12-14T20:10:23.130117Z", "shell.execute_reply": "2022-12-14T20:10:23.129279Z" }, "id": "d5JcgLFR6gHv" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(4, shape=(), dtype=int32)\n" ] } ], "source": [ "# This will be an int32 tensor by default; see \"dtypes\" below.\n", "rank_0_tensor = tf.constant(4)\n", "print(rank_0_tensor)" ] }, { "cell_type": "markdown", "metadata": { "id": "tdmPAn9fWYs5" }, "source": [ "\"벡터\" 또는 \"순위-1\" 텐서는 값의 목록과 같습니다. 벡터에는 하나의 축이 있습니다." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.133953Z", "iopub.status.busy": "2022-12-14T20:10:23.133366Z", "iopub.status.idle": "2022-12-14T20:10:23.141843Z", "shell.execute_reply": "2022-12-14T20:10:23.141130Z" }, "id": "oZos8o_R6oE7" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor([2. 3. 4.], shape=(3,), dtype=float32)\n" ] } ], "source": [ "# Let's make this a float tensor.\n", "rank_1_tensor = tf.constant([2.0, 3.0, 4.0])\n", "print(rank_1_tensor)" ] }, { "cell_type": "markdown", "metadata": { "id": "G3IJG-ug_H4u" }, "source": [ "\"행렬\" 또는 \"순위-2\" 텐서에는 두 개의 축이 있습니다." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.145207Z", "iopub.status.busy": "2022-12-14T20:10:23.144671Z", "iopub.status.idle": "2022-12-14T20:10:23.150449Z", "shell.execute_reply": "2022-12-14T20:10:23.149619Z" }, "id": "cnOIA_xb6u0M" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[[1. 2.]\n", " [3. 4.]\n", " [5. 6.]], shape=(3, 2), dtype=float16)\n" ] } ], "source": [ "# If you want to be specific, you can set the dtype (see below) at creation time\n", "rank_2_tensor = tf.constant([[1, 2],\n", " [3, 4],\n", " [5, 6]], dtype=tf.float16)\n", "print(rank_2_tensor)" ] }, { "cell_type": "markdown", "metadata": { "id": "19m72qEPkfxi" }, "source": [ "\n", "\n", " \n", " \n", " \n", "\n", "\n", " \n", " \n", " \n", "\n", "
스칼라, 형상: [] 벡터, 형상: [3] 행렬, 형상: [3, 2]
\"A \"The \"A
\n" ] }, { "cell_type": "markdown", "metadata": { "id": "fjFvzcn4_ehD" }, "source": [ "텐서에는 더 많은 축이 있을 수 있습니다. 여기에는 세 개의 축이 있는 텐서가 사용됩니다." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.153816Z", "iopub.status.busy": "2022-12-14T20:10:23.153253Z", "iopub.status.idle": "2022-12-14T20:10:23.158130Z", "shell.execute_reply": "2022-12-14T20:10:23.157366Z" }, "id": "sesW7gw6JkXy" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[[[ 0 1 2 3 4]\n", " [ 5 6 7 8 9]]\n", "\n", " [[10 11 12 13 14]\n", " [15 16 17 18 19]]\n", "\n", " [[20 21 22 23 24]\n", " [25 26 27 28 29]]], shape=(3, 2, 5), dtype=int32)\n" ] } ], "source": [ "# There can be an arbitrary number of\n", "# axes (sometimes called \"dimensions\")\n", "rank_3_tensor = tf.constant([\n", " [[0, 1, 2, 3, 4],\n", " [5, 6, 7, 8, 9]],\n", " [[10, 11, 12, 13, 14],\n", " [15, 16, 17, 18, 19]],\n", " [[20, 21, 22, 23, 24],\n", " [25, 26, 27, 28, 29]],])\n", "\n", "print(rank_3_tensor)" ] }, { "cell_type": "markdown", "metadata": { "id": "rM2sTGIkoE3S" }, "source": [ "축이 두 개 이상인 텐서를 시각화하는 방법에는 여러 가지가 있습니다." ] }, { "cell_type": "markdown", "metadata": { "id": "NFiYfNMMhDgL" }, "source": [ "\n", "\n", " \n", "\n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "
3축 텐서, 형상: [3, 2, 5]
" ] }, { "cell_type": "markdown", "metadata": { "id": "oWAc0U8OZwNb" }, "source": [ "`np.array` 또는 `tensor.numpy` 메서드를 사용하여 텐서를 NumPy 배열로 변환할 수 있습니다." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.161510Z", "iopub.status.busy": "2022-12-14T20:10:23.160928Z", "iopub.status.idle": "2022-12-14T20:10:23.167415Z", "shell.execute_reply": "2022-12-14T20:10:23.166727Z" }, "id": "J5u6_6ZYaS7B" }, "outputs": [ { "data": { "text/plain": [ "array([[1., 2.],\n", " [3., 4.],\n", " [5., 6.]], dtype=float16)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.array(rank_2_tensor)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.170309Z", "iopub.status.busy": "2022-12-14T20:10:23.169913Z", "iopub.status.idle": "2022-12-14T20:10:23.174337Z", "shell.execute_reply": "2022-12-14T20:10:23.173658Z" }, "id": "c6Taz2gIaZeo" }, "outputs": [ { "data": { "text/plain": [ "array([[1., 2.],\n", " [3., 4.],\n", " [5., 6.]], dtype=float16)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rank_2_tensor.numpy()" ] }, { "cell_type": "markdown", "metadata": { "id": "hnz19F0ocEKD" }, "source": [ "텐서에는 종종 float와 int가 포함되지만, 다음과 같은 다른 유형도 있습니다.\n", "\n", "- 복소수\n", "- 문자열\n", "\n", "기본 `tf.Tensor` 클래스에서는 텐서가 \"직사각형\"이어야 합니다. 즉, 각 축을 따라 모든 요소의 크기가 같습니다. 그러나 다양한 형상을 처리할 수 있는 특수 유형의 텐서가 있습니다.\n", "\n", "- 비정형 텐서(아래의 [RaggedTensor](#ragged_tensors) 참조)\n", "- 희소 텐서(아래의 [SparseTensor](#sparse_tensors) 참조)" ] }, { "cell_type": "markdown", "metadata": { "id": "SDC7OGeAIJr8" }, "source": [ "덧셈, 요소별 곱셈 및 행렬 곱셈을 포함하여 텐서에 대한 기본 산술을 수행할 수 있습니다." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.177957Z", "iopub.status.busy": "2022-12-14T20:10:23.177410Z", "iopub.status.idle": "2022-12-14T20:10:23.186004Z", "shell.execute_reply": "2022-12-14T20:10:23.185400Z" }, "id": "-DTkjwDOIIDa" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[[2 3]\n", " [4 5]], shape=(2, 2), dtype=int32) \n", "\n", "tf.Tensor(\n", "[[1 2]\n", " [3 4]], shape=(2, 2), dtype=int32) \n", "\n", "tf.Tensor(\n", "[[3 3]\n", " [7 7]], shape=(2, 2), dtype=int32) \n", "\n" ] } ], "source": [ "a = tf.constant([[1, 2],\n", " [3, 4]])\n", "b = tf.constant([[1, 1],\n", " [1, 1]]) # Could have also said `tf.ones([2,2])`\n", "\n", "print(tf.add(a, b), \"\\n\")\n", "print(tf.multiply(a, b), \"\\n\")\n", "print(tf.matmul(a, b), \"\\n\")" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.189559Z", "iopub.status.busy": "2022-12-14T20:10:23.188907Z", "iopub.status.idle": "2022-12-14T20:10:23.194110Z", "shell.execute_reply": "2022-12-14T20:10:23.193443Z" }, "id": "2smoWeUz-N2q" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[[2 3]\n", " [4 5]], shape=(2, 2), dtype=int32) \n", "\n", "tf.Tensor(\n", "[[1 2]\n", " [3 4]], shape=(2, 2), dtype=int32) \n", "\n", "tf.Tensor(\n", "[[3 3]\n", " [7 7]], shape=(2, 2), dtype=int32) \n", "\n" ] } ], "source": [ "print(a + b, \"\\n\") # element-wise addition\n", "print(a * b, \"\\n\") # element-wise multiplication\n", "print(a @ b, \"\\n\") # matrix multiplication" ] }, { "cell_type": "markdown", "metadata": { "id": "S3_vIAl2JPVc" }, "source": [ "텐서는 모든 종류의 연산(ops)에 사용합니다." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.197395Z", "iopub.status.busy": "2022-12-14T20:10:23.196846Z", "iopub.status.idle": "2022-12-14T20:10:23.205389Z", "shell.execute_reply": "2022-12-14T20:10:23.204722Z" }, "id": "Gp4WUYzGIbnv" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(10.0, shape=(), dtype=float32)\n", "tf.Tensor([1 0], shape=(2,), dtype=int64)\n", "tf.Tensor(\n", "[[2.6894143e-01 7.3105854e-01]\n", " [9.9987662e-01 1.2339458e-04]], shape=(2, 2), dtype=float32)\n" ] } ], "source": [ "c = tf.constant([[4.0, 5.0], [10.0, 1.0]])\n", "\n", "# Find the largest value\n", "print(tf.reduce_max(c))\n", "# Find the index of the largest value\n", "print(tf.math.argmax(c))\n", "# Compute the softmax\n", "print(tf.nn.softmax(c))" ] }, { "cell_type": "markdown", "metadata": { "id": "0MNM-q7-MZLz" }, "source": [ "참고: 일반적으로 TensorFlow 함수가 `Tensor`를 입력으로 받을 것을 예상하는 경우 이 함수는 `tf.convert_to_tensor`를 사용하여 `Tensor`로 변환할 수 있는 모든 항목을 허용하게 됩니다." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.208669Z", "iopub.status.busy": "2022-12-14T20:10:23.208255Z", "iopub.status.idle": "2022-12-14T20:10:23.213389Z", "shell.execute_reply": "2022-12-14T20:10:23.212692Z" }, "id": "_wch0N8xNEt-" }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tf.convert_to_tensor([1,2,3])" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.216585Z", "iopub.status.busy": "2022-12-14T20:10:23.216046Z", "iopub.status.idle": "2022-12-14T20:10:23.223471Z", "shell.execute_reply": "2022-12-14T20:10:23.222800Z" }, "id": "ngqIeWYeNJVI" }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tf.reduce_max([1,2,3])" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.226377Z", "iopub.status.busy": "2022-12-14T20:10:23.225842Z", "iopub.status.idle": "2022-12-14T20:10:23.232846Z", "shell.execute_reply": "2022-12-14T20:10:23.232241Z" }, "id": "ThVMxqbVNOq3" }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tf.reduce_max(np.array([1,2,3]))" ] }, { "cell_type": "markdown", "metadata": { "id": "NvSAbowVVuRr" }, "source": [ "## 형상 정보" ] }, { "cell_type": "markdown", "metadata": { "id": "hkaBIqkTCcGY" }, "source": [ "텐서는 형상이 있습니다. 사용되는 일부 용어는 다음과 같습니다.\n", "\n", "- **형상**: 텐서의 각 차원의 길이(요소의 수)\n", "- **순위**: 텐서 축의 수입니다. 스칼라는 순위가 0이고 벡터의 순위는 1이며 행렬의 순위는 2입니다.\n", "- **축** 또는 **차원**: 텐서의 특정 차원\n", "- **크기**: 텐서의 총 항목 수, 형상 벡터 요소의 곱\n" ] }, { "cell_type": "markdown", "metadata": { "id": "E9L3-kCQq2f6" }, "source": [ "참고: \"2차원 텐서\"에 대한 참조가 있을 수 있지만, 순위-2 텐서는 일반적으로 2D 공간을 설명하지 않습니다." ] }, { "cell_type": "markdown", "metadata": { "id": "VFOyG2tn8LhW" }, "source": [ "텐서 및 `tf.TensorShape` 객체에는 다음에 액세스하기 위한 편리한 속성이 있습니다." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.236444Z", "iopub.status.busy": "2022-12-14T20:10:23.235900Z", "iopub.status.idle": "2022-12-14T20:10:23.240790Z", "shell.execute_reply": "2022-12-14T20:10:23.240179Z" }, "id": "RyD3yewUKdnK" }, "outputs": [], "source": [ "rank_4_tensor = tf.zeros([3, 2, 4, 5])" ] }, { "cell_type": "markdown", "metadata": { "id": "oTZZW9ziq4og" }, "source": [ "\n", "\n", " \n", "\n", "\n", " \n", "\n", " \n", "
순위-4 텐서, 형상: [3, 2, 4, 5]
\"A \"A
\n" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.243920Z", "iopub.status.busy": "2022-12-14T20:10:23.243388Z", "iopub.status.idle": "2022-12-14T20:10:23.248400Z", "shell.execute_reply": "2022-12-14T20:10:23.247632Z" }, "id": "MHm9vSqogsBk" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Type of every element: \n", "Number of axes: 4\n", "Shape of tensor: (3, 2, 4, 5)\n", "Elements along axis 0 of tensor: 3\n", "Elements along the last axis of tensor: 5\n", "Total number of elements (3*2*4*5): 120\n" ] } ], "source": [ "print(\"Type of every element:\", rank_4_tensor.dtype)\n", "print(\"Number of axes:\", rank_4_tensor.ndim)\n", "print(\"Shape of tensor:\", rank_4_tensor.shape)\n", "print(\"Elements along axis 0 of tensor:\", rank_4_tensor.shape[0])\n", "print(\"Elements along the last axis of tensor:\", rank_4_tensor.shape[-1])\n", "print(\"Total number of elements (3*2*4*5): \", tf.size(rank_4_tensor).numpy())" ] }, { "cell_type": "markdown", "metadata": { "id": "2ZGZp_JOOPOv" }, "source": [ "하지만 `Tensor.ndim` 및 `Tensor.shape` 속성은 `Tensor` 객체를 반환하지 않음에 유의해야 합니다. `Tensor`가 필요한 경우 `tf.rank` 또는 `tf.shape` 함수를 사용해야 합니다. 이 둘의 차이는 미묘하지만 그래프를 작성할 때 중요할 수 있습니다(나중에)." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.251616Z", "iopub.status.busy": "2022-12-14T20:10:23.251076Z", "iopub.status.idle": "2022-12-14T20:10:23.255195Z", "shell.execute_reply": "2022-12-14T20:10:23.254511Z" }, "id": "Ptq0-y6APCpD" }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tf.rank(rank_4_tensor)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.258297Z", "iopub.status.busy": "2022-12-14T20:10:23.257948Z", "iopub.status.idle": "2022-12-14T20:10:23.262841Z", "shell.execute_reply": "2022-12-14T20:10:23.262202Z" }, "id": "HslrDOEBPICN" }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tf.shape(rank_4_tensor)" ] }, { "cell_type": "markdown", "metadata": { "id": "bQmE_Vx5JilS" }, "source": [ "축은 종종 인덱스로 참조하지만, 항상 각 축의 의미를 추적해야 합니다. 축이 전역에서 로컬로 정렬되는 경우가 종종 있습니다. 배치 축이 먼저 오고 그 다음에 공간 차원과 각 위치의 특성이 마지막에 옵니다. 이러한 방식으로 특성 벡터는 연속적인 메모리 영역입니다.\n", "\n", "\n", "\n", "\n", "\n", "\n", " \n", "\n", "
일반적인 축 순서
\"Keep
" ] }, { "cell_type": "markdown", "metadata": { "id": "FlPoVvJS75Bb" }, "source": [ "## 인덱싱" ] }, { "cell_type": "markdown", "metadata": { "id": "apOkCKqCZIZu" }, "source": [ "### 단일 축 인덱싱\n", "\n", "TensorFlow는 [Python의 목록 또는 문자열 인덱싱](https://docs.python.org/3/tutorial/introduction.html#strings){:.external}과 마찬가지로 표준 Python 인덱싱 규칙과 NumPy 인덱싱의 기본 규칙을 따릅니다.\n", "\n", "- 인덱스는 `0`에서 시작합니다.\n", "- 음수 인덱스는 끝에서부터 거꾸로 계산합니다.\n", "- 콜론, `:`은 `start:stop:step` 슬라이스에 사용됩니다.\n" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.266052Z", "iopub.status.busy": "2022-12-14T20:10:23.265499Z", "iopub.status.idle": "2022-12-14T20:10:23.269460Z", "shell.execute_reply": "2022-12-14T20:10:23.268763Z" }, "id": "SQ-CrJxLXTIM" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 1 1 2 3 5 8 13 21 34]\n" ] } ], "source": [ "rank_1_tensor = tf.constant([0, 1, 1, 2, 3, 5, 8, 13, 21, 34])\n", "print(rank_1_tensor.numpy())" ] }, { "cell_type": "markdown", "metadata": { "id": "mQYYL56PXSak" }, "source": [ "스칼라를 사용하여 인덱싱하면 축이 제거됩니다." ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.272937Z", "iopub.status.busy": "2022-12-14T20:10:23.272418Z", "iopub.status.idle": "2022-12-14T20:10:23.278950Z", "shell.execute_reply": "2022-12-14T20:10:23.278302Z" }, "id": "n6tqHciOWMt5" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "First: 0\n", "Second: 1\n", "Last: 34\n" ] } ], "source": [ "print(\"First:\", rank_1_tensor[0].numpy())\n", "print(\"Second:\", rank_1_tensor[1].numpy())\n", "print(\"Last:\", rank_1_tensor[-1].numpy())" ] }, { "cell_type": "markdown", "metadata": { "id": "qJLHU_a2XwpG" }, "source": [ "`:` 슬라이스를 사용하여 인덱싱하면 축이 유지됩니다." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.281883Z", "iopub.status.busy": "2022-12-14T20:10:23.281440Z", "iopub.status.idle": "2022-12-14T20:10:23.293846Z", "shell.execute_reply": "2022-12-14T20:10:23.293172Z" }, "id": "giVPPcfQX-cu" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Everything: [ 0 1 1 2 3 5 8 13 21 34]\n", "Before 4: [0 1 1 2]\n", "From 4 to the end: [ 3 5 8 13 21 34]\n", "From 2, before 7: [1 2 3 5 8]\n", "Every other item: [ 0 1 3 8 21]\n", "Reversed: [34 21 13 8 5 3 2 1 1 0]\n" ] } ], "source": [ "print(\"Everything:\", rank_1_tensor[:].numpy())\n", "print(\"Before 4:\", rank_1_tensor[:4].numpy())\n", "print(\"From 4 to the end:\", rank_1_tensor[4:].numpy())\n", "print(\"From 2, before 7:\", rank_1_tensor[2:7].numpy())\n", "print(\"Every other item:\", rank_1_tensor[::2].numpy())\n", "print(\"Reversed:\", rank_1_tensor[::-1].numpy())" ] }, { "cell_type": "markdown", "metadata": { "id": "elDSxXi7X-Bh" }, "source": [ "### 다축 인덱싱" ] }, { "cell_type": "markdown", "metadata": { "id": "Cgk0uRUYZiai" }, "source": [ "더 높은 순위의 텐서는 여러 인덱스를 전달하여 인덱싱됩니다.\n", "\n", "단일 축의 경우에서와 정확히 같은 규칙이 각 축에 독립적으로 적용됩니다." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.297060Z", "iopub.status.busy": "2022-12-14T20:10:23.296513Z", "iopub.status.idle": "2022-12-14T20:10:23.300419Z", "shell.execute_reply": "2022-12-14T20:10:23.299653Z" }, "id": "Tc5X_WlsZXmd" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1. 2.]\n", " [3. 4.]\n", " [5. 6.]]\n" ] } ], "source": [ "print(rank_2_tensor.numpy())" ] }, { "cell_type": "markdown", "metadata": { "id": "w07U9vq5ipQk" }, "source": [ "각 인덱스에 정수를 전달하면 결과는 스칼라입니다." ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.303687Z", "iopub.status.busy": "2022-12-14T20:10:23.303162Z", "iopub.status.idle": "2022-12-14T20:10:23.308491Z", "shell.execute_reply": "2022-12-14T20:10:23.307891Z" }, "id": "PvILXc1PjqTM" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4.0\n" ] } ], "source": [ "# Pull out a single value from a 2-rank tensor\n", "print(rank_2_tensor[1, 1].numpy())" ] }, { "cell_type": "markdown", "metadata": { "id": "3RLCzAOHjfEH" }, "source": [ "정수와 슬라이스의 조합을 사용하여 인덱싱할 수 있습니다." ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.311713Z", "iopub.status.busy": "2022-12-14T20:10:23.311177Z", "iopub.status.idle": "2022-12-14T20:10:23.322835Z", "shell.execute_reply": "2022-12-14T20:10:23.322096Z" }, "id": "YTqNqsfJkJP_" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Second row: [3. 4.]\n", "Second column: [2. 4. 6.]\n", "Last row: [5. 6.]\n", "First item in last column: 2.0\n", "Skip the first row:\n", "[[3. 4.]\n", " [5. 6.]] \n", "\n" ] } ], "source": [ "# Get row and column tensors\n", "print(\"Second row:\", rank_2_tensor[1, :].numpy())\n", "print(\"Second column:\", rank_2_tensor[:, 1].numpy())\n", "print(\"Last row:\", rank_2_tensor[-1, :].numpy())\n", "print(\"First item in last column:\", rank_2_tensor[0, -1].numpy())\n", "print(\"Skip the first row:\")\n", "print(rank_2_tensor[1:, :].numpy(), \"\\n\")" ] }, { "cell_type": "markdown", "metadata": { "id": "P45TwSUVSK6G" }, "source": [ "다음은 3축 텐서의 예입니다." ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.325693Z", "iopub.status.busy": "2022-12-14T20:10:23.325256Z", "iopub.status.idle": "2022-12-14T20:10:23.330305Z", "shell.execute_reply": "2022-12-14T20:10:23.329640Z" }, "id": "GuLoMoCVSLxK" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[[ 4 9]\n", " [14 19]\n", " [24 29]], shape=(3, 2), dtype=int32)\n" ] } ], "source": [ "print(rank_3_tensor[:, :, 4])" ] }, { "cell_type": "markdown", "metadata": { "id": "9NgmHq27TJOE" }, "source": [ "\n", "\n", "\n", "\n", "\n", " \n", " \n", "\n", "
배치에서 각 예의 모든 위치에서 마지막 특성 선택하기
\"A \"The
" ] }, { "cell_type": "markdown", "metadata": { "id": "t9V83-thHn89" }, "source": [ "[텐서 슬라이싱 가이드](https://tensorflow.org/guide/tensor_slicing)에서 인덱싱을 적용하여 텐서의 개별 요소를 조작하는 방법을 알아보세요." ] }, { "cell_type": "markdown", "metadata": { "id": "fpr7R0t4SVb0" }, "source": [ "## 형상 조작하기\n", "\n", "텐서의 형상을 바꾸는 것은 매우 유용합니다.\n" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.333618Z", "iopub.status.busy": "2022-12-14T20:10:23.333199Z", "iopub.status.idle": "2022-12-14T20:10:23.337170Z", "shell.execute_reply": "2022-12-14T20:10:23.336494Z" }, "id": "EMeTtga5Wq8j" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(3, 1)\n" ] } ], "source": [ "# Shape returns a `TensorShape` object that shows the size along each axis\n", "x = tf.constant([[1], [2], [3]])\n", "print(x.shape)" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.340244Z", "iopub.status.busy": "2022-12-14T20:10:23.339697Z", "iopub.status.idle": "2022-12-14T20:10:23.343101Z", "shell.execute_reply": "2022-12-14T20:10:23.342402Z" }, "id": "38jc2RXziT3W" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[3, 1]\n" ] } ], "source": [ "# You can convert this object into a Python list, too\n", "print(x.shape.as_list())" ] }, { "cell_type": "markdown", "metadata": { "id": "J_xRlHZMKYnF" }, "source": [ "텐서를 새로운 형상으로 바꿀 수 있습니다. 기본 데이터를 복제할 필요가 없으므로 `tf.reshape` 연산은 빠르고 저렴합니다." ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.346515Z", "iopub.status.busy": "2022-12-14T20:10:23.345989Z", "iopub.status.idle": "2022-12-14T20:10:23.350658Z", "shell.execute_reply": "2022-12-14T20:10:23.350046Z" }, "id": "pa9JCgMLWy87" }, "outputs": [], "source": [ "# You can reshape a tensor to a new shape.\n", "# Note that you're passing in a list\n", "reshaped = tf.reshape(x, [1, 3])" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.353688Z", "iopub.status.busy": "2022-12-14T20:10:23.353162Z", "iopub.status.idle": "2022-12-14T20:10:23.357183Z", "shell.execute_reply": "2022-12-14T20:10:23.356354Z" }, "id": "Mcq7iXOkW3LK" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(3, 1)\n", "(1, 3)\n" ] } ], "source": [ "print(x.shape)\n", "print(reshaped.shape)" ] }, { "cell_type": "markdown", "metadata": { "id": "gIB2tOkoVr6E" }, "source": [ "데이터의 레이아웃은 메모리에서 유지되고 요청된 형상이 같은 데이터를 가리키는 새 텐서가 작성됩니다. TensorFlow는 C 스타일 \"행 중심\" 메모리 순서를 사용합니다. 여기에서 가장 오른쪽에 있는 인덱스를 증가시키면 메모리의 단일 단계에 해당합니다." ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.360248Z", "iopub.status.busy": "2022-12-14T20:10:23.359802Z", "iopub.status.idle": "2022-12-14T20:10:23.363810Z", "shell.execute_reply": "2022-12-14T20:10:23.363092Z" }, "id": "7kMfM0RpUgI8" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[[[ 0 1 2 3 4]\n", " [ 5 6 7 8 9]]\n", "\n", " [[10 11 12 13 14]\n", " [15 16 17 18 19]]\n", "\n", " [[20 21 22 23 24]\n", " [25 26 27 28 29]]], shape=(3, 2, 5), dtype=int32)\n" ] } ], "source": [ "print(rank_3_tensor)" ] }, { "cell_type": "markdown", "metadata": { "id": "TcDtfQkJWzIx" }, "source": [ "텐서를 평평하게 하면 어떤 순서로 메모리에 배치되어 있는지 확인할 수 있습니다." ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.367146Z", "iopub.status.busy": "2022-12-14T20:10:23.366744Z", "iopub.status.idle": "2022-12-14T20:10:23.370679Z", "shell.execute_reply": "2022-12-14T20:10:23.369855Z" }, "id": "COnHEPuaWDQp" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23\n", " 24 25 26 27 28 29], shape=(30,), dtype=int32)\n" ] } ], "source": [ "# A `-1` passed in the `shape` argument says \"Whatever fits\".\n", "print(tf.reshape(rank_3_tensor, [-1]))" ] }, { "cell_type": "markdown", "metadata": { "id": "jJZRira2W--c" }, "source": [ "일반적으로, `tf.reshape`의 합리적인 용도는 인접한 축을 결합하거나 분할하는 것뿐입니다(또는 `1`을 추가/제거).\n", "\n", "이 3x2x5 텐서의 경우, 슬라이스가 혼합되지 않으므로 (3x2)x5 또는 3x (2x5)로 재구성하는 것이 합리적입니다." ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.374237Z", "iopub.status.busy": "2022-12-14T20:10:23.373713Z", "iopub.status.idle": "2022-12-14T20:10:23.378767Z", "shell.execute_reply": "2022-12-14T20:10:23.377989Z" }, "id": "zP2Iqc7zWu_J" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[[ 0 1 2 3 4]\n", " [ 5 6 7 8 9]\n", " [10 11 12 13 14]\n", " [15 16 17 18 19]\n", " [20 21 22 23 24]\n", " [25 26 27 28 29]], shape=(6, 5), dtype=int32) \n", "\n", "tf.Tensor(\n", "[[ 0 1 2 3 4 5 6 7 8 9]\n", " [10 11 12 13 14 15 16 17 18 19]\n", " [20 21 22 23 24 25 26 27 28 29]], shape=(3, 10), dtype=int32)\n" ] } ], "source": [ "print(tf.reshape(rank_3_tensor, [3*2, 5]), \"\\n\")\n", "print(tf.reshape(rank_3_tensor, [3, -1]))" ] }, { "cell_type": "markdown", "metadata": { "id": "6ZsZRUhihlDB" }, "source": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "
몇 가지 좋은 재구성
\"A \"The \"The
\n" ] }, { "cell_type": "markdown", "metadata": { "id": "nOcRxDC3jNIU" }, "source": [ "형상을 변경하면 같은 총 요소 수를 가진 새로운 형상에 대해 \"작동\"하지만, 축의 순서를 고려하지 않으면 별로 쓸모가 없습니다.\n", "\n", "`tf.reshape`에서 축 교환이 작동하지 않으면, `tf.transpose`를 수행해야 합니다.\n" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.382280Z", "iopub.status.busy": "2022-12-14T20:10:23.381714Z", "iopub.status.idle": "2022-12-14T20:10:23.388503Z", "shell.execute_reply": "2022-12-14T20:10:23.387919Z" }, "id": "I9qDL_8u7cBH" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[[[ 0 1 2 3 4]\n", " [ 5 6 7 8 9]\n", " [10 11 12 13 14]]\n", "\n", " [[15 16 17 18 19]\n", " [20 21 22 23 24]\n", " [25 26 27 28 29]]], shape=(2, 3, 5), dtype=int32) \n", "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[[ 0 1 2 3 4 5]\n", " [ 6 7 8 9 10 11]\n", " [12 13 14 15 16 17]\n", " [18 19 20 21 22 23]\n", " [24 25 26 27 28 29]], shape=(5, 6), dtype=int32) \n", "\n", "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]\n" ] } ], "source": [ "# Bad examples: don't do this\n", "\n", "# You can't reorder axes with reshape.\n", "print(tf.reshape(rank_3_tensor, [2, 3, 5]), \"\\n\") \n", "\n", "# This is a mess\n", "print(tf.reshape(rank_3_tensor, [5, 6]), \"\\n\")\n", "\n", "# This doesn't work at all\n", "try:\n", " tf.reshape(rank_3_tensor, [7, -1])\n", "except Exception as e:\n", " print(f\"{type(e).__name__}: {e}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "qTM9-5eh68oo" }, "source": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "
몇 가지 잘못된 재구성
\"You \"Anything \"The
" ] }, { "cell_type": "markdown", "metadata": { "id": "N9r90BvHCbTt" }, "source": [ "완전히 지정되지 않은 형상 전체에 걸쳐 실행할 수 있습니다. 형상에 `None`(축 길이를 알 수 없음)이 포함되거나 전체 형상이 `None`(텐서의 순위를 알 수 없음)입니다.\n", "\n", "[tf.RaggedTensor](#ragged_tensors)를 제외하고 이러한 형상은 TensorFlow의 상징적인 그래프 빌딩 API 컨텍스트에서만 발생합니다.\n", "\n", "- tf.function\n", "- keras 함수형 API\n" ] }, { "cell_type": "markdown", "metadata": { "id": "fDmFtFM7k0R2" }, "source": [ "## `DTypes`에 대한 추가 정보\n", "\n", "`tf.Tensor`의 데이터 유형을 검사하려면, `Tensor.dtype` 속성을 사용합니다.\n", "\n", "Python 객체에서 `tf.Tensor`를 만들 때 선택적으로 데이터 유형을 지정할 수 있습니다.\n", "\n", "그렇지 않으면, TensorFlow는 데이터를 나타낼 수 있는 데이터 유형을 선택합니다. TensorFlow는 Python 정수를 `tf.int32`로, 파이썬 부동 소수점 숫자를 `tf.float32`로 변환합니다. 그렇지 않으면, TensorFlow는 NumPy가 배열로 변환할 때 사용하는 것과 같은 규칙을 사용합니다.\n", "\n", "유형별로 캐스팅할 수 있습니다." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.391850Z", "iopub.status.busy": "2022-12-14T20:10:23.391411Z", "iopub.status.idle": "2022-12-14T20:10:23.398905Z", "shell.execute_reply": "2022-12-14T20:10:23.398198Z" }, "id": "5mSTDWbelUvu" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor([2 3 4], shape=(3,), dtype=uint8)\n" ] } ], "source": [ "the_f64_tensor = tf.constant([2.2, 3.3, 4.4], dtype=tf.float64)\n", "the_f16_tensor = tf.cast(the_f64_tensor, dtype=tf.float16)\n", "# Now, cast to an uint8 and lose the decimal precision\n", "the_u8_tensor = tf.cast(the_f16_tensor, dtype=tf.uint8)\n", "print(the_u8_tensor)" ] }, { "cell_type": "markdown", "metadata": { "id": "s1yBlJsVlFSu" }, "source": [ "## 브로드캐스팅\n", "\n", "브로드캐스팅은 [NumPy의 해당 특성](https://numpy.org/doc/stable/user/basics.broadcasting.html){:.external}에서 빌린 개념입니다. 요컨대, 특정 조건에서 작은 텐서는 결합된 연산을 실행할 때 더 큰 텐서에 맞게 자동으로 \"확장(streched)\"됩니다.\n", "\n", "가장 간단하고 가장 일반적인 경우는 스칼라에 텐서를 곱하거나 추가하려고 할 때입니다. 이 경우, 스칼라는 다른 인수와 같은 형상으로 브로드캐스트됩니다. " ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.401934Z", "iopub.status.busy": "2022-12-14T20:10:23.401702Z", "iopub.status.idle": "2022-12-14T20:10:23.407141Z", "shell.execute_reply": "2022-12-14T20:10:23.406448Z" }, "id": "P8sypqmagHQN" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor([2 4 6], shape=(3,), dtype=int32)\n", "tf.Tensor([2 4 6], shape=(3,), dtype=int32)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor([2 4 6], shape=(3,), dtype=int32)\n" ] } ], "source": [ "x = tf.constant([1, 2, 3])\n", "\n", "y = tf.constant(2)\n", "z = tf.constant([2, 2, 2])\n", "# All of these are the same computation\n", "print(tf.multiply(x, 2))\n", "print(x * y)\n", "print(x * z)" ] }, { "cell_type": "markdown", "metadata": { "id": "o0SBoR6voWcb" }, "source": [ "마찬가지로, 크기가 1인 축은 다른 인수와 일치하도록 확장할 수 있습니다. 두 인수 모두 같은 계산으로 확장할 수 있습니다.\n", "\n", "이 경우, 3x1 행렬에 요소별로 1x4 행렬을 곱하여 3x4 행렬을 만듭니다. 선행 1이 선택 사항인 점에 유의하세요. y의 형상은 `[4]`입니다." ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.411329Z", "iopub.status.busy": "2022-12-14T20:10:23.410834Z", "iopub.status.idle": "2022-12-14T20:10:23.415977Z", "shell.execute_reply": "2022-12-14T20:10:23.415355Z" }, "id": "6sGmkPg3XANr" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[[1]\n", " [2]\n", " [3]], shape=(3, 1), dtype=int32) \n", "\n", "tf.Tensor([1 2 3 4], shape=(4,), dtype=int32) \n", "\n", "tf.Tensor(\n", "[[ 1 2 3 4]\n", " [ 2 4 6 8]\n", " [ 3 6 9 12]], shape=(3, 4), dtype=int32)\n" ] } ], "source": [ "# These are the same computations\n", "x = tf.reshape(x,[3,1])\n", "y = tf.range(1, 5)\n", "print(x, \"\\n\")\n", "print(y, \"\\n\")\n", "print(tf.multiply(x, y))" ] }, { "cell_type": "markdown", "metadata": { "id": "t_7sh-EUYLrE" }, "source": [ "\n", "\n", " \n", "\n", "\n", " \n", "\n", "
추가 시 브로드캐스팅: [1, 4][3, 1]의 곱하기는 [3,4]입니다.
\"Adding
\n" ] }, { "cell_type": "markdown", "metadata": { "id": "9V3KgSJcKDRz" }, "source": [ "브로드캐스팅이 없는 같은 연산이 여기 있습니다." ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.418954Z", "iopub.status.busy": "2022-12-14T20:10:23.418438Z", "iopub.status.idle": "2022-12-14T20:10:23.423518Z", "shell.execute_reply": "2022-12-14T20:10:23.422801Z" }, "id": "elrF6v63igY8" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[[ 1 2 3 4]\n", " [ 2 4 6 8]\n", " [ 3 6 9 12]], shape=(3, 4), dtype=int32)\n" ] } ], "source": [ "x_stretch = tf.constant([[1, 1, 1, 1],\n", " [2, 2, 2, 2],\n", " [3, 3, 3, 3]])\n", "\n", "y_stretch = tf.constant([[1, 2, 3, 4],\n", " [1, 2, 3, 4],\n", " [1, 2, 3, 4]])\n", "\n", "print(x_stretch * y_stretch) # Again, operator overloading" ] }, { "cell_type": "markdown", "metadata": { "id": "14KobqYu85gi" }, "source": [ "대부분의 경우 브로드캐스팅은 브로드캐스트 연산으로 메모리에서 확장된 텐서를 구체화하지 않으므로 시간과 공간 효율적입니다.\n", "\n", "`tf.broadcast_to`를 사용하여 브로드캐스팅이 어떤 모습인지 알 수 있습니다." ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.426701Z", "iopub.status.busy": "2022-12-14T20:10:23.426198Z", "iopub.status.idle": "2022-12-14T20:10:23.431188Z", "shell.execute_reply": "2022-12-14T20:10:23.430466Z" }, "id": "GW2Q59_r8hZ6" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(\n", "[[1 2 3]\n", " [1 2 3]\n", " [1 2 3]], shape=(3, 3), dtype=int32)\n" ] } ], "source": [ "print(tf.broadcast_to(tf.constant([1, 2, 3]), [3, 3]))" ] }, { "cell_type": "markdown", "metadata": { "id": "Z2bAMMQY-jpP" }, "source": [ "예를 들어, `broadcast_to`는 수학적인 op와 달리 메모리를 절약하기 위해 특별한 연산을 수행하지 않습니다. 여기에서 텐서를 구체화합니다.\n", "\n", "훨씬 더 복잡해질 수 있습니다. Jake VanderPlas의 저서 Python Data Science Handbook해당 섹션{:.external}에 더 많은 브로드캐스팅 트릭이 소개되어 있습니다(이번에도 NumPy에서)." ] }, { "cell_type": "markdown", "metadata": { "id": "o4Rpz0xAsKSI" }, "source": [ "## tf.convert_to_tensor\n", "\n", "`tf.matmul` 및 `tf.reshape`와 같은 대부분의 ops는 클래스 `tf.Tensor`의 인수를 사용합니다. 그러나 위의 경우, 텐서 형상의 Python 객체가 수용됨을 알 수 있습니다.\n", "\n", "전부는 아니지만 대부분의 ops는 텐서가 아닌 인수에 대해 `convert_to_tensor`를 호출합니다. 변환 레지스트리가 있어 NumPy의 `ndarray`, `TensorShape` , Python 목록 및 `tf.Variable`과 같은 대부분의 객체 클래스는 모두 자동으로 변환됩니다.\n", "\n", "자세한 내용은 `tf.register_tensor_conversion_function`을 참조하세요. 자신만의 유형이 있으면 자동으로 텐서로 변환할 수 있습니다." ] }, { "cell_type": "markdown", "metadata": { "id": "05bBVBVYV0y6" }, "source": [ "## 비정형 텐서\n", "\n", "어떤 축을 따라 다양한 수의 요소를 가진 텐서를 \"비정형(ragged)\"이라고 합니다. 비정형 데이터에는 `tf.ragged.RaggedTensor`를 사용합니다.\n", "\n", "예를 들어, 비정형 텐서는 정규 텐서로 표현할 수 없습니다." ] }, { "cell_type": "markdown", "metadata": { "id": "VPc3jGoeJqB7" }, "source": [ "\n", "\n", " \n", "\n", "\n", " \n", "\n", "
`tf.RaggedTensor`, 형상: [4, None]
\"A
" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.434768Z", "iopub.status.busy": "2022-12-14T20:10:23.434211Z", "iopub.status.idle": "2022-12-14T20:10:23.437383Z", "shell.execute_reply": "2022-12-14T20:10:23.436688Z" }, "id": "VsbTjoFfNVBF" }, "outputs": [], "source": [ "ragged_list = [\n", " [0, 1, 2, 3],\n", " [4, 5],\n", " [6, 7, 8],\n", " [9]]" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.440470Z", "iopub.status.busy": "2022-12-14T20:10:23.439980Z", "iopub.status.idle": "2022-12-14T20:10:23.444093Z", "shell.execute_reply": "2022-12-14T20:10:23.443318Z" }, "id": "p4xKTo57tutG" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ValueError: Can't convert non-rectangular Python sequence to Tensor.\n" ] } ], "source": [ "try:\n", " tensor = tf.constant(ragged_list)\n", "except Exception as e:\n", " print(f\"{type(e).__name__}: {e}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "0cm9KuEeMLGI" }, "source": [ "대신 `tf.ragged.constant`를 사용하여 `tf.RaggedTensor`를 작성합니다." ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.447492Z", "iopub.status.busy": "2022-12-14T20:10:23.447090Z", "iopub.status.idle": "2022-12-14T20:10:23.452153Z", "shell.execute_reply": "2022-12-14T20:10:23.451433Z" }, "id": "XhF3QV3jiqTj" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "ragged_tensor = tf.ragged.constant(ragged_list)\n", "print(ragged_tensor)" ] }, { "cell_type": "markdown", "metadata": { "id": "sFgHduHVNoIE" }, "source": [ "`tf.RaggedTensor`의 형상에는 알 수 없는 길이의 일부 축이 포함됩니다." ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.455322Z", "iopub.status.busy": "2022-12-14T20:10:23.454895Z", "iopub.status.idle": "2022-12-14T20:10:23.458437Z", "shell.execute_reply": "2022-12-14T20:10:23.457745Z" }, "id": "Eo_3wJUWNgqB" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(4, None)\n" ] } ], "source": [ "print(ragged_tensor.shape)" ] }, { "cell_type": "markdown", "metadata": { "id": "V9njclVkkN7G" }, "source": [ "## 문자열 텐서\n", "\n", "`tf.string`은 `dtype`이며, 텐서에서 문자열(가변 길이의 바이트 배열)과 같은 데이터를 나타낼 수 있습니다.\n", "\n", "문자열은 원자성이므로 Python 문자열과 같은 방식으로 인덱싱할 수 없습니다. 문자열의 길이는 텐서의 축 중의 하나가 아닙니다. 문자열을 조작하는 함수에 대해서는 `tf.strings`를 참조하세요." ] }, { "cell_type": "markdown", "metadata": { "id": "5P_8spEGQ0wp" }, "source": [ "다음은 스칼라 문자열 텐서입니다." ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.461639Z", "iopub.status.busy": "2022-12-14T20:10:23.461237Z", "iopub.status.idle": "2022-12-14T20:10:23.465963Z", "shell.execute_reply": "2022-12-14T20:10:23.465210Z" }, "id": "sBosmM8MkIh4" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(b'Gray wolf', shape=(), dtype=string)\n" ] } ], "source": [ "# Tensors can be strings, too here is a scalar string.\n", "scalar_string_tensor = tf.constant(\"Gray wolf\")\n", "print(scalar_string_tensor)" ] }, { "cell_type": "markdown", "metadata": { "id": "CMFBSl1FQ3vE" }, "source": [ "문자열의 벡터는 다음과 같습니다." ] }, { "cell_type": "markdown", "metadata": { "id": "IO-c3Tq3RC1L" }, "source": [ "\n", "\n", " \n", "\n", "\n", " \n", "\n", "
문자열의 벡터, 형상: [3,]
\"The
" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.469206Z", "iopub.status.busy": "2022-12-14T20:10:23.468848Z", "iopub.status.idle": "2022-12-14T20:10:23.472771Z", "shell.execute_reply": "2022-12-14T20:10:23.472076Z" }, "id": "41Dv2kL9QrtO" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor([b'Gray wolf' b'Quick brown fox' b'Lazy dog'], shape=(3,), dtype=string)\n" ] } ], "source": [ "# If you have three string tensors of different lengths, this is OK.\n", "tensor_of_strings = tf.constant([\"Gray wolf\",\n", " \"Quick brown fox\",\n", " \"Lazy dog\"])\n", "# Note that the shape is (3,). The string length is not included.\n", "print(tensor_of_strings)" ] }, { "cell_type": "markdown", "metadata": { "id": "76gQ9qrgSMzS" }, "source": [ "위의 출력에서 `b` 접두사는 `tf.string` dtype이 유니코드 문자열이 아니라 바이트 문자열임을 나타냅니다. TensorFlow에서 유니코드 텍스트를 처리하는 자세한 내용은 [유니코드 튜토리얼](https://www.tensorflow.org/tutorials/load_data/unicode)을 참조하세요." ] }, { "cell_type": "markdown", "metadata": { "id": "ClSBPK-lZBQp" }, "source": [ "유니코드 문자를 전달하면 UTF-8로 인코딩됩니다." ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.476316Z", "iopub.status.busy": "2022-12-14T20:10:23.475824Z", "iopub.status.idle": "2022-12-14T20:10:23.480129Z", "shell.execute_reply": "2022-12-14T20:10:23.479349Z" }, "id": "GTgL53jxSMd9" }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tf.constant(\"🥳👍\")" ] }, { "cell_type": "markdown", "metadata": { "id": "Ir9cY42MMAei" }, "source": [ "문자열이 있는 일부 기본 함수는 `tf.strings`을 포함하여 `tf.strings.split`에서 찾을 수 있습니다." ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.483416Z", "iopub.status.busy": "2022-12-14T20:10:23.482966Z", "iopub.status.idle": "2022-12-14T20:10:23.515216Z", "shell.execute_reply": "2022-12-14T20:10:23.514424Z" }, "id": "8k2K0VTFyj8e" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor([b'Gray' b'wolf'], shape=(2,), dtype=string)\n" ] } ], "source": [ "# You can use split to split a string into a set of tensors\n", "print(tf.strings.split(scalar_string_tensor, sep=\" \"))" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.518301Z", "iopub.status.busy": "2022-12-14T20:10:23.517874Z", "iopub.status.idle": "2022-12-14T20:10:23.526321Z", "shell.execute_reply": "2022-12-14T20:10:23.525716Z" }, "id": "zgGAn1dfR-04" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "# ...but it turns into a `RaggedTensor` if you split up a tensor of strings,\n", "# as each string might be split into a different number of parts.\n", "print(tf.strings.split(tensor_of_strings))" ] }, { "cell_type": "markdown", "metadata": { "id": "HsAn1kPeO84m" }, "source": [ "\n", "\n", " \n", "\n", "\n", " \n", "\n", "
세 개의 분할된 문자열, 형상: [3, None]
\"Splitting
" ] }, { "cell_type": "markdown", "metadata": { "id": "st9OxrUxWSKY" }, "source": [ "`tf.string.to_number`:" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.529565Z", "iopub.status.busy": "2022-12-14T20:10:23.529058Z", "iopub.status.idle": "2022-12-14T20:10:23.540472Z", "shell.execute_reply": "2022-12-14T20:10:23.539740Z" }, "id": "3nRtx3X9WRfN" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor([ 1. 10. 100.], shape=(3,), dtype=float32)\n" ] } ], "source": [ "text = tf.constant(\"1 10 100\")\n", "print(tf.strings.to_number(tf.strings.split(text, \" \")))" ] }, { "cell_type": "markdown", "metadata": { "id": "r2EZtBbJBns4" }, "source": [ "`tf.cast`를 사용하여 문자열 텐서를 숫자로 변환할 수는 없지만, 바이트로 변환한 다음 숫자로 변환할 수 있습니다." ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.543539Z", "iopub.status.busy": "2022-12-14T20:10:23.543060Z", "iopub.status.idle": "2022-12-14T20:10:23.555225Z", "shell.execute_reply": "2022-12-14T20:10:23.554465Z" }, "id": "fo8BjmH7gyTj" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Byte strings: tf.Tensor([b'D' b'u' b'c' b'k'], shape=(4,), dtype=string)\n", "Bytes: tf.Tensor([ 68 117 99 107], shape=(4,), dtype=uint8)\n" ] } ], "source": [ "byte_strings = tf.strings.bytes_split(tf.constant(\"Duck\"))\n", "byte_ints = tf.io.decode_raw(tf.constant(\"Duck\"), tf.uint8)\n", "print(\"Byte strings:\", byte_strings)\n", "print(\"Bytes:\", byte_ints)" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.558359Z", "iopub.status.busy": "2022-12-14T20:10:23.557838Z", "iopub.status.idle": "2022-12-14T20:10:23.573161Z", "shell.execute_reply": "2022-12-14T20:10:23.572475Z" }, "id": "uSQnZ7d1jCSQ" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Unicode bytes: tf.Tensor(b'\\xe3\\x82\\xa2\\xe3\\x83\\x92\\xe3\\x83\\xab \\xf0\\x9f\\xa6\\x86', shape=(), dtype=string)\n", "\n", "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)\n", "\n", "Unicode values: tf.Tensor([ 12450 12498 12523 32 129414], shape=(5,), dtype=int32)\n" ] } ], "source": [ "# Or split it up as unicode and then decode it\n", "unicode_bytes = tf.constant(\"アヒル 🦆\")\n", "unicode_char_bytes = tf.strings.unicode_split(unicode_bytes, \"UTF-8\")\n", "unicode_values = tf.strings.unicode_decode(unicode_bytes, \"UTF-8\")\n", "\n", "print(\"\\nUnicode bytes:\", unicode_bytes)\n", "print(\"\\nUnicode chars:\", unicode_char_bytes)\n", "print(\"\\nUnicode values:\", unicode_values)" ] }, { "cell_type": "markdown", "metadata": { "id": "fE7nKJ2YW3aY" }, "source": [ "`tf.string` dtype은 TensorFlow의 모든 원시 바이트 데이터에 사용됩니다. `tf.io` 모듈에는 이미지 디코딩 및 csv 구문 분석을 포함하여 데이터를 바이트로 변환하거나 바이트에서 변환하는 함수가 포함되어 있습니다." ] }, { "cell_type": "markdown", "metadata": { "id": "ua8BnAzxkRKV" }, "source": [ "## 희소 텐서\n", "\n", "때로는 매우 넓은 임베드 공간과 같이 데이터가 희소합니다. TensorFlow는 `tf.sparse.SparseTensor` 및 관련 연산을 지원하여 희소 데이터를 효율적으로 저장합니다." ] }, { "cell_type": "markdown", "metadata": { "id": "mS5zgqgUTPRb" }, "source": [ "\n", "\n", " \n", "\n", "\n", " \n", "\n", "
`tf.SparseTensor`, 형상: [3, 4]
\"An
" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "execution": { "iopub.execute_input": "2022-12-14T20:10:23.576703Z", "iopub.status.busy": "2022-12-14T20:10:23.576103Z", "iopub.status.idle": "2022-12-14T20:10:23.585153Z", "shell.execute_reply": "2022-12-14T20:10:23.584370Z" }, "id": "B9nbO1E2kSUN" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SparseTensor(indices=tf.Tensor(\n", "[[0 0]\n", " [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)) \n", "\n", "tf.Tensor(\n", "[[1 0 0 0]\n", " [0 0 2 0]\n", " [0 0 0 0]], shape=(3, 4), dtype=int32)\n" ] } ], "source": [ "# Sparse tensors store values by index in a memory-efficient manner\n", "sparse_tensor = tf.sparse.SparseTensor(indices=[[0, 0], [1, 2]],\n", " values=[1, 2],\n", " dense_shape=[3, 4])\n", "print(sparse_tensor, \"\\n\")\n", "\n", "# You can convert sparse tensors to dense\n", "print(tf.sparse.to_dense(sparse_tensor))" ] } ], "metadata": { "colab": { "collapsed_sections": [ "Tce3stUlHN0L" ], "name": "tensor.ipynb", "toc_visible": true }, "kernelspec": { "display_name": "Python 3", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.16" } }, "nbformat": 4, "nbformat_minor": 0 }