{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "g_nWetWWd_ns" }, "source": [ "##### Copyright 2019 The TensorFlow Authors." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "cellView": "form", "execution": { "iopub.execute_input": "2022-12-14T20:23:00.927464Z", "iopub.status.busy": "2022-12-14T20:23:00.927011Z", "iopub.status.idle": "2022-12-14T20:23:00.931196Z", "shell.execute_reply": "2022-12-14T20:23:00.930537Z" }, "id": "2pHVBk_seED1" }, "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": "code", "execution_count": 2, "metadata": { "cellView": "form", "execution": { "iopub.execute_input": "2022-12-14T20:23:00.934781Z", "iopub.status.busy": "2022-12-14T20:23:00.934239Z", "iopub.status.idle": "2022-12-14T20:23:00.937687Z", "shell.execute_reply": "2022-12-14T20:23:00.937101Z" }, "id": "N_fMsQ-N8I7j" }, "outputs": [], "source": [ "#@title MIT License\n", "#\n", "# Copyright (c) 2017 François Chollet\n", "#\n", "# Permission is hereby granted, free of charge, to any person obtaining a\n", "# copy of this software and associated documentation files (the \"Software\"),\n", "# to deal in the Software without restriction, including without limitation\n", "# the rights to use, copy, modify, merge, publish, distribute, sublicense,\n", "# and/or sell copies of the Software, and to permit persons to whom the\n", "# Software is furnished to do so, subject to the following conditions:\n", "#\n", "# The above copyright notice and this permission notice shall be included in\n", "# all copies or substantial portions of the Software.\n", "#\n", "# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", "# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", "# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n", "# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", "# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n", "# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n", "# DEALINGS IN THE SOFTWARE." ] }, { "cell_type": "markdown", "metadata": { "id": "pZJ3uY9O17VN" }, "source": [ "# 모델 저장과 복원" ] }, { "cell_type": "markdown", "metadata": { "id": "M4Ata7_wMul1" }, "source": [ "
![]() | \n",
" ![]() | \n",
" ![]() | \n",
" ![]() | \n",
"
.ckpt
확장자가 있는 TensorFlow 체크포인트 형식을 사용합니다. `.h5` 확장자를 사용하여 HDF5 형식으로 저장하려면 [모델 저장 및 로드](https://www.tensorflow.org/guide/keras/save_and_serialize) 가이드를 참조하세요."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T20:23:21.561533Z",
"iopub.status.busy": "2022-12-14T20:23:21.560963Z",
"iopub.status.idle": "2022-12-14T20:23:21.824898Z",
"shell.execute_reply": "2022-12-14T20:23:21.824117Z"
},
"id": "R7W5plyZ-u9X"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"32/32 - 0s - loss: 0.4952 - sparse_categorical_accuracy: 0.8790 - 166ms/epoch - 5ms/step\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Restored model, accuracy: 87.90%\n"
]
}
],
"source": [
"# Save the weights\n",
"model.save_weights('./checkpoints/my_checkpoint')\n",
"\n",
"# Create a new model instance\n",
"model = create_model()\n",
"\n",
"# Restore the weights\n",
"model.load_weights('./checkpoints/my_checkpoint')\n",
"\n",
"# Evaluate the model\n",
"loss, acc = model.evaluate(test_images, test_labels, verbose=2)\n",
"print(\"Restored model, accuracy: {:5.2f}%\".format(100 * acc))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kOGlxPRBEvV1"
},
"source": [
"## 전체 모델 저장하기\n",
"\n",
"`tf.keras.Model.save`를 호출하여 단일 `file/folder`에 모델의 아키텍처, 가중치 및 훈련 구성을 저장합니다. 이렇게 하면 원본 Python 코드에 액세스하지 않고도 사용할 수 있도록 모델을 내보낼 수 있습니다.* 옵티마이저 상태가 복구되므로 중단했던 지점부터 훈련을 재개할 수 있습니다.\n",
"\n",
"전체 모델은 두 가지 다른 파일 형식(`SavedModel` 및 `HDF5`)으로 저장할 수 있습니다. TensorFlow `SavedModel` 형식은 TF2.x의 기본 파일 형식입니다. 그러나 모델을 `HDF5` 형식으로 저장할 수 있습니다. 전체 모델을 두 가지 파일 형식으로 저장하는 방법에 대한 자세한 내용은 아래에 설명되어 있습니다.\n",
"\n",
"완전한 기능의 모델을 저장하는 것은 매우 유용합니다. 즉, TensorFlow.js([저장된 모델](https://www.tensorflow.org/js/tutorials/conversion/import_saved_model), [HDF5](https://www.tensorflow.org/js/tutorials/conversion/import_keras))에서 로드한 다음 웹 브라우저에서 훈련 및 실행하거나 TensorFlow Lite([저장된 모델](https://www.tensorflow.org/lite/models/convert/#convert_a_savedmodel_recommended_), [HDF5](https://www.tensorflow.org/lite/models/convert/#convert_a_keras_model_))를 사용하여 모바일 장치에서 실행되도록 변환할 수 있습니다.\n",
"\n",
"*사용자 정의 객체(예: 하위 클래싱된 모델 또는 레이어)는 저장 및 로드할 때 특별한 주의가 필요합니다. 아래의 **사용자 정의 객체 저장하기** 섹션을 참조하세요."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kPyhgcoVzqUB"
},
"source": [
"### SavedModel 포맷"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "LtcN4VIb7JkK"
},
"source": [
"SavedModel 형식은 모델을 직렬화하는 또 다른 방법입니다. 이 형식으로 저장된 모델은 `tf.keras.models.load_model`을 사용하여 복원할 수 있으며 TensorFlow Serving과 호환됩니다. [SavedModel 가이드](../../guide/saved_model.ipynb)에 SavedModel을 제공/검사하는 방법이 자세히 설명되어 있습니다. 아래 섹션은 모델을 저장하고 복원하는 단계를 보여줍니다."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T20:23:21.829042Z",
"iopub.status.busy": "2022-12-14T20:23:21.828434Z",
"iopub.status.idle": "2022-12-14T20:23:23.898642Z",
"shell.execute_reply": "2022-12-14T20:23:23.897753Z"
},
"id": "sI1YvCDFzpl3"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:Detecting that an object or model or tf.train.Checkpoint is being deleted with unrestored values. See the following logs for the specific values in question. To silence these warnings, use `status.expect_partial()`. See https://www.tensorflow.org/api_docs/python/tf/train/Checkpoint#restorefor details about the status object returned by the restore function.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.1\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.2\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.3\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.4\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.5\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.6\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.7\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING:tensorflow:Value in checkpoint could not be found in the restored object: (root).optimizer._variables.8\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/5\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\r",
" 1/32 [..............................] - ETA: 23s - loss: 2.4248 - sparse_categorical_accuracy: 0.0938"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"23/32 [====================>.........] - ETA: 0s - loss: 1.3202 - sparse_categorical_accuracy: 0.6440 "
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"32/32 [==============================] - 1s 2ms/step - loss: 1.1550 - sparse_categorical_accuracy: 0.6920\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 2/5\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\r",
" 1/32 [..............................] - ETA: 0s - loss: 0.4617 - sparse_categorical_accuracy: 0.8750"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"24/32 [=====================>........] - ETA: 0s - loss: 0.4221 - sparse_categorical_accuracy: 0.8906"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"32/32 [==============================] - 0s 2ms/step - loss: 0.4072 - sparse_categorical_accuracy: 0.8950\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 3/5\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\r",
" 1/32 [..............................] - ETA: 0s - loss: 0.4280 - sparse_categorical_accuracy: 0.9062"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"24/32 [=====================>........] - ETA: 0s - loss: 0.3102 - sparse_categorical_accuracy: 0.9245"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"32/32 [==============================] - 0s 2ms/step - loss: 0.2911 - sparse_categorical_accuracy: 0.9220\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 4/5\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\r",
" 1/32 [..............................] - ETA: 0s - loss: 0.2092 - sparse_categorical_accuracy: 0.9375"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"22/32 [===================>..........] - ETA: 0s - loss: 0.2035 - sparse_categorical_accuracy: 0.9574"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"32/32 [==============================] - 0s 2ms/step - loss: 0.1990 - sparse_categorical_accuracy: 0.9580\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 5/5\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\r",
" 1/32 [..............................] - ETA: 0s - loss: 0.2438 - sparse_categorical_accuracy: 0.9375"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"23/32 [====================>.........] - ETA: 0s - loss: 0.1655 - sparse_categorical_accuracy: 0.9592"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"32/32 [==============================] - 0s 2ms/step - loss: 0.1525 - sparse_categorical_accuracy: 0.9630\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO:tensorflow:Assets written to: saved_model/my_model/assets\n"
]
}
],
"source": [
"# Create and train a new model instance.\n",
"model = create_model()\n",
"model.fit(train_images, train_labels, epochs=5)\n",
"\n",
"# Save the entire model as a SavedModel.\n",
"!mkdir -p saved_model\n",
"model.save('saved_model/my_model') "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "iUvT_3qE8hV5"
},
"source": [
"SavedModel 형식은 protobuf 바이너리와 TensorFlow 체크포인트를 포함하는 디렉토리입니다. 저장된 모델 디렉토리를 검사합니다."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T20:23:23.903183Z",
"iopub.status.busy": "2022-12-14T20:23:23.902492Z",
"iopub.status.idle": "2022-12-14T20:23:24.263104Z",
"shell.execute_reply": "2022-12-14T20:23:24.261913Z"
},
"id": "sq8fPglI1RWA"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"my_model\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"assets\tfingerprint.pb\tkeras_metadata.pb saved_model.pb variables\r\n"
]
}
],
"source": [
"# my_model directory\n",
"!ls saved_model\n",
"\n",
"# Contains an assets folder, saved_model.pb, and variables folder.\n",
"!ls saved_model/my_model"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "B7qfpvpY9HCe"
},
"source": [
"저장된 모델로부터 새로운 케라스 모델을 로드합니다:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T20:23:24.267855Z",
"iopub.status.busy": "2022-12-14T20:23:24.267519Z",
"iopub.status.idle": "2022-12-14T20:23:24.509684Z",
"shell.execute_reply": "2022-12-14T20:23:24.508932Z"
},
"id": "0YofwHdN0pxa"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential_5\"\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"_________________________________________________________________\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" Layer (type) Output Shape Param # \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"=================================================================\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" dense_10 (Dense) (None, 512) 401920 \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" dropout_5 (Dropout) (None, 512) 0 \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" dense_11 (Dense) (None, 10) 5130 \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"=================================================================\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Total params: 407,050\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Trainable params: 407,050\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Non-trainable params: 0\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"_________________________________________________________________\n"
]
}
],
"source": [
"new_model = tf.keras.models.load_model('saved_model/my_model')\n",
"\n",
"# Check its architecture\n",
"new_model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "uWwgNaz19TH2"
},
"source": [
"복원된 모델은 원본 모델과 동일한 매개변수로 컴파일되어 있습니다. 이 모델을 평가하고 예측에 사용해 보죠:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T20:23:24.517024Z",
"iopub.status.busy": "2022-12-14T20:23:24.516414Z",
"iopub.status.idle": "2022-12-14T20:23:24.946495Z",
"shell.execute_reply": "2022-12-14T20:23:24.945565Z"
},
"id": "Yh5Mu0yOgE5J"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"32/32 - 0s - loss: 0.4686 - sparse_categorical_accuracy: 0.8520 - 174ms/epoch - 5ms/step\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Restored model, accuracy: 85.20%\n",
"\r",
" 1/32 [..............................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"32/32 [==============================] - 0s 1ms/step\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"(1000, 10)\n"
]
}
],
"source": [
"# Evaluate the restored model\n",
"loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)\n",
"print('Restored model, accuracy: {:5.2f}%'.format(100 * acc))\n",
"\n",
"print(new_model.predict(test_images).shape)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "SkGwf-50zLNn"
},
"source": [
"### HDF5 파일로 저장하기\n",
"\n",
"케라스는 [HDF5](https://en.wikipedia.org/wiki/Hierarchical_Data_Format) 표준을 따르는 기본 저장 포맷을 제공합니다. "
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T20:23:24.950129Z",
"iopub.status.busy": "2022-12-14T20:23:24.949827Z",
"iopub.status.idle": "2022-12-14T20:23:26.253725Z",
"shell.execute_reply": "2022-12-14T20:23:26.252899Z"
},
"id": "m2dkmJVCGUia"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/5\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\r",
" 1/32 [..............................] - ETA: 23s - loss: 2.4508 - sparse_categorical_accuracy: 0.0938"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"21/32 [==================>...........] - ETA: 0s - loss: 1.4227 - sparse_categorical_accuracy: 0.5848 "
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"32/32 [==============================] - 1s 3ms/step - loss: 1.1802 - sparse_categorical_accuracy: 0.6620\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 2/5\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\r",
" 1/32 [..............................] - ETA: 0s - loss: 0.4583 - sparse_categorical_accuracy: 0.8125"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"23/32 [====================>.........] - ETA: 0s - loss: 0.4319 - sparse_categorical_accuracy: 0.8641"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"32/32 [==============================] - 0s 2ms/step - loss: 0.4295 - sparse_categorical_accuracy: 0.8750\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 3/5\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\r",
" 1/32 [..............................] - ETA: 0s - loss: 0.2316 - sparse_categorical_accuracy: 0.9375"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"23/32 [====================>.........] - ETA: 0s - loss: 0.2780 - sparse_categorical_accuracy: 0.9334"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"32/32 [==============================] - 0s 2ms/step - loss: 0.2942 - sparse_categorical_accuracy: 0.9270\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 4/5\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\r",
" 1/32 [..............................] - ETA: 0s - loss: 0.1834 - sparse_categorical_accuracy: 0.9375"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"23/32 [====================>.........] - ETA: 0s - loss: 0.2171 - sparse_categorical_accuracy: 0.9470"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"32/32 [==============================] - 0s 2ms/step - loss: 0.2196 - sparse_categorical_accuracy: 0.9490\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 5/5\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\r",
" 1/32 [..............................] - ETA: 0s - loss: 0.1569 - sparse_categorical_accuracy: 0.9688"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"23/32 [====================>.........] - ETA: 0s - loss: 0.1565 - sparse_categorical_accuracy: 0.9647"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"32/32 [==============================] - 0s 2ms/step - loss: 0.1616 - sparse_categorical_accuracy: 0.9650\n"
]
}
],
"source": [
"# Create and train a new model instance.\n",
"model = create_model()\n",
"model.fit(train_images, train_labels, epochs=5)\n",
"\n",
"# Save the entire model to a HDF5 file.\n",
"# The '.h5' extension indicates that the model should be saved to HDF5.\n",
"model.save('my_model.h5') "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "GWmttMOqS68S"
},
"source": [
"이제 이 파일로부터 모델을 다시 만들어 보죠:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T20:23:26.258043Z",
"iopub.status.busy": "2022-12-14T20:23:26.257750Z",
"iopub.status.idle": "2022-12-14T20:23:26.337374Z",
"shell.execute_reply": "2022-12-14T20:23:26.336667Z"
},
"id": "5NDMO_7kS6Do"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"sequential_6\"\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"_________________________________________________________________\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" Layer (type) Output Shape Param # \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"=================================================================\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" dense_12 (Dense) (None, 512) 401920 \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" dropout_6 (Dropout) (None, 512) 0 \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" dense_13 (Dense) (None, 10) 5130 \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
" \n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"=================================================================\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Total params: 407,050\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Trainable params: 407,050\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Non-trainable params: 0\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"_________________________________________________________________\n"
]
}
],
"source": [
"# Recreate the exact same model, including its weights and the optimizer\n",
"new_model = tf.keras.models.load_model('my_model.h5')\n",
"\n",
"# Show the model architecture\n",
"new_model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "JXQpbTicTBwt"
},
"source": [
"정확도를 확인해 보겠습니다:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"execution": {
"iopub.execute_input": "2022-12-14T20:23:26.343938Z",
"iopub.status.busy": "2022-12-14T20:23:26.343636Z",
"iopub.status.idle": "2022-12-14T20:23:26.560663Z",
"shell.execute_reply": "2022-12-14T20:23:26.559793Z"
},
"id": "jwEaj9DnTCVA"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"32/32 - 0s - loss: 0.4311 - sparse_categorical_accuracy: 0.8640 - 171ms/epoch - 5ms/step\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Restored model, accuracy: 86.40%\n"
]
}
],
"source": [
"loss, acc = new_model.evaluate(test_images, test_labels, verbose=2)\n",
"print('Restored model, accuracy: {:5.2f}%'.format(100 * acc))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "dGXqd4wWJl8O"
},
"source": [
"Keras는 아키텍처를 검사하여 모델을 저장합니다. 이 기술은 모든 내용을 저장합니다.\n",
"\n",
"- 가중치 값\n",
"- 모델 구조\n",
"- 모델의 훈련 구성(`.compile()` 메서드에 전달하는 내용)\n",
"- 존재하는 옵티마이저와 그 상태(훈련을 중단한 곳에서 다시 시작할 수 있게 해줌)\n",
"\n",
"체크포인트가 호환되지 않기 때문에 케라스는 v1.x 옵티마이저(`tf.compat.v1.train`)를 저장할 수 없습니다. v1.x 옵티마이저를 사용하려면 로드한 후에 모델을 다시 컴파일해야 합니다. 따라서 옵티마이저의 상태를 잃게 됩니다.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kAUKJQyGqTNH"
},
"source": [
"### 사용자 정의 객체\n",
"\n",
"SavedModel 형식을 사용하는 경우, 이 섹션을 건너뛸 수 있습니다. HDF5와 SavedModel의 주요 차이점은 HDF5는 객체 구성을 사용하여 모델 아키텍처를 저장하는 반면, SavedModel은 실행 그래프를 저장한다는 것입니다. 따라서 SavedModel은 원본 코드 없이도 서브클래싱된 모델 및 사용자 지정 레이어와 같은 사용자 지정 객체를 저장할 수 있습니다.\n",
"\n",
"사용자 정의 객체를 HDF5로 저장하려면 다음 과정을 따르세요:\n",
"\n",
"1. 이 객체에 `get_config` 메서드를 정의하고 선택적으로 `from_config` 클래스 메서드를 정의합니다.\n",
" - `get_config(self)`는 객체를 다시 생성하기 위해 필요한 JSON 직렬화된 매개변수 딕셔너리를 반환합니다.\n",
" - `from_config(cls, config)`는 `get_config`에서 반환된 설정을 사용해 새로운 객체를 만듭니다. 기본적으로 이 함수는 이 설정을 초기화 메서드의 매개변수로 사용합니다(`return cls(**config)`).\n",
"2. 모델을 로드할 때 이 객체를 `custom_objects` 매개변수로 전달합니다. 문자열 클래스 이름과 파이썬 클래스를 매핑한 딕서너리를 매개변수로 제공해야 합니다. 예를 들면 `tf.keras.models.load_model(path, custom_objects={'CustomLayer': CustomLayer})`\n",
"\n",
"사용자 정의 객체 및 get_config
의 예를 보려면 처음부터 레이어 및 모델 작성하기 튜토리얼을 참조하세요.\n"
]
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"collapsed_sections": [],
"name": "save_and_load.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
}