ddps-lab / tfserving-inference

0 stars 2 forks source link

h5 파일을 pb 파일로 변환할 때 생기는 오류 해결 #20

Closed kh3654po closed 1 year ago

kh3654po commented 1 year ago

이전의 nlp모델을 사용하는 코드를 보면 edge-inference/NLP/model에 있는 model_download.sh를 실행하면 bert_imdb_model.h5 distilbert_sst2_model.h5 lstm_imdb_model.h5 rnn_imdb_model.h5가 다운로드된다. 이후 코드에서 tf.keras.models.load_model("./model/bert_imdb_model.h5")를 하면 로드가 되는데 이는 edge-inference/NLP/bert_imdb.py에서 볼 수 있다.

실행하면 아래와 같은 에러가 나온다

Traceback (most recent call last):
  File "convert_h5_to_saved_model.py", line 5, in <module>
    model = tf.keras.models.load_model(h5_path)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/saving/save.py", line 206, in load_model
    return saved_model_load.load(filepath, compile, options)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/saving/saved_model/load.py", line 121, in load
    meta_graph_def = loader_impl.parse_saved_model(path).meta_graphs[0]
  File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/saved_model/loader_impl.py", line 116, in parse_saved_model
    constants.SAVED_MODEL_FILENAME_PB))
OSError: SavedModel file does not exist at: /home/nvidia-xavier2/edge-inference/NLP/model/bert_imdb_model.h5/{saved_model.pbtxt|saved_model.pb}
kh3654po commented 1 year ago

https://webnautes.tistory.com/1493 https://github.com/tensorflow/tensorflow/issues/35909 https://stackoverflow.com/questions/61699140/oserror-savedmodel-file-does-not-exist-at-dnn-mpg-model-h5-saved-model-pbt

위 링크 등을 통해 해결방법 찾아 시도해보았으나 현재까지 안되고 있는 상황입니다.

kmu-leeky commented 1 year ago

석현아 이 에러는 tfserving 에서 모델을 로드할때 생기는 에러인거지?

kh3654po commented 1 year ago

아닙니다 tf serving에서 로드하려면 TensorFlow 모델 형식(.pb)이어야하는데 현재는 h5 모델 형식입니다. 따라서 h5모델을 pb모델로 변환해주어야하는데 이는 tensorflow에서 h5 모델을 로드한 후에 pb 모델로 저장하는게 가능합니다. 예시 코드는 다음과 같습니다.

import tensorflow as tf

# Keras 모델 로드
model = tf.keras.models.load_model('bert_imdb_model.h5')

# SavedModel 형식으로 변환하여 내보내기
tf.saved_model.save(model, 'bert_imdb_saved_model')

현재 에러는 bert_imdb_model.h5를 로드할때 생기는 에러입니다. 잘못된 사용법인가 해서 검색을 해보니 사용방법 자체에는 문제가 없습니다.

kmu-leeky commented 1 year ago

일반 tf 에서는 문제없이 사용을 했던것으로 알고 있거든. 필요하다면 정애에게 한번 물어봐도 괜찮을것 같아.

kh3654po commented 1 year ago

넵 한번 물어보겠습니다

mh3ong commented 1 year ago

https://github.com/ddps-lab/edge-inference/blob/be359f987338a2129ee9e1eeecb8ddb8b0738162/NLP/distilbert_sst2.py 의 있는 코드를 이용하여 아래와 같이 코드를작성하니 distilbert_sst2 모델을 keras 형식 (pb)로 추출하는데 잘 진행이 되는 것 같습니다. 나머지 모델도 다른 코드를 참고하여 아래와 같이 작업하면 될 듯 합니다.

import transformers
import datasets
import tensorflow as tf
import time
import numpy as np
import pandas as pd
import tqdm

def create_bert_input_features(tokenizer, docs, max_seq_length):

    all_ids, all_masks = [], []
    for doc in tqdm.tqdm(docs, desc="Converting docs to features"):
        tokens = tokenizer.tokenize(doc)
        if len(tokens) > max_seq_length-2:
            tokens = tokens[0 : (max_seq_length-2)]
        tokens = ['[CLS]'] + tokens + ['[SEP]']
        ids = tokenizer.convert_tokens_to_ids(tokens)
        masks = [1] * len(ids)
        # Zero-pad up to the sequence length.
        while len(ids) < max_seq_length:
            ids.append(0)
            masks.append(0)
        all_ids.append(ids)
        all_masks.append(masks)
    encoded = np.array([all_ids, all_masks])
    return encoded

def train_and_save_model(saved_model_dir):

  global model

  dataset = datasets.load_dataset("glue", "sst2")

  train_reviews = np.array(dataset['train']["sentence"])
  train_sentiments = np.array(dataset['train']["label"])

  valid_reviews = np.array(dataset['validation']["sentence"])
  valid_sentiments = np.array(dataset['validation']["label"])

  # test_reviews = np.array(dataset['test']["sentence"])

  tokenizer = transformers.DistilBertTokenizer.from_pretrained('distilbert-base-uncased')

  MAX_SEQ_LENGTH = 128

  train_features_ids, train_features_masks = create_bert_input_features(tokenizer, train_reviews, 
                                                                        max_seq_length=MAX_SEQ_LENGTH)

  val_features_ids, val_features_masks = create_bert_input_features(tokenizer, valid_reviews, 
                                                                    max_seq_length=MAX_SEQ_LENGTH)

  train_ds = (
    tf.data.Dataset
    .from_tensor_slices(((train_features_ids, train_features_masks), train_sentiments))
    .shuffle(2048)
    .batch(128)
    .prefetch(tf.data.experimental.AUTOTUNE)
  )

  valid_ds = (
    tf.data.Dataset
    .from_tensor_slices(((val_features_ids, val_features_masks), valid_sentiments))
    .batch(128)
    .prefetch(tf.data.experimental.AUTOTUNE)
  )

  inp_id = tf.keras.layers.Input(shape=(MAX_SEQ_LENGTH,), dtype='int32', name="bert_input_ids")
  inp_mask = tf.keras.layers.Input(shape=(MAX_SEQ_LENGTH,), dtype='int32', name="bert_input_masks")
  inputs = [inp_id, inp_mask]

  hidden_state = transformers.TFDistilBertModel.from_pretrained('distilbert-base-uncased')(inputs)[0]
  pooled_output = hidden_state[:, 0]    
  dense1 = tf.keras.layers.Dense(256, activation='relu')(pooled_output)
  drop1 = tf.keras.layers.Dropout(0.25)(dense1)
  dense2 = tf.keras.layers.Dense(256, activation='relu')(drop1)
  drop2 = tf.keras.layers.Dropout(0.25)(dense2)
  output = tf.keras.layers.Dense(1, activation='sigmoid')(drop2)

  model = tf.keras.Model(inputs=inputs, outputs=output)
  model.compile(optimizer=tf.optimizers.Adam(learning_rate=2e-5, 
                                              epsilon=1e-08), 
                loss='binary_crossentropy', metrics=['accuracy'])

  model.fit(train_ds, 
      validation_data=valid_ds,
      epochs=3)

  model.save(saved_model_dir, include_optimizer=False, save_format='tf')

model_name = 'distilbert_sst2'
saved_model_dir=f'./model/{model_name}_model.h5'
train_and_save_model(saved_model_dir)
kmu-leeky commented 1 year ago

nice!

kh3654po commented 1 year ago

h5 파일로드가 안돼서 운호님 코드를 참고해서 모델을 새롭게 학습시키고 저장할 때 h5가 아닌 pb로 저장하도록 하였습니다. imdb 데이터셋을 학습시킨 bert 모델입니다. 학습시킨 모델의 압축파일을 s3://edge-inference/NLP/에 업로드하였고 이를 xavier 장비에서 다운로드받아 tf model server에 로드해보았습니다. 현재 로드는 잘됐지만 bench 코드를 작성하여 테스트해보진 않았습니다. 후에 코드를 작성하여 테스트를 진행하겠습니다.

kh3654po commented 1 year ago

추가적인 이슈