Tensorflow Lite는 Bazel로 빌드해서 사용 할 수 있다.
여기서는 C++로 간단하게 테스트코드를 만드는 방법까지 정리해보았다.
Tensorflow Lite를 빌드하고 실제 Inference까지 진행하기에는 크게 3단계로 나뉜다
1. Tensorflow 소스코드로부터 libtensorflowlite.so 빌드
2. 모델을 학습한 후 최종 모델을 .tflite형태로 변환
3. C++이나 자바에서 inference할 코드 작성
차근차근 해보도록 하자
libtensorflowlite.so 빌드
1. 원하는 TF 버전 브랜치를 찾아 git clone
tensorflow/tensorflow
An Open Source Machine Learning Framework for Everyone - tensorflow/tensorflow
github.com
2. TF 버전에 맞는 Bazel 버전을 확인 한 후 설치 -> tensorflow 소스의 .bazelversion파일을 확인하면 된다
bazelbuild/bazel
a fast, scalable, multi-language and extensible build system - bazelbuild/bazel
github.com
3. Bazel 설치 후 환경변수 추가
ex) ~/.bashrc
export BAZEL_HOME=/usr/bin
export PATH=$BAZEL_HOME:$PATH
4. ~/tensorflow 폴더로 이동하여 ./configure로 빌드 옵션을 세팅
- Please specify the location of python. [Default is /usr/bin/python]: /usr/bin/python2.7 -> 아나콘다를 쓰기때문에 /usr/bin/anaconda3/bin/python 로 바꿔주었음 (which python으로 경로 확인)
- 이 다음에도 여러가지 옵션들이 있는데 일단 로컬에서 테스트 코드만 돌려볼 목적이므로 대부분 NO를 선택해주면 된다.
5. 빌드
~/tensorflow에서
bazel build -c opt --cxxopt='--std=c++11' --fat_apk_cpu=x86_64 tensorflow/lite:libtensorflowlite.so
- ~/tensorflow/bazel-bin/tensorflow/lite에서 so파일 생성됨
- --fat_apk_cpu=x86_64 is the option for linux machine
모델을 .tflite로 변환
TF lite에서 지원되는 Operation 을 확인 하고 모델링을 한다
특히 RNN 연산의 경우 제약사항이 많은 것 같으니 꼭 확인을 하고 모델링하도록 하자!
TensorFlow Lite and TensorFlow operator compatibility
TensorFlow Lite supports a number of TensorFlow operations used in common inference models. As they are processed by the TensorFlow Lite Optimizing Converter, those operations may be elided or fused, before the supported operations are mapped to their Tens
www.tensorflow.org
Convert RNN models | TensorFlow Lite
The TensorFlow Lite interpreter currently implements a subset of TensorFlow operations, meaning some model architectures cannot immediately be converted due to missing operations. Some RNN-based architectures are affected by this. The following document ou
www.tensorflow.org
4. 내가 만든 모델 학습 -> 저장(ckpt or h5) -> .tflite 파일로 변환
Sample model and Save as .tflite
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
model = tf.keras.Sequential([tf.keras.layers.Dense(units=1, input_shape=[1])])
model.compile(optimizer='sgd', loss='mean_squared_error')
xs = np.array([ -1.0, 0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)
ys = np.array([ -3.0, -1.0, 1.0, 3.0, 5.0, 7.0], dtype=float)
model.fit(xs, ys, epochs=500)
print(model.predict([10.0]))
converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()
open('linear.tflite', 'wb').write(tflite_model)
*참고
이건 Checkpoint 로 model을 save하고 load하는 예시
Training and Save a model
model = Mymodel()
model.compile(optimizer=optimizer, loss=cross_entropy, metrics=metrics)
callbacks = tf.keras.callbacks.ModelCheckpoint(filepath='training_ckpt/cp_{epoc}', save_weights_only=True, monitor='val_loss', save_best_only=True)
model.fit(train_dataset, epochs=100, callbacks=callbacks, validation_data=val_dataset)
Convert model to .tflite
model = Mymodel()
model.compile(optimizer=optimizer, loss=cross_entropy, metrics=metrics)
checkpoint_path = 'training_ckpt/ckpt_100' #your ckpt path
model.load_weights(checkpoint_path)
converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()
C++로 libtensorflowlite.so 와 연동하여 inference해보기
1. Inference코드 작성
#include <stdio.h>
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/model.h"
#include "tensorflow/lite/tools/gen_op_registration.h"
using namespace tflite;
int main(){
std::unique_ptr<tflite::FlatBufferModel> model = tflite::FlatBufferModel::BuildFromFile("linear.tflite");
if(!model){
printf("Failed to mmap model\n");
exit(0);
}
tflite::ops::builtin::BuiltinOpResolver resolver;
std::unique_ptr<tflite::Interpreter> interpreter;
tflite::InterpreterBuilder(*model.get(), resolver)(&interpreter);
// Resize input tensors, if desired.
interpreter->AllocateTensors();
float* input = interpreter->typed_input_tensor<float>(0);
// Dummy input for testing
*input = 2.0;
interpreter->Invoke();
float* output = interpreter->typed_output_tensor<float>(0);
printf("Result is: %f\n", *output);
return 0;
}
2. 폴더 구성
.
└── main
├── linear.cc
└── linear.tflite
│
└── lib
│ └── libtensorflowlite.so
│
└── tensorflow
└── lite
└── *headers*
- tensorflow 폴더의 경우 ~/tensorflow/tensorflow 폴더를 통채로 복사했다
3. CMake빌드
- CMakeLists.txt 예시
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(tflite_test)
SET(CMAKE_BUILD_TYPE Debug)
SET(CMAKE_VERBOSE_MAKEFILE true)
SET(CMAKE_C_COMPILER "g++")
ADD_COMPILE_OPTIONS ( -g -Wall -std=c++11 )
SET (CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections")
INCLUDE_DIRECTORIES(./ ./flatbuffers/include)
LINK_DIRECTORIES(./lib/)
LINK_LIBRARIES(tensorflowlite)
ADD_EXECUTABLE(tflite_test ./linear.cc)
cmake CMakeLists.txt
make
4. 최종 산출물 확인
./tflite_test
Result is: 3.002121
간단하게 so파일과 연동해서 사용해보았다.
안드로이드용 빌드는 나중에 추가로 정리할 예정.
'Study > 머신러닝' 카테고리의 다른 글
Keras에서 Learning Rate 로그 남기기 (0) | 2020.06.16 |
---|---|
Tensorflow CuDNN RNN vs 그냥 RNN 비교 (0) | 2020.05.12 |
Tensorflow2.0 / CUDA / Nvidia driver 호환 (0) | 2020.02.14 |
docker 에서 한국어 설정하기 (0) | 2020.02.05 |
Keras에서 binary_crossentropy와 categorical_crossentropy 차이 (0) | 2019.12.16 |
댓글