Mobile Technology

이민예 2019-08-12

Mobile Technology for Deep Learning

Content

  1. TensorFlow 모델 개발

  2. TensorFlow Lite 모델 변환

  3. 모바일 어플리케이션에서 딥러닝 모델 실행

  4. 모델 최적화

1. TensorFlow 모델 개발

기개발된 텐서플로우 모델이 있다면, 이 단계는 skip한다. 텐서플로우의 경량화된 추상화 라이브러리인 tf-slim 라이브러리를 사용하면 성능이 검증된 다양한 CNN 모델들을 (VGGNet, InceptionNet, ResNet, MobileNet) 을 쉽게 사용가능하다.

데이터 셋 준비

기본적으로 MNIST, flowers, cifar10, imagenet 데이터가 존재한다.

git clone https://github.com/tensorflow/models/
cd tfslim/models/research/slim 
$ python download_and_convert_data.py \
    --dataset_name=flowers \
    --dataset_dir=./datasets/flowers

Model Architecture 선택 및 모델 훈련

$ python train_image_classifier.py \
    --train_dir=./output/flowers_train_result \
    --dataset_name=flowers \
    --dataset_split_name=train \
    --dataset_dir=./datasets/flowers \
    --batch_size=50 \
    --model_name=inception_v1 \
    --max_number_of_steps=5000 # 1epoch = 50 step(2500장) / 총 100 epoch 학습

모델 평가

$ python eval_image_classifier.py \
    --alsologtostderr \
    --checkpoint_path=./output/flowers_train_result \
    --dataset_dir=./datasets/flowers \
    --dataset_name=flowers \
    --dataset_split_name=validation \
    --model_name=inception_v1

Reference

https://www.tensorflow.org/lite/convert/python_api?hl=ko

https://www.inovex.de/blog/tensorflow-mobile-training-and-deploying-a-neural-network/

2. TensorFlow Lite 모델 변환

TensorFlow Lite converter

TensorFlow Lite 최적화 컨버터( TensorFlow Lite converter )는 Tensorflow 그래프를 Tensorflow Lite 그래프로 변환한다. 즉, TensorFlow Lite converter 는 TensorFlow Lite FlatBuffer file (.tflite) 를 생성한다. Converter SavedModel directories, tf.keras models, and concrete functions 등 다양한 형태의 변환을 지원한다.

아래는 SavedModel 로부터 convert를 하는 방법이다. 변환 후, FlatBuffer 파일은 클라이언트 기기에 올라가며, TFLite interpreter 해석기를 통해 모델을 커널에서 사용할 수 있도록 한다.

Tensorflow Lite 변환방법

  • SavedModel

import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
tflite_model = converter.convert()
open("converted_model.tflite", "wb").write(tflite_model)
  • tf.Keras (with quantization)

# Convert the model to the TensorFlow Lite format with quantization
converter = tf.lite.TFLiteConverter.from_keras_model(model_2)
converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
tflite_model = converter.convert()

# Save the model to disk
open("sine_model_quantized.tflite", "wb").write(tflite_model)
  • tf.Keras (without quantization)

# Convert the model to the TensorFlow Lite format without quantization
converter = tf.lite.TFLiteConverter.from_keras_model(model_2)
tflite_model = converter.convert()

# Save the model to disk
open("sine_model.tflite", "wb").write(tflite_model)

Reference https://www.tensorflow.org/lite/convert/python_api?hl=ko

3. 모바일 어플리케이션에서 딥러닝 모델 실행

모델을 배포하고, 실행하는 방법에는 여러가지 있다.

  1. TensorFlow Lite 해석기 ( TensorFlow Lite interpreter ) 를 통해 Android NN API 가 tflite 모델을 재구성 하고, 계산 유닛 (CPU/DSP) 에 효율적으로 계산 자원을 분배하여 모델 연산을 가속화 한다.

  2. Firebase ML Tooklit 을 사용하여 Firebase 에 모델을 배포한 후, 실행한다.

3-1. Android NNAPI (Neural Networks API)

  • Android Neural Networks API (NNAPI) 는 On-deivce에서 계산효율적 ML을 위해서 설계된 Android C/C++ API임.

  • TensorFlow Lite 모델은 Android NN API의 Kernel Interpreter로 재구성 및 최적화 되어 계산 하드웨어에 연결됨.

  • Hardware-specific processing을 통해서 neural net inference 속도 개선함.

  • Android 에서 잘 돌아가도록 tflite모델을 재구성하며 계산 자원 분배함.

  • 디바이스가 보유하는 계산 유닛(CPU/CPU/DSP)에 효율적으로 계산 workload를 할당함.

FlatBuffer 파일은 JAVA Interpreter 클래스가 생성될 시, 내부적으로 Native C++ API 를 호출하고 그 안에서 로드된다.

tflite interpreter JAVA 객체 생성

tflite = new Interpreter(loadModelFile(activity));

tflite inference 수행하는 class내부에서 tflite interpreter 실행

  1. JAPA API tflite.run() 이 실행되면 NativeInterpreterWrapper(JNI)를 경유해서 그 안에서 C++ API Interpreter->invoke() 를 호출

  2. C++ API Interpreter -> invoke()안에서 nnapi_delegate->invoke()가 호출

  3. nnapi_delegate->invoke()안에서 nnapi_delegate->BuildGraph() 호출

tflite.run(imgData, labelProbArray);

Android NN API 개요

  1. .tflite 파일을 JAVA/C++ API을 통해서 로드해서,

  2. C++ Android Kernal Interpreter를 통해서 NNAPI클래스로 넘겨주고,

  3. C++NNAPI Op set을 이용해서 내부에서 tflite 모델을 low-level로 내부적으로 빌드한다.

  4. low-level tflite모델을 NNAPI를 통해서 실행한다.

제약사항 : 이 API는 Android 8.1(API 레벨 27) 이상을 실행하는 모든 기기에서 사용할 수 있습니다.

Reference https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/lite/java/demo/app/src/main/java/com/example/android/tflitecamerademo/ImageClassifier.java

3-2. ML Kit 로 Tensorflow Lite 모델을 사용하여 추론

  • Firebase console에서 Android App 과 Firebase 연동

    • Firebase 메타 데이터를 app 디렉토리에 추가

dependencies {
  // ...
  implementation 'com.google.firebase:firebase-ml-model-interpreter:15.0.0'
}
apply plugin: 'com.google.gms.google-services'
  • Firebase에 텐서플로우 라이트 모델 Tensorflow Lite FlatBuffer file (.tflite) 배포

  • 모델을 사용하여 앱 실행

모델 input에 들어가는 이미지 픽셀 사이즈 ( 224*224) 를 명시한다. 또한 일차원의 리스트임을 FirebaseModelInputOutputOptions 통해 명시한다. 오프라인에서도 동작하기 위해서, FirebaseLocalModelSource객체인 registerLocalModelSource을 생성하고, FirebaseModelManager 를 통해 등록한다. 기개발된 모델 파일mobilenet_v1.0_224_quant.tflite 은 assets. 폴더안에 위치시킨다.

MainActivity.java
    /**
     * An instance of the driver class to run model inference with Firebase.
     */
    private FirebaseModelInterpreter mInterpreter;
    /**
     * Data configuration of input & output data of model.
     */
    private FirebaseModelInputOutputOptions mDataOptions;
MainActivity.java
     mLabelList = loadLabelList(this);
        mRun = findViewById(R.id.button_run_custom_model);
        mRun.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                runModelInference();
            }
        });

        int[] inputDims = {DIM_BATCH_SIZE, DIM_IMG_SIZE_X, DIM_IMG_SIZE_Y, DIM_PIXEL_SIZE};
        int[] outputDims = {DIM_BATCH_SIZE, mLabelList.size()};
        try {
            mDataOptions =
                    new FirebaseModelInputOutputOptions.Builder()
                            .setInputFormat(0, FirebaseModelDataType.BYTE, inputDims)
                            .setOutputFormat(0, FirebaseModelDataType.BYTE, outputDims)
                            .build();
            FirebaseModelDownloadConditions conditions = new FirebaseModelDownloadConditions
                    .Builder()
                    .requireWifi()
                    .build();
            FirebaseLocalModelSource localModelSource =
                    new FirebaseLocalModelSource.Builder("asset")
                            .setAssetFilePath(LOCAL_MODEL_ASSET).build();

            FirebaseCloudModelSource cloudSource = new FirebaseCloudModelSource.Builder
                    (HOSTED_MODEL_NAME)
                    .enableModelUpdates(true)
                    .setInitialDownloadConditions(conditions)
                    .setUpdatesDownloadConditions(conditions)  // You could also specify
                    // different conditions
                    // for updates
                    .build();
            FirebaseModelManager manager = FirebaseModelManager.getInstance();
            manager.registerLocalModelSource(localModelSource);
            manager.registerCloudModelSource(cloudSource);
            FirebaseModelOptions modelOptions =
                    new FirebaseModelOptions.Builder()
                            .setCloudModelName(HOSTED_MODEL_NAME)
                            .setLocalModelName("asset")
                            .build();
            mInterpreter = FirebaseModelInterpreter.getInstance(modelOptions);
        } catch (FirebaseMLException e) {
            showToast("Error while setting up the model");
            e.printStackTrace();
        }
  • 모델 예측 실행

runModelInference() 테스트 이미지에 대해 예측값을 돌려주는 함수 작성한다. task.getResult()기개발된 모델에서 분석한 결과값을 제공한다. 그 아래 코드는 정렬하여 최종적인 데이터를 app UI 에 뿌려준다.

MainActivity.java
 private void runModelInference() {
        if (mInterpreter == null) {
            Log.e(TAG, "Image classifier has not been initialized; Skipped.");
            return;
        }
        // Create input data.
        ByteBuffer imgData = convertBitmapToByteBuffer(mSelectedImage, mSelectedImage.getWidth(),
                mSelectedImage.getHeight());

        try {
            FirebaseModelInputs inputs = new FirebaseModelInputs.Builder().add(imgData).build();
            // Here's where the magic happens!!
            mInterpreter
                    .run(inputs, mDataOptions)
                    .continueWith(
                            new Continuation<FirebaseModelOutputs, List<String>>() {
                                @Override
                                public List<String> then(Task<FirebaseModelOutputs> task) {
                                    byte[][] labelProbArray = task.getResult()
                                            .<byte[][]>getOutput(0);
                                    List<String> topLabels = getTopLabels(labelProbArray);
                                    mGraphicOverlay.clear();
                                    GraphicOverlay.Graphic labelGraphic = new LabelGraphic
                                            (mGraphicOverlay, topLabels);
                                    mGraphicOverlay.add(labelGraphic);
                                    return topLabels;
                                }
                            });
        } catch (FirebaseMLException e) {
            e.printStackTrace();
            showToast("Error running model inference");
        }

    }

4. 모델 최적화

Model Optimization Toolkit 양자화를 사용하여 기존 신경망의 부동 소수점 수를 줄여 모델의 연산량과 용량을 대폭 줄이어, 정확성을 증가시킨다.

Android Wear App 개발

프로젝트 생성

  • “Phone and Tablet” 항목을 선택 후 Minimum SDK 를 API 18: Android 4.3 (Jelly Bean) 로 선택합니다.

  • “Waer” 항목을 선택 후 Minimum SDK 를 API 20: Android 4.4 (KitKat Wear) 로 선택합니다.

  • 프로젝트 위자드가 완료되면, “mobile” 과 “wear” 두 개의 모듈이 포함된 프로젝트가 생성됩니다. 말 그대로 “mobile” 모듈은 휴대 단말에 설치될 앱을 위한 모듈이며, “wear” 모듈은 안드로이드 웨어 디바이스에서 동작하는 앱을 위한 모듈입니다.

Android App 개발

Android Life Cycle

프로젝트 기간: ~ 2020.03

심전도 열람 및 저장이 가능한 모바일 어플리케이션 개발

패치형 심전도 측정기기는 Bluetooth를 활용하여 실시간 환자의 심전도를 모바일 어플리케이션으로 전송합니다. 모바일 어플리케이션은 다음의 기능을 수행합니다.‌

모바일 어플리케이션 기능명세

  • 구글 Firebase에 심전도 데이터 저장

  • 심전도 그래프 시각화

모바일 어플리케이션 기획

  • 사용자 : 환자

  • 목적 : 환자 본인의 심전도 데이터 열람

  • App의 특징

    • 환자의 진단 기록을 다루기 때문 보안 중요

    • 사용자에게 친근한 유저 인터페이스 개발 필요

  • Mobile APP Technology Stack

Front-End

Back-End

DataBase

OS

React-native

JAVA or Kotlin

Firebase

Android OS

프로젝트 기간: 2014.06 - 2014.09

식당 정보 제공 어플리케이션 앱 (배고픈 한동이) 개발

  • 사용자: 포항 주민

  • 역할 : 모바일 어플리케이션 개발

  • 업무 :

    • Google 지도 API 개발

    • 상세 화면 개발

  • 내용 : 기존 교내 식당 정보를 제공하는 어플리케이션이 있었으나, 음식에 대한 학생들의 의견을 학생 식당에게 전달하여 음식의 질을 개선하는 데까지는 아쉬운 점이 있었습니다. 이러한 점에 착안하여 단순히 정보를 제공받는 패러다임을 바꾸고, 소통의 장을 형성하였습니다. 기획부터 UI/UX를 고려한 화면설계, 안드로이드 개발과 협업, 홍보와 마케팅까지 많은 고민과 회의 끝에 지난해 9월 포항 맛집 앱을 출시할 수 있게 되었습니다. 그리고 지금은 많은 이들의 호응으로 약 3천명의 유저를 확보하고 있습니다.

  • Mobile APP Technology Stack

Front-End

Back-End

DataBase

OS

XML layouts

JAVA

MySQL

Android OS

프로젝트 기간: 2014.09 - 2014.11

외부 거주자들을 위한 원룸 앱 (집찾는 한동이) 개발

  • 사용자: 포항 주민

  • 역할 : 모바일 어플리케이션 개발

  • 업무 :

    • Google 지도 API 개발

    • 상세 화면 개발

  • 내용 : 배고픈 한동이 프로젝트와 동일하게 Android, MySqL, 그리고 PHP를 사용하였습니다. 구글지도 Open API를 사용하여 지도 위에 각 지역에 해당하는 부동산 매물 정보를 표시하였습니다. ListView를 사용하여 매물을 보여주었고, 매물 상세 정보 페이지 에서는 방의 내부 사진들을 슬라이딩하여 볼 수 있도록 하였습니다. 각 배고픈 한동이와 집 찾는 한동이 안드로이드 어플리케이션을 개발하면서 새로 등록되는 부동산 매물 정보와 식당 정보들을 쉽게 관리하기 위한 관리자 시스템이 필요하였습니다. 서버언어 PHP와 , MySqL, JavaScript, Ajax를 사용하여 웹을 개발하였고, BootStrap 프레임워크를 이용하였습니다.

  • Mobile APP Technology Stack

Front-End

Back-End

DataBase

OS

XML layouts

JAVA

MySQL

Android OS

졸업작품 프로젝트 기간: 2014.12 - 2015.02

재난 대응 어플리케이션 (BeeSafe) 개발

  • 사용자: 재난을 대피하는 모든 사람

  • 역할 : 모바일 어플리케이션 개발

  • 업무 :

    • 신고 및 카카오톡 API 연동 구현

    • 대피요령 Q&A 게시판 구축

  • 내용 : 2014년, 세월호와 고양터미널 화재사건, 그리고 메르스로 많은 사람들이 목숨을 잃었습니다. 재난 대비 요령을 알고 있었다면 살 수 있지 않았을까 라는 의문을 가지고 재난 대응 어플리케이션이라는 졸업 작품의 주제를 선택하였습니다. 119, 112와 같은 전담 기관에 앱을 사용해 신고할 시 GPS 정보를 함께 보내주어 사고자의 위치를 신속 정확하게 알 수 있도록 하였고, Azure Paas와 SQL Server을 사용하여 실시간으로 대피요령을 알 수 있도록 QnA게시판을 구축하였습니다. 그 외 GitHub Paging 기능으로 iFrame을 사용하여 국민 대피 요령 정보를 동영상과 함께 보여주었습니다.

  • Mobile APP Technology Stack

Front-End

Back-End

DataBase

OS

XML layouts

JAVA

MySQL

Android OS

프로젝트 기간: 2015.07 - 2015.08

경기 점수판 앱 (몇대몇) 개발

  • 사용자: 스포츠를 좋아하는 사람

  • 역할 : 모바일 어플리케이션 개발

  • 업무 :

    • 점수판 HW 기기와의 블루투스 통신 개발

  • 내용 : K글로벌 IOT스타트업 첼린지에서 상을 수상한 BYIT 스타트업에서 소프트웨어 엔지니어로서 근무하였습니다. 경기 점수판 하드웨어와 안드로이드 앱의 통신을 위해 Classic Bluetooth 을 사용하여 블루투스 통신을 하였습니다.

  • Mobile APP Technology Stack

Front-End

Back-End

DataBase

OS

XML layouts

JAVA

MySQL

Android OS

Last updated