Tensorflow 2 TFJS
자바스크립트에서 텐서플로우 모델을 사용하기 위해서는 TensorflowJS 에 맞는 형태로 Tensorflow 모델을 변형해야 합니다.
TFJS는 tfjs-react-native등 웹 뿐만 아니라 react-native에서도 사용 가능한 라이브러리라는 장점이 있습니다.
자세한 내용은 위 tensorflow/tfjs-converter 페이지에서 확인할 수 있습니다. 저는 몇 가지 예시를 간략하게 정리해두고자 합니다.
Abstract
Tensorflow 모델은 보통 .h5
로 저장되는 형식과 .pb
가 안에 있는 디렉토리 형식으로 저장이 됩니다.
.h5
파일의 경우 Keras 모델이라고 이해하시면 됩니다. 즉 model.fit() summary() 등의 메서드가 가능한 케라스 모델입니다.
.pb
파일의 경우 살짝 복잡합니다. Keras 형식이 남아있는 pb 파일이 있고, 완전히 Tensorflow Graph으로 변경을 시킨 pb 파일이 있습니다. 앞의 방식을 tf.keras.SaveModel, 뒤의 방식을 Tensorflow SavedModel이라고 합니다.
즉 같은 pb라도 하나는 Load하면 model.summary()가 가능한 케라스 모델이고 다른 하나는 이런 메서드가 없어서 model.signatures 등으로 추론을 해야 한다는 걸 기억해주시면 좋겠습니다.
https://saturncloud.io/blog/how-to-export-keras-h5-to-tensorflow-pb-a-comprehensive-guide/
상기 링크는 h5를 pb로 컨버팅하는 방법에 대한 링크인데, 중간 쯔음 Graph로 변환하지 않은 pb 형식이 Keras pb라고 보시면 됩니다.
저는 처음에 pb 파일 컨버팅에서 애를 먹었는데 나중에서야 같은 pb여도 형식이 다를 수 있다는 걸 알게 되었습니다.
즉, 정리하면 다음과 같습니다.
텐서플로 모델은 다음과 같이 저장될 수 있습니다.
Keras 형식 .h5 SavedModel 형식 .pb
a. tf.keras SavedModel .pb
b. TensorFlow SavedModel .pb
파이토치의 경우 .pth → .onnx → .pb(tensor graph) 변환을 한 후 텐서플로JS로 컨버팅을 진행하면 됩니다.
Converting
학습한 모델을 TFJS에서 사용하기 위해서는 tfjs-converter를 사용하여 모델을 컨버팅해야 합니다.
우선 컴퓨터 파이썬 환경에 tensorflowjs를 설치해야 합니다.
pip3 install tensorflowjs
이제 각각의 저장 방법에 맞추어 컨버팅을 진행하면 됩니다.
Tensorflow SavedModel to TFJS
tensorflowjs_converter \\
--input_format=tf_saved_model \\
--output_format=tfjs_graph_model \\
--signature_name=serving_default \\
--saved_model_tags=serve \\
saved_model 경로 \\
web_model 저장할 경로
tf.keras SavedModel to TFJS
tensorflowjs_converter \\
--input_format=keras_saved_model \\
saved_model 경로 \\
web_model 저장할 경로
Keras H5 to TFJS
tensorflowjs_converter \\
--input_format=keras \\
saved_model 경로 \\
web_model 저장할 경로
--input_format 을 각 포멧마다 잘 지정해야 한다는 걸 알 수 있습니다.
Quantization
tensorflowjs_converter 를 통해 컨버팅을 수행할 때 quantization 옵션을 사용하여 양자화가 가능합니다.
사용 가능한 옵션은 총 3가지입니다. 이런 옵션들 역시 https://github.com/tensorflow/tfjs/tree/master/tfjs-converter 에서 상세히 확인하실 수 있습니다.
--quantize_float16 | float16 양자화를 적용할 쉼표로 구분된 노드 이름 목록입니다. 또한 와일드카드 기호(*)를 사용하여 여러 노드에 양자화를 적용할 수도 있습니다(예: 전환/*/가중치). 노드 없이 플래그가 제공되면 기본 동작은 모든 노드와 일치합니다. |
--quantize_uint8 | 1바이트 아핀 양자화를 적용하기 위한 쉼표로 구분된 노드 이름 목록입니다. 또한 와일드카드 기호(*)를 사용하여 여러 노드에 양자화를 적용할 수도 있습니다(예: 전환/*/가중치). 노드 없이 플래그가 제공되면 기본 동작은 모든 노드와 일치합니다. |
--quantize_uint16 | 2바이트 아핀 양자화를 적용하기 위한 쉼표로 구분된 노드 이름 목록입니다. 또한 와일드카드 기호(*)를 사용하여 여러 노드에 양자화를 적용할 수도 있습니다(예: 전환/*/가중치). 노드 없이 플래그가 제공되면 기본 동작은 모든 노드와 일치합니다. |