• 텐서플로우로 이미지인식 모바일앱 만들어보기 - 4 (모바일사용을 위한 그래프 변환) [머신러닝/딥러닝]
  • 공돌이
    조회 수: 7060, 2017.05.02 14:54:25
  • 2017.05.12: 앞부분 수정사항과 맞추기 위해 폴더명을 data, train 에서 input, output으로 변경했습니다.

    =====================

    이번에는 좀 짧습니다 ㅎ

     

    지난시간 까지 이미지를 학습시켜서 결과물로 .pb 확장자의 그래프파일(protobuf라고 하네요)과 텍스트파일(라벨)을 만들었습니다.

    하지만, 이렇게 만들어진 파일을 바로 모바일에서 읽을수가 없습니다. 모바일에서는 적용할 수 없는 op (operation) 가 일부 들어가 있기 때문이라고 하네요.

     

    그래서 모바일에서 지원하지 않는 op들을 제거해주는 (예를들면 DecodeJpeg 같은거) 작업을 해줘야 하는데 그게 바로 optimize_for_inference 라는 툴이 하는 역할입니다.

     

    2번째 강좌(https://meisteruser.net/devflow/2241) 에서 몇개의 툴들을 빌드 했었는데요...그중에 하나가 바로 optimize_for_inference 입니다.

     

    얘를 이용해서 아래와 같은 포맷으로 변환을 해보겠습니다.

     

    1) 학습된 그래프파일을 최적화하기

    우선, 터미널을 닫으셨다면...다시 터미널을 열고

     

    $ cd tensorflow

    $ source bin/activate 

     

    해서 가상환경을 활성화 한 다음

     

    아래의 명령을 실행해 줍니다.

     

    tensorflow/bazel-bin/tensorflow/python/tools/optimize_for_inference \
    --input=train/output/flower_photos/retrained_graph.pb \
    --output=train/output/flower_photos/optimized_graph.pb \
    --input_names=Mul \
    --output_names=final_result

     

    --input 은 지난시간에 ratrain 툴을 이용해서 만든 결과 그래프를 입력으로 넣어주고요

    --output 은 변환해서 생성할 그래프파일의 위치와 파일명을 지정해주시면 됩니다.

    --input_names 와 output_names 는 입출력 노드명인데, 우리는 스크래치부터 학습시킨게 아니니까, 예제에서 쓰는 노드명을 그대로 입력해주시면 됩니다. (Mul, final_result)

     

    그러면 잠시 시간이 흐른 후 파일이 생성됩니다.

     

    이거 잘 변환됐는지 함 확인해봐야겠죠?

     

     bazel-bin/tensorflow/examples/label_image/label_image \

             --input_layer=Mul \

             --output_layer=final_result \

             --labels=train/output/flower_photos/retrained_labels.txt \

             --image=test.jpg \

             --graph=train/output/flower_photos/optimized_graph.pb

     

    --graph  부분에 retrained_graph.pb 대신에 방금 생성한 optimized_graph를 지정해주시고 나머지는 동일하게 해서 돌려보시면 prediction값이 나옵니다.

     

    2017-05-02 11:43:38.480719: I tensorflow/examples/label_image/main.cc:206] dandelion (1): 0.999632

    2017-05-02 11:43:38.481233: I tensorflow/examples/label_image/main.cc:206] sunflowers (3): 0.000169071

    2017-05-02 11:43:38.481238: I tensorflow/examples/label_image/main.cc:206] tulips (4): 9.32354e-05

    2017-05-02 11:43:38.481242: I tensorflow/examples/label_image/main.cc:206] daisy (0): 7.80553e-05

    2017-05-02 11:43:38.481245: I tensorflow/examples/label_image/main.cc:206] roses (2): 2.74587e-05

     

    dandelion 일 확률 99.9% 나왔네요 ㅎㅎ 잘 변환된것 같습니다.

     

     

    2) Quantize 하기

    지금 파일을 바로 아이폰이나 안드로이드에서 사용할 수도 있지만, 아직 모바일에 최적화되어있는건 아닙니다. optimized_graph.pb 파일의 사이즈를 한번 보시면 거의 90MB전후가 되지요.  이 파일을 zip 으로 압축해보면 거의 압축이 안되는걸 아실 수 있을겁니다.  

    이것은 모델에서 사용된 가중치값들이 전부 조금조금씩 다른 float 값들로 이루어져 있어서 압축이 안되기 때문인데요, 그래서 반올림등의 작업을 통해 비슷한 float 값들을 압축이 가능한 동일한 값으로 변경시키는 작업을 해주는 것이 좋습니다.  (이 float 값들은 주로 가중치 -  weights - 라는 요소로, 텐서플로우 등의 머신러닝의 선형회귀분석을 통한 예측모델 구현에 대단히 중요한 값입니다...만 이 글의 범위를 벗어나니 이정도로만...) 

     

    이게 quantize 과정인데요, 이 과정을 통해서 변환된 결과물은 얼핏보기엔 크기가 비슷해 보이지만 압축해보면 크기가 거의 20MB중반대로 작아지는걸 알 수 있습니다.

     

    나중에 아이폰이나 안드로이드에서 사용하게 되면, 해당 실행파일(.ipa , .apk) 들이 자체적으로 압축되는 형태이므로, 줄어든 형태가 된다고 합니다.

     

    bazel-bin/tensorflow/tools/quantization/quantize_graph \
    --input=train/output/flower_photos/optimized_graph.pb \
    --output=train/output/flower_photos/rounded_graph.pb \
    --output_node_names=final_result \
    --mode=weights_rounded

     

    이렇게 만든 rounded_graph 를 한번 테스트해보겠습니다.

     

     bazel-bin/tensorflow/examples/label_image/label_image \

             --input_layer=Mul \

             --output_layer=final_result \

             --labels=train/output/flower_photos/retrained_labels.txt \

             --image=test.jpg \

             --graph=train/output/flower_photos/rounded_graph.pb

     

    2017-05-02 11:43:39.107280: I tensorflow/examples/label_image/main.cc:206] dandelion (1): 0.999289

    2017-05-02 11:43:39.107830: I tensorflow/examples/label_image/main.cc:206] sunflowers (3): 0.000307598

    2017-05-02 11:43:39.107836: I tensorflow/examples/label_image/main.cc:206] tulips (4): 0.000232983

    2017-05-02 11:43:39.107840: I tensorflow/examples/label_image/main.cc:206] daisy (0): 9.28887e-05

    2017-05-02 11:43:39.107843: I tensorflow/examples/label_image/main.cc:206] roses (2): 7.76977e-05

     

    보시는 바와 같이 살짝 예측치가 내려가긴 했으나 크게 차이가 나지 않으므로 괜찮은것 같습니다.

    (훈련횟수나 이미지소스, classify 방법 등에 따라 차이가 좀 날 수도 있습니다)

     

     

    3) Memory Mapping하기 (옵션)

    이렇게 quantize 된 그래프도 모바일에서 사용하는데에 문제 없지만,

     

    모바일에서는 이 그래프파일을 메모리에 로드해서 예측하는 과정에서 계속 사용해야 하므로, 자칫하면 메모리관련 크래쉬(메모리 오버플로우 등) 가 날 확률이 높아집니다...라고설명을 하네요. 그래서 모바일 상의 메모리 구조에 맞게 memory mapping 해주는 과정이 하나 더 들어가는데...

     

    문제는 안드로이드에서 이렇게 매핑된 그래프파일을 불러들이는 방법을 아직 못찾았습니다...ㅠㅜ

    iOS는 Graph load 하면서 옵션을 줘서 memory mapping된 파일을 불러들일 수 있는데, 안드로이드는 그 옵션을 못찾겠네요...쩝

     

    그래서 아래 내용은 예시만 보여드리고, 다음 회차에서 보여드릴 모바일에서 불러서 사용하는 부분은 quantize 된걸로 하겠습니다(rounded_graph.pb)

    방법을 찾으면 매핑된 그래프로 demo를 동작하는 것을 보여드리는 것으로 하고, 일단은 이렇게 한다 정도만 우선 참고해주세요...

     

     tensorflow/bazel-bin/tensorflow/contrib/util/convert_graphdef_memmapped_format \

             --in_graph=train/output/flower_photos/rounded_graph.pb \

             --out_graph=train/output/flower_photos/mmapped_graph.pb

     

    여기서는 노드명을 줄 필요는 없고, 입력받을 그래프명과 저장할 최종결과물파일명만 지정해주시면 됩니다.

     

    그리고, 매핑된 그래프파일은 모바일에 맞게 재구성된 그래프이므로, PC에서는 읽을수가 없다고 합니다. 그래서 테스트도 어렵네요...-_-;;

     

     

    여기까지 하시면 다음회차에 실제로 사용해 볼 rounded_graph.pb 파일과 retrained_graph.txt(라벨) 파일이 준비되었습니다.

     

    다음회차에서는 android의 경우는 안드로이드스튜디오 사용기준으로 설명을 드릴 예정이니 참고해주시고,

    iOS는 Xcode 를 사용하는 것으로 알려드립니다. 

     

     

    다음 튜토리얼에서 뵈요!