base64 서명 데이터 학습

Tensorflow 정리 2021. 7. 20. 13:53

1. Base64 인코딩 된 것 이미지로 전환해서 학습이 가능한지 확인.

 - base64 데이터 형태로 학습이 가능하다.

 

2. base64 데이터 학습 사용법 (Keras 모델의 Xception 사용)

 - tensorflow가 아직 익숙하지 않음로 Keras를 사용하여 구현.

 2.1 keras 모델 학습을 위한 전제조건

from tensorflow import keras

model = keras.applications.Xception(weights="imagenet")
model.compile(loss="categorical_crossentropy")

 2.2 작업 순서

   - 1. base64 문자열로 인코딩된 입력 이미지 디코딩
   - 2. Tensor로 변환
   - 3. 크기 조정
   - 4. 모델에 필요한 영상 전처리 단계 적용

from typing import Callable, Tuple
import tensorflow as tf


# if using tf >=2.0, disable eager execution to use tf.placeholder
tf.compat.v1.disable_eager_execution()


class ServingInputReceiver:
    """
    A callable object that returns a 
    `tf.estimator.export.ServingInputReceiver` 
    object that provides a method to convert 
    `image_bytes` input to model.input
    """
    def __init__(
        self, img_size: Tuple[int], 
        preprocess_fn: Callable = None, 
        input_name: str = "input_1"):
        
        self.img_size = img_size
        self.preprocess_fn = preprocess_fn
        self.input_name = input_name
        
    def decode_img_bytes(self, img_b64: str) -> tf.Tensor:
        """
        Decodes a base64 encoded bytes and converts it to a Tensor.
        Args:
            img_bytes (str): base64 encoded bytes of an image file
        Returns:
            img (Tensor): a tensor of shape (width, height, 3)
        """
        img = tf.io.decode_image(
            img_b64, 
            channels=3,
            dtype=tf.uint8,
            expand_animations=False
        )
        img = tf.image.resize(img, size=self.img_size)
        img = tf.ensure_shape(img, (*self.img_size, 3))
        img = tf.cast(img, tf.float32)
        return img
    
    def __call__(self) -> tf.estimator.export.ServingInputReceiver:
        # a placeholder for a batch of base64 string encoded of image bytes
        imgs_b64 = tf.compat.v1.placeholder(
            shape=(None,), 
            dtype=tf.string, 
            name="image_bytes")
        
        # apply self.decode_img_bytes() to a batch of image bytes (imgs_b64)
        imgs = tf.map_fn(
            self.decode_img_bytes, 
            imgs_b64, 
            dtype=tf.float32)
        
        # apply preprocess_fn if applicable
        if self.preprocess_fn:
            imgs = self.preprocess_fn(imgs)
        
        return tf.estimator.export.ServingInputReceiver(
            features={self.input_name: imgs},
            receiver_tensors={"image_bytes": imgs_b64}
        )

 2.3 객체 생성

   - base64 input을 처리할 serving_input_receiver객체 생성

   - 객체 생성 후 리사이즈 & 모델 적용 (keras.applications.xception.preprocess_input)

from tensorflow import keras

serving_input_receiver = ServingInputReceiver(
    img_size=(299, 299),
    preprocess_fn=keras.applications.xception.preprocess_input,
    input_name="input_1")

  2.4 TF 서비스 모델 export

estimator_save_dir = "estimators/xception"
estimator = tf.keras.estimator.model_to_estimator(
    keras_model=model,
    model_dir=estimator_save_dir)

export_model_dir = "models/classification/xception/"  # this is where the exported model will end up. 
estimator.export_saved_model(
    export_dir_base=export_model_dir,
    serving_input_receiver_fn=serving_input_receiver)

   - 2.4 까지 적용했을 때의 Keras 모델 구조

models
└── classification
    └── xception
        └── 1586063263
            ├── saved_model.pb
            └── variables
                ├── variables.data-00000-of-00002
                ├── variables.data-00001-of-00002
                └── variables.index

  2.5 export한 모델 서비스하기

   - Docker 이용

docker run -p 8500:8500 \ 
           -p 8501:8501 \ 
           -v <path_to_model_dir>/models/classification/xception:/models/xception \
           -e MODEL_NAME=xception -t tensorflow/serving

  2.6 서비스한 모델 테스트

   - 샘플 예제

import base64
from typing import Dict
import requests


SERVER_URL = "http://localhost:8501/v1/models/xception:predict"


def encode_img(img_filename: str) -> str:
    with open(img_filename, "rb") as f:
        img_bytes = base64.b64encode(f.read())
    return img_bytes.decode("utf8")


def prepare_request(img_filename: str) -> Dict:
    img_bytes = encode_img(img_filename)
    req = {
        "instances": [
            {"image_bytes": {"b64": img_bytes}},
        ]
    }
    return req

def send_request(img_filename: str) -> Dict:
    predict_request = prepare_request(img_filename)
    response = requests.post(SERVER_URL, json=predict_request)
    response.raise_for_status()
    return response.json()

   - 샘플 예제 request 방법(파일 경로 및 확장자)

response = send_request("path-to-img.jpg|png|gif")

   - 샘플 예제 output

{'predictions': [[0.000263870839,
   0.000306949107,
   0.000248591678,
   0.000319328334,
   0.000141894678,
   0.000295011501,
   0.000241611619,
   ...]]
  }

 

3. 이미지 처리를 위한 다른 사용법

  - base64 형태가 아닌 img 로딩해서 사용

   3.1 이미지(local file) -> 예측

#이미지를 불러와서 모델 예측에 사용
fpath="image.jpg"
image_size = (224, 224)

img = tf.keras.preprocessing.image.load_img(
    fpath,
    grayscale=False,
    color_mode="rgb",
    target_size=IMAGE_SIZE,
    interpolation='bilinear')

input_array = tf.keras.preprocessing.image.img_to_array(img)
input_array[0][0] # output: array([167., 103.,  66.], dtype=float32)
pred = model_loaded.predict(np.expand_dims(input_array, axis = 0)/255)

   3.2 이미지(local file) -> base64변환 -> 예측

#이미지를 base64로 읽어와서 예측에 사용
fpath="image.jpg"

# convert image base64 to be sent
image_base64 = base64.b64encode(open(fpath, 'rb').read()).decode("utf-8")
data = json.dumps({'image': image_base64})

# on the server side I get `data` and I want to read the base64 to feed tensorflow model
image = base64.b64decode(json.loads(data)['image'])
image[0:5] # output: b'xffxd8xffxe0x00'

image = tf.io.decode_image(image, channels=3)
image = tf.image.resize(image, 
                        method="bilinear", 
                        size=IMAGE_SIZE)

input_array = np.array(image) 
input_array[0][0] # output array([163.3482  , 102.01786 ,  62.383926], dtype=float32)
pred = model.predict(np.expand_dims(input_array, axis=0))

   3.3 이미지(url) -> base64변환 -> 예측 소스는 추가 필요

# Download the image
IMAGE_URL = https://tensorflow.org/images/blogs/serving/cat.jpg
dl_request= requests.get(IMAGE_URL, stream=True)
dl_request.raise_for_status()
# Compose a JSON Predict request (send JPEG image in base64).
jpeg_bytes= base64.b64encode(dl_request.content).decode('utf-8')
predict_request= '{"instances" : [{"b64": "%s"}]}' % jpeg_bytes
 
#output : {"instances" : [{"b64": "/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAKACiiigAooooAKKKKACiiigAooooA//Z"}]}

 

 

4. 1회성이 아닌 지속적 학습하기 위해 어떻게 구현해야 하는가?

   - 단순히 생각하기로는 학습 서버와 운영 서버를 따로 구성

   - 학습 서버는 입력된 base64 input에 대해 지속적으로 학습 수행

   - 학습 후 일정 주기마자 운영 서버에 배포

   - 머신러닝모델 학습배포 사이클 https://ichi.pro/ko/meosin-leoning-model-eul-peulodeogsyeon-e-baepohaneun-munje-245001997032627

 

5. 참고 json

#2. base64 데이터 표현 json
{ "b64": "base64 encoded string" }
  
#3. base64 데이터 표현 json(서명 정의 및 캡션 포함)
{   "signature_name": "classify_objects",
    "examples": 
    [
      {
        "image": { "b64": "aW1hZ2UgYnl0ZXM=" },
        "caption": "seaside"
      },
      {
        "image": { "b64": "YXdlc29tZSBpbWFnZSBieXRlcw==" },
        "caption": "mountains"
      }   
    ] 
}

 

 

6. 기존에 논의되었던 문장기준 한글 OCR 판별 참고자료

http://101.101.175.217:8080/static/aiocr/learning

 

 

 

 

 

https://medium.com/@sdanaipat/deploy-keras-models-using-tensorflow-serving-5b46b7d5e024

'Tensorflow 정리' 카테고리의 다른 글

머신러닝 모델 배포 방법  (0) 2021.06.29
SVM 알고리즘  (0) 2021.06.08
TensorFlow 연습  (0) 2021.05.19