딥러닝 모델 서비스하기

이재경·2023년 1월 9일
0

인공지능

목록 보기
7/14

모델 저장하기

이번 실습에서는 Tensorflow를 통해 모델을 저장하는 방법을 알아보도록 하겠습니다.

Tensorflow에서 모델을 저장하기 위해 사용하는 형식은 H5 Format과 SavedModel 두 가지가 있습니다. 실습에서는 두 가지 방식으로 각각 저장하는 방법을 실습 해보도록 하겠습니다.

지시사항
모델 저장 실습을 위해 간단한 CNN 모델을 만들고 1회 학습을 진행할 것입니다. 이를 위해 데이터셋은 MNIST 데이터셋을 사용할 것입니다.

H5 Format으로 모델 저장하기
main 함수 내에서 H5 형식으로 모델을 저장하는 코드를 완성하세요.
저장할 모델 파일의 이름은 h5_model.h5로 해야 합니다.
SavedModel로 모델 저장하기
main 함수 내에서 SavedModel 형식으로 모델을 저장하는 코드를 완성하세요.
저장할 모델 파일의 이름은 saved_model로 해야 합니다.

from elice_utils import EliceUtils

elice_utils = EliceUtils()

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

import tensorflow as tf
from tensorflow.keras import layers, models, Sequential
from tensorflow.keras.datasets import mnist
import numpy as np

def load_data():
    (X_train, y_train), (X_test, y_test) = mnist.load_data()
    
    X_train, X_test = X_train / 255.0, X_test / 255.0
    
    X_train = np.expand_dims(X_train, axis=-1)
    X_test = np.expand_dims(X_test, axis=-1)
    
    return X_train, X_test, y_train, y_test

def build_model(input_shape, num_classes=10):
    model = Sequential()
    
    model.add(layers.Conv2D(16, kernel_size=(3, 3), padding="same", activation="relu", input_shape=input_shape))
    model.add(layers.MaxPool2D(2))
    
    model.add(layers.Conv2D(32, kernel_size=(3, 3), padding="same", activation="relu"))
    model.add(layers.MaxPool2D(2))
    
    model.add(layers.Flatten())
    model.add(layers.Dense(num_classes, activation="softmax"))
    
    return model

def main():
    X_train, X_test, y_train, y_test = load_data()
    
    model = build_model(X_train[0].shape)
    
    model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
    model.fit(X_train, y_train, epochs=1, batch_size=64, shuffle=True, verbose=2)
    
    # TODO: H5 형식으로 모델 저장
    model.save("h5_model.h5")
    
    # TODO: SavedModel 형식으로 모델 저장
    model.save("saved_model")

if __name__ == "__main__":
    main()

모델 불러오기

이번 실습에서는 저장된 모델을 불러오는 과정을 실습하겠습니다.
특히, 코드에서 모델에 대한 정보를 정의하지 않고 저장된 모델을 불러와 모델의 구조를 포함한 정보들을 출력해보겠습니다.

이번 실습을 위해서 afterfit이라는 이름으로 SavedModel 형식의 모델과 체크포인트 파일들을 준비했습니다.

지시사항을 보고 저장된 모델을 불러오세요.

지시사항
SavedModel 형식 모델 불러오기
이 모델은 학습을 마친 후 다음 함수를 이용하여 저장했습니다.
model.save("./afterfit")
Copy
이 모델을 불러와 loaded_model에 저장하세요
5번째 체크포인트 불러오기
이 모델을 학습하는 과정에서 다음과 같이 콜백함수를 추가하고 학습을 진행했습니다.
ckpt=tf.keras.callbacks.ModelCheckpoint("./checkpoints/cp-{epoch:04d}.ckpt")

학습을 위한 중간 과정

fcl_model.fit(x_train, y_train, epochs= 10,validation_data=(x_val, y_val), validation_freq=1,callbacks=[ckpt])
Copy
위 코드를 참고하여 10개의 체크포인트중 5번째 체크포인트를 불러오는 코드를 작성하세요

import os
import tensorflow as tf

# 모델에 대한 어떠한 정보도 정의하지 않습니다
# 오직 저장된 모델로부터 다양한 정보를 불러와 출력합니다.


print("학습하던 모델을 불러옵니다.")
# TODO: 지시사항을 보고 학습한 SavedModel 형식 모델을 불러오세요 
loaded_model = tf.keras.models.load_model("afterfit")
loaded_model.summary()

# TODO: 지시사항을 보고 5번째 체크 포인트를 불러오세요
loaded_ckpt = tf.keras.models.load_model("./checkpoints/cp-0005.ckpt")
loaded_ckpt.summary()

이어서 모델 학습하기

이번 실습에서는 학습 과정에서 기록된 체크포인트들 중에서 특정 시점의 체크포인트를 불러오고 그 지점부터 이어서 학습하는 과정을 실습하겠습니다.

실습 폴더의 checkpoints 디렉토리 안에는 cp-0001.ckpt부터 cp-0010.ckpt이 존재합니다.

이번 실습에서는 10번째 체크포인트 cp-0010.ckpt를 불러와 이어서 5 epoch을 더 학습시켜보겠습니다.

이번 실습에서 결과를 빠르게 보기 위해서 테스트 데이터로 학습을 진행하겠습니다.

지시사항
체크포인트 불러오기
checkpnt_path에 10번째 체크포인트의 경로를 저장하세요
model에 checkpnt_path에 저장된 체크포인트를 불러오세요.
체크포인트에는 모델의 가중치와 모델의 구조에 대한 모든 정보가 포함되어 있습니다.
이어서 학습하기
이 체크포인트는 10 epoch까지 학습이 완료된 모델입니다.
이어서 11epoch부터 5epoch 학습을 진행하도록 epoch과 initial_epoch을 설정하세요

import os
import tensorflow as tf
from tensorflow.keras import layers, models, Sequential
from tensorflow.keras.datasets import mnist
import numpy as np

def load_data(): # 학습에 사용할 데이터입니다.

    (X_train, y_train), (X_test, y_test) = mnist.load_data()
    
    X_train, X_test = X_train / 255.0, X_test / 255.0
    
    X_train = np.expand_dims(X_train, axis=-1)
    X_test = np.expand_dims(X_test, axis=-1)
    
    return X_train, X_test, y_train, y_test

def main():
    X_train, X_test, y_train, y_test = load_data() # 빠른 실습을 위해 양이 적은 X_test, y_test 를 학습합니다.
    
    # TODO: 10번째 체크포인트의 경로를 checkpnt_path에 저장하세요
    checkpnt_path = "checkpoints/cp-0010.ckpt"
    
    # TODO: 불러온 체크포인트를 불러와 model에 저장하세요
    model = tf.keras.models.load_model(checkpnt_path)
    
    # TODO: 10epoch까지 학습된 이 모델을 11번째 epoch부터 이어서 5 epoch 더 학습시키세요
    hist = model.fit( x=X_test, y=y_test, batch_size=64, epochs=15,
        shuffle=True, initial_epoch=10)
        
    return hist, checkpnt_path

if __name__ == "__main__":
    main()

모델 변환하기

이번 실습에서는 자바스크립트 환경에서 Tensorflow 모델을 사용할 수 있도록 변환하는 과정을 실습하겠습니다. 간단한 모델의 학습을 진행하고 모델을 변환하는 과정과 기존의 Tensorflow 모델을 변환하는 방법을 각각 실습해보겠습니다.

모델 변환 방법
tfjs.converters.save_keras_model를 이용하면 tensorflow 모델을 tensorflowjs 모델로 변환할 수 있습니다.
tfjs.converters.save_keras_model 의 첫번째 매개변수는 원본 모델을 전달합니다.
tfjs.converters.save_keras_model 의 두번째 매개변수는 변환된 모델을 저장할 이름을 전달합니다.

지시사항
학습을 완료한 모델 model을 "JSModel1"라는 이름으로 변환하여 저장하세요
저장된 다른 SavedModel 모델인 "OtherSModel"를 loaded_model에 불러오세요.
불러온 모델을 "JSModel2"라는 이름으로 변환하여 저장하세요

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

import tensorflow as tf
from tensorflow.keras import layers, models, Sequential
from tensorflow.keras.datasets import mnist
import numpy as np
import tensorflowjs as tfjs


def load_data():
    (X_train, y_train), (X_test, y_test) = mnist.load_data()
    
    X_train, X_test = X_train / 255.0, X_test / 255.0
    
    X_train = np.expand_dims(X_train, axis=-1)
    X_test = np.expand_dims(X_test, axis=-1)
    
    return X_train, X_test, y_train, y_test

def build_model(input_shape, num_classes=10):
    model = Sequential()
    
    model.add(layers.Conv2D(8, kernel_size=(3, 3), padding="same", activation="relu", input_shape=input_shape))
    model.add(layers.MaxPool2D(2))
    
    model.add(layers.Conv2D(16, kernel_size=(3, 3), padding="same", activation="relu"))
    model.add(layers.MaxPool2D(2))
    
    model.add(layers.Flatten())
    model.add(layers.Dense(num_classes, activation="softmax"))
    
    return model


X_train, X_test, y_train, y_test = load_data()

model = build_model(X_train[0].shape)

model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
model.fit(X_train, y_train, epochs=1, batch_size=64, shuffle=True, verbose=1)    

# TODO: 학습한 모델을 바로 변환 
tfjs.converters.save_keras_model(model,"JSModel1")

# TODO: 다른 SavedModel 형식의 모델인 "OtherSModel"을 불러오기
loaded_model = tf.keras.models.load_model("OtherSModel")

# TODO: loaded_model을 tensorflow js로 변환
tfjs.converters.save_keras_model(loaded_model,"JSModel2")

Flask로 서비스하기

이번 실습에서는 MNIST dataset으로 분류된 모델을 서비스하는 방법을 알아보겠습니다. 학습된 모델은 mymodel이라는 이름으로 저장되어 있습니다.

사용자는 /?img=two.png 처럼 서버에 이미지의 URL을 전달하고, 서버는 해당 URL에서 이미지를 불러와 모델에 맞는 형태로 바꾸어 예측하고, 그 결과를 돌려줍니다.

이번 실습에서는 실제 이미지가 아닌 img 디렉토리 내의 이미지'two.png'혹은 'seven.png'를 입력 받는다고 가정하고 서비스하겠습니다.

지시사항을 보고 코드를 완성하세요

지시사항
모델을 사용하는 코드는work 함수에 작성되어 있습니다. 이 함수는 이미지를 모델에 입력하고 출력 값을 해석하여 수치를 리턴합니다. 아래 지시사항을 보고 코드를 작성하세요.

모델은 if name == "main":에서 불러옵니다. mymodel이라는 이름으로 저장된 모델을 불러오세요.
전달받은 img를 model을 이용하여 예측합니다. 예측은 predict함수를 사용합니다.
pred에는 batch 단위의 결과 값이 저장되어 있습니다. 본 실습에서는 이미지를 한개만 입력하므로 첫번째 결과를 출력하여 pred에 저장하세요
이제 pred에는 0부터 9까지 각각의 비율이 들어있습니다. 결과 값은 비율이 가장 높은 값이므로 해당 값을 tf.math.argmax함수를 이용하여 찾아서 idx에 저장하세요

from flask import Flask, jsonify, request
import tensorflow as tf
app = Flask(__name__)
import PIL.Image as image

def work(img, model): # 이미지를 입력하면 숫자를 출력하는 함수
    pred = model.predict(img) # TODO: 모델에 이미지를 넣고 결과를 pred에 저장
    pred = pred[0] # TODO: batch 단위로 나온 결과에서 이미지 하나의 결과를 추출
    idx = tf.math.argmax(pred)  # TODO: 결과중 가장 확률이 높은 index 가져오기
    return idx

@app.route("/", methods=["GET"]) # @app.route를 작성하고, GET Method만 사용합니다.
def predict():    
    imgurl = request.args.get("img")       # img라는 이름으로 url을 받아옴
    result_string="please input image url"
    if imgurl != None:                     # imgurl을 제대로 받은 경우
        imgurl=imgurl.split("?")[0]
        img = image.open("img/"+imgurl)        # 전달받은 url의 이미지 로드  
        img=tf.keras.utils.img_to_array(img)   # 이미지를 행렬로 변환
        img=tf.expand_dims(img, axis=0)        # batch를 위해 한 차원 높게 변환   
        idx = work(img, model)   # 모델을 work 함수를 통해 사용합니다.    
        result_string = "This number is %d"%(idx)   #사용자에게 보여줄 문자열
    return jsonify(result_string)


# Flask 서버를 실행하는 코드입니다.
if __name__ == "__main__":
    model = tf.keras.models.load_model("mymodel") # TODO: 학습된 모델 "mymodel"을 불러오세요.
    app.run(host="0.0.0.0", port=8080) # flask 서비스 시작
profile
코딩으로 빛나게

0개의 댓글