[TF] SavedModel 은?

SavedModel이란?

SavedModel는 TensorFlow에서 모델을 저장할 때의 일반적인 직렬화 형식입니다. TensorFlow에는 기본 모델의 저장 형식으로 Checkpoint가 있습니다. Python으로 코드를 작성 모델을 훈련하여 일정한 간격마다 모델을 저장할 때 Checkpoint 형식의 저장이 적합합니다. 그러나 완성 된 모델을 막상 실전 환경에서 추론시키고 싶다는 같은 경우를 생각하면, 그 추론의 프로그램을 다른에서 쓸 필요가 있거나, 원래 모델을 탑재하는 시스템이 Python으로 작성되어 있지 않을 때, Checkpoint 형식을 사용할 수 없습니다. SavedModel 형식으로 저장하면 프로그래밍 언어에 의존하지 않고 명령 줄에서 추론을하거나 TensorFlow Serving과 TensorFlow Model Analysis, GCP의 Cloud ML Engine 등 높은 수준의 서비스 및 도구 TensorFlow 모델을 이용할 수 할 수 있습니다.

저장 방법

우선 모델로 슈퍼 간단한 계산 그래프를 제공합니다.

import tensorflow as tf

x = tf.placeholder (tf.float32, shape = [None] name = 'input')
y = tf.placeholder (tf.float32, shape = [None] name = 'target')

a = tf.Variable (tf.zeros ([1]) name = 'var_1')
b = tf.Variable (tf.zeros ([1]) name = 'var_2')
out = tf.identity (a * x + b name = 'out')

loss = tf.reduce_mean (tf.square (y-out))

global_step = tf.train.get_or_create_global_step ()
train = tf.train.GradientDescentOptimizer (0.5) .minimize (loss, global_step = global_step)

init = tf.global_variables_initializer ()

sess = tf.InteractiveSession ()

sess.run (init)

본래는 훈련 등을 할 필요가 있지만, 간단히 설명하기 위해서 여러가지를 생략했습니다. 모델을 정의할 수 있기 때문에, 우선 간단히tf.saved_model.simple_save 메소드를 사용하여 SavedModel 형식으로 모델을 만듭니다.

simple_save 의한 저장

tf.saved_model.simple_save (sess './models'inputs = { "input": x} outputs = { "output": out})

이렇게하면 models 디렉토리 아래에 다음과 같은 파일이 나타납니다. 스크린샷 2020-07-13 오전 10.50.36

Session과 모델의 디렉토리를 매개변수로 사용하는 tf.train.Saver ()에 따르면 Checkpoint 형식의 모델 저장과 같지만 다른 점은 입력과 출력의 Tensor를 지정하는 점입니다. 당연하겠지만 계산 그래프를 만든 것은 개발자이기 때문에 어떤 Tensor가 입력이고 어디가 출력인지 알겠죠. 하지만 TensorFlow Serving 등의 라이브러리라면 입력과 출력을 알 수 없을 수 있습니다. 예를 들면 클래스 분류를 하는 모델을 만든다고 했을 때, 출력에도 소프트 맥스 함수를 작용시켜서 각 클래스에서 확률을 어플리케이션에서 필요할 수도 있고, 단순히 입력이 어떤 클래스에 속하는 것만 원하는 경우도 있고, 이럴때는 소프트 맥스 함수를 작용시킬 이전 Tensor 만 있으면 충분합니다. 따라서 SavedModel을 내보낼 때 입출력 정보를 지정 해줄 필요가 있고, 그러한 입출력 정보를 TensorFlow는 "Signature"라고합니다. 이 간단한 방법으로 내 보낸 SavedModel 곧 TensorFlow Serving과saved_model_cli에서 사용할 수 있습니다. 또한 Python 이외의 언어도 읽을 수 있습니다.

SavedModelBuilder 의한 저장

방금 전의tf.saved_model.simple_save는 편리하고 쉽게 사용할 수 있지만 최소의 기능 밖에 제공하지 않습니다. 여기에서는 세부적인 것을 설정할 수 있도록 tf.saved_model.builder.SavedModelBuilder ()를 이용한 저장 방법을 소개합니다.

builder = tf.saved_model.builder.SavedModelBuilder ( './ models')
signature = tf.saved_model.predict_signature_def (inputs = { 'input': x} outputs = { 'output': out})
builder.add_meta_graph_and_variables (sess = sess,
                                     tags = [tf.saved_model.tag_constants.SERVING,
                                     signature_def_map = { 'predict': signature})
builder.save ()

simple_save에 비해 약간 복잡해지고 있습니다. 먼저 디렉토리 이름을 받아서tf.saved_model.builder.SavedModelBuilder ()를 선언합니다. 이렇게하면models라는 디렉토리가 완성됩니다. 하지만 아직 내용이 비어 있습니다. 다음 Signature를 정의합니다. 이곳은 조금의 simple_save과 비슷합니다. Signiture의 정의에 필요한 것은 입력과 출력의 Tensor 다른 메소드라는 것이 사실 필요하고, 여기에서는 Predict라는 메소드에 대한 Signature를 정의하고 있습니다. 각종 방법의 차이 등을 알고 싶다면 [여기] (https://github.com/tensorflow/serving/blob/master/tensorflow_serving/g3doc/signature_defs.md)를 참고하면 좋다고 생각합니다. 또한 Predict 이외의 메소드 용의 Signature를 정의하는 함수와보다 일반적인 Signature를 만들기위한tf.saved_model.build_signature_def ()라는 메소드도 존재하기 때문에 필요에 따라 사용할 수 있습니다. Signature를 정의한 후에add_meta_graph_and_variables 메소드를 사용하여 모델을 추가합니다. Session 및 Signature를 전달하는 것은 당연하지만, 여기에 또 다른 새로운 개념이다 tag라는 것이 나옵니다. 이 tag는 한마디로 여러 계산 그래프를 구별하기위한 것입니다. 사실 SavedModel에는 여러 계산 그래프를 포함 할 수 있습니다. 유스 케이스로 훈련 계산 그래프와 추론의 계산 그래프를 나눈다는 것은 잘 이루어집니다. 또한 같은 모델이라하더라도 배포하는 에지 디바이스를 통해 GPU가 사용할 때, 그렇지 않을 때 등 다양한 경우가 있습니다. CPU 버전과 GPU 버전에서 모델을 나누어 두는 것은 좋겠지요. 여기서는 하나만 계산 그래프를 추가하지만 여러개를 추가할 경우 처음에는 반드시add_meta_graph_and_variables 메서드 모델의 뼈대와 Variable을 모두 추가 해야하고, 2 번째 이후는add_meta_graph 라는 메소드에 웨이트를 공유하는 다른 계산 그래프를 추가 할 수 있습니다. tag는 문자열 목록이라면 무엇이든 좋지만, TensorFlow는

  • SERVING
  • TRAINING
  • GPU
  • TPU

같은 고정 된 문자열이 정의합니다. GPU에서 추론할 때 [SERVING, GPU]처럼 tag를 설정해 놓는 것이 읽어 올 때 tag를 잘 보여줍니다. 마지막으로save 메서드 SavedModel를 내 보냅니다.

구조

이 예에서는 전체 기능을 활용하고 있지 않기 때문에 빠진 것도 있습니다만, SavedModel의 구조는 다음과 같습니다.

assets /
assets.extra /
variables /
    variables.data - ????? - of - ?????
    variables.index
saved_model.pb | saved_model.pbtxt

saved_model.pb는 메타 그래프를 나타냅니다. 어떤 작업과 어떤 Variable이 연산되었는지 구조는 지키면서 Variable 값 자체는 가지지는 않습니다. variables 바로 아래의 두 파일이 Variable 값을 가집니다. tf.train.Saver ()를 이용한 저장과 거의 똑같습니다. assets 단어 사전 파일 등의 외부 파일이 저장되는 폴더입니다. add_meta_graph_and_variables ()메소드의 인수assets_collection으로 지정합니다. 이 부분이 Checkpoint 형식과 다른 점입니다.

tf.keras에서 내보내기

예시에서 TensorFlow의 LowLevelAPI에서 설명하고 Session 등의 개념이 나왔습니다. Keras를 사용해서 만든다면 Session 을 사용하지 않을 수 있지만, TF2.0부터는 Keras 가 통합되어 KerasAPI (tf.keras)을 사용할 것이기 때문에 tf.keras에서 SavedModel을 생성하는 방법을 참고하세요.

import tensorflow as tf

model = tf.keras.models.load_model ( './ model.h5')
export_path = './models'

with tf.keras.backend.get_session () as sess :
    tf.saved_model.simple_save (
        sess,
        export_path,
        inputs = { 'input': model.input}
        outputs = {t.name:t for t in model.outputs})

tf.keras.backend.get_session ()메소드에서 Session을 취득할 수 있기 때문에 나머지는 그대로입니다.

참고 사이트