{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "ISubpr_SSsiM" }, "source": [ "##### Copyright 2020 The TensorFlow Authors.\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "cellView": "form", "execution": { "iopub.execute_input": "2022-12-14T21:05:24.200190Z", "iopub.status.busy": "2022-12-14T21:05:24.199983Z", "iopub.status.idle": "2022-12-14T21:05:24.203658Z", "shell.execute_reply": "2022-12-14T21:05:24.203149Z" }, "id": "3jTMb1dySr3V" }, "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": "6DWfyNThSziV" }, "source": [ "# 모듈, 레이어 및 모델 소개\n", "\n", "
![]() | \n",
" ![]() | \n",
" ![]() | \n",
" ![]() | \n",
"
tf.Graph
를 설명하는 프로토콜 버퍼입니다.\n",
"\n",
"모델과 레이어는 실제로 이 표현을 생성한 클래스의 인스턴스를 만들지 않고도 이 표현에서 로드할 수 있습니다. 이는 대규모 또는 에지 기기에서 제공하는 것과 같이 Python 인터프리터가 없거나 또는 원하지 않는 상황 또는 원래 Python 코드를 사용할 수 없거나 사용하는 것이 실용적이지 않은 상황에서 바람직합니다.\n",
"\n",
"모델을 새 객체로 로드할 수 있습니다."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T21:05:31.527325Z",
"iopub.status.busy": "2022-12-14T21:05:31.527066Z",
"iopub.status.idle": "2022-12-14T21:05:31.565570Z",
"shell.execute_reply": "2022-12-14T21:05:31.564954Z"
},
"id": "zRFcA5wIefv4"
},
"outputs": [],
"source": [
"new_model = tf.saved_model.load(\"the_saved_model\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "-9EF3mT7i3qN"
},
"source": [
"저장된 모델을 로드하여 생성된 `new_model`은 클래스 지식이 없는 내부 TensorFlow 사용자 객체입니다. `SequentialModule` 유형이 아닙니다."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T21:05:31.568943Z",
"iopub.status.busy": "2022-12-14T21:05:31.568352Z",
"iopub.status.idle": "2022-12-14T21:05:31.572599Z",
"shell.execute_reply": "2022-12-14T21:05:31.572055Z"
},
"id": "EC_eQj7yi54G"
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"isinstance(new_model, SequentialModule)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "-OrOX1zxiyhR"
},
"source": [
"이 새 모델은 이미 정의된 입력 서명에서 동작합니다. 이와 같이 복원된 모델에 더 많은 서명을 추가할 수 없습니다."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T21:05:31.575569Z",
"iopub.status.busy": "2022-12-14T21:05:31.575022Z",
"iopub.status.idle": "2022-12-14T21:05:31.582175Z",
"shell.execute_reply": "2022-12-14T21:05:31.581616Z"
},
"id": "_23BYYBWfKnc"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tf.Tensor([[0. 5.7581444]], shape=(1, 2), dtype=float32)\n",
"tf.Tensor(\n",
"[[[0. 5.7581444]\n",
" [0. 5.7581444]]], shape=(1, 2, 2), dtype=float32)\n"
]
}
],
"source": [
"print(my_model([[2.0, 2.0, 2.0]]))\n",
"print(my_model([[[2.0, 2.0, 2.0], [2.0, 2.0, 2.0]]]))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "qSFhoMtTjSR6"
},
"source": [
"따라서, `SavedModel`을 사용하면 `tf.Module`을 사용하여 TensorFlow 가중치와 그래프를 저장한 다음 다시 로드할 수 있습니다."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Rb9IdN7hlUZK"
},
"source": [
"## Keras 모델 및 레이어\n",
"\n",
"이 시점까지 Keras에 대한 언급이 없습니다. `tf.Module` 위에 고유한 상위 수준 API를 빌드할 수 있습니다.\n",
"\n",
"이 섹션에서는 Keras가 `tf.Module`을 사용하는 방법을 살펴봅니다. Keras 모델에 대한 전체 사용자 가이드는 [Keras 가이드](https://www.tensorflow.org/guide/keras/sequential_model)에서 찾을 수 있습니다.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "uigsVGPreE-D"
},
"source": [
"### Keras 레이어\n",
"\n",
"`tf.keras.layers.Layer`는 모든 Keras 레이어의 기본 클래스이며 `tf.Module`에서 상속합니다.\n",
"\n",
"부모를 교체한 다음 `__call__`을 `call`로 변경하여 모듈을 Keras 레이어로 변환할 수 있습니다."
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T21:05:31.585441Z",
"iopub.status.busy": "2022-12-14T21:05:31.584867Z",
"iopub.status.idle": "2022-12-14T21:05:31.594364Z",
"shell.execute_reply": "2022-12-14T21:05:31.593798Z"
},
"id": "88YOGquhnQRd"
},
"outputs": [],
"source": [
"class MyDense(tf.keras.layers.Layer):\n",
" # Adding **kwargs to support base Keras layer arguments\n",
" def __init__(self, in_features, out_features, **kwargs):\n",
" super().__init__(**kwargs)\n",
"\n",
" # This will soon move to the build step; see below\n",
" self.w = tf.Variable(\n",
" tf.random.normal([in_features, out_features]), name='w')\n",
" self.b = tf.Variable(tf.zeros([out_features]), name='b')\n",
" def call(self, x):\n",
" y = tf.matmul(x, self.w) + self.b\n",
" return tf.nn.relu(y)\n",
"\n",
"simple_layer = MyDense(name=\"simple\", in_features=3, out_features=3)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "nYGmAsPrws--"
},
"source": [
"Keras 레이어에는 다음 섹션에서 설명하는 몇 가지 부기(bookkeeping)를 수행한 다음 `call()`을 호출하는 고유한 `__call__`이 있습니다. 기능에 변화가 없는 것을 알 수 있습니다."
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T21:05:31.597108Z",
"iopub.status.busy": "2022-12-14T21:05:31.596852Z",
"iopub.status.idle": "2022-12-14T21:05:31.604948Z",
"shell.execute_reply": "2022-12-14T21:05:31.604361Z"
},
"id": "nIqE8wOznYKG"
},
"outputs": [
{
"data": {
"text/plain": [
"