Tensorflow Lite는 Bazel로 빌드해서 사용 할 수 있다.
여기서는 C++로 간단하게 테스트코드를 만드는 방법까지 정리해보았다.
Tensorflow Lite를 빌드하고 실제 Inference까지 진행하기에는 크게 3단계로 나뉜다
1. Tensorflow 소스코드로부터 libtensorflowlite.so 빌드
2. 모델을 학습한 후 최종 모델을 .tflite형태로 변환
3. C++이나 자바에서 inference할 코드 작성
차근차근 해보도록 하자
libtensorflowlite.so 빌드
1. 원하는 TF 버전 브랜치를 찾아 git clone
2. TF 버전에 맞는 Bazel 버전을 확인 한 후 설치 -> tensorflow 소스의 .bazelversion파일을 확인하면 된다
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 연산의 경우 제약사항이 많은 것 같으니 꼭 확인을 하고 모델링하도록 하자!
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 |
댓글