잡동사니

라즈베리파이에 AI 구동환경 설치하기 본문

IT/AI

라즈베리파이에 AI 구동환경 설치하기

yeTi 2020. 5. 6. 17:56

안녕하세요. yeTi입니다.
오늘은 라즈베리파이에 AI를 구동하는 환경을 설정해보려고 합니다.

이를 위해서 Tensorflow를 활용해 모델을 생성하고 Tensorflow Lite를 활용해 모델의 변환 및 라즈베리파이에 AI를 구동했습니다.

작업환경

  • OS : Linux raspberrypi 4.19
  • Tensorflow : 2.1.0
  • Python : 2

Tensorflow

Tensorflow를 설치하고 mnist 모델을 생성합니다.

Tensorflow - Dockerhub

CPU만 사용하는 Tensorflow를 일회성 컨테이너로 사용하고 싶으면 다음과 같이 구동합니다.

$ docker run -it --rm tensorflow/tensorflow bash

Tensorflow에 Jupyter notebook을 포함한 버전을 사용하고 싶으면 다음과 같이 구동합니다.

$ docker run -it --rm -p 8888:8888 tensorflow/tensorflow:latest-jupyter

기존에 사용하던 notebook의 디렉토리를 사용하고 싶으면 -v $(realpath ~/notebooks):/tf/notebooks옵션을 추가합니다.

텐서플로 2.0 시작하기: 초보자용Save and serialize models with Keras를 참고하여 샘플 모델 생성 및 저장하는 방법입니다.

import tensorflow as tf

print(tf.__version__)

mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(x_train, y_train, epochs=5)

model.evaluate(x_test,  y_test, verbose=2)

tf.saved_model.save(model, 'output/mnist/1')

저장한 mnist/1 폴더를 호스트의 위치로 가져온다. 가져오는 방법은 docker에서 볼륨설정을 하던가 컨테이너의 파일을 호스트로 복사하면 됩니다.

Tensorflow Serving

Tensorflow Serving을 설치하여 모델이 정상동작하는지 확인합니다.

샘플 예제

TensorFlow Serving with Docker를 참고하여 샘플 모델을 구동하는 방법입니다.

# Download sample model
$ git clone https://github.com/tensorflow/serving

# Set environment variable for Location of demo models  
$ TESTDATA="/home/hshwang/repo-tenserflow-serving/serving/tensorflow_serving/servables/tensorflow/testdata"

# Start TensorFlow Serving container and open the REST API port  
# Bind port 8501 to 8502
# Bind directory /models/half_plus_two to $TESTDATA/saved_model_half_plus_two_cpu
$ docker run -t --rm -p 8502:8501 \
    -v "$TESTDATA/saved_model_half_plus_two_cpu:/models/half_plus_two" \
    -e MODEL_NAME=half_plus_two tensorflow/serving &

# Query the model using the predict API  
$ curl -d '{"instances": [1.0, 2.0, 5.0]}' \
    -X POST http://localhost:8502/v1/models/half_plus_two:predict

# Returns => { "predictions": [2.5, 3.0, 4.5] }

mnist 구동

이제 앞에서 생성한 mnist/1모델을 Serving해 봅니다.

# Start TensorFlow Serving container and open the REST API port  
# Bind port 8501 to 8502
# Bind directory /models/mnist to /home/hshwang/repo-tenserflow-serving/mnist
$ docker run -t --rm -p 8502:8501 \
    -v "/home/hshwang/repo-tenserflow-serving/mnist:/models/mnist" \
    -e MODEL_NAME=mnist tensorflow/serving &

검증하는 코드는 다음과 같습니다.

import json
import requests
from PIL import Image
import numpy as np

test_image = Image.open('sample_data/mnist_test_image_7.jpg')
pixels = np.array(test_image)/255.0

address = 'http://192.168.5.164:8502/v1/models/mnist:predict'
data = json.dumps({'instances':pixels.tolist()})

result = requests.post(address, data=data)
predictions = json.loads(str(result.content))['predictions']

for prediction in predictions:
    print(np.argmax(prediction))

TensorRT

라즈베리파이에 TensorRT를 활용할 수 있는지 검토해봅니다.

설치 요구사항

  • PyCUDA가 설치되어 있어야 함
  • CUDA Toolkit이 설치되어 있어야 함

Troubleshooting

TensorRT Installation Guide에 따라 PyCUDA설치 중 cuda.h를 찾는 오류가 발생한다.

# pycuda 설치
$ pip install 'pycuda>=2019.1.1'

src/cpp/cuda.hpp:14:10: fatal error: cuda.h: 그런 파일이나 디렉터리가 없습니다
     #include <cuda.h>

이는 CUDA Toolkit을 설치해야되고, 이를 설치하기 위해서는 CUDA에서 지원하는 GPU를 사용하고 있어야 한다.

따라서 GPU를 사용하지 않는 기기에는 CUDA를 설치할 수 없으므로 TensorRT를 사용할 수 없다.

그 밖에 자세한 사항은 TensorRT Installation Guide 참조하면 된다.

Tensorflow Lite

Tensorflow Lite를 라즈베리파이에 설치하고 AI 모델을 구동합니다.

Python quickstart - TensorFlow Lite를 참고하여 TensorFlow Lite interpreter를 설치합니다.

$ pip3 install https://dl.google.com/coral/python/tflite_runtime-2.1.0.post1-cp37-cp37m-linux_armv7l.whl

샘플 예제

Python quickstart - TensorFlow Lite에서 제공하는 샘플 모델을 구동해봅니다.

모델의 구동 환경을 설정합니다.

# Get python file
curl https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/examples/python/label_image.py > label_image.py
# Get photo
curl https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/lite/examples/label_image/testdata/grace_hopper.bmp > grace_hopper.bmp
# Get model
curl https://storage.googleapis.com/download.tensorflow.org/models/mobilenet_v1_2018_02_22/mobilenet_v1_1.0_224.tgz | tar xzv -C .
# Get labels
curl https://storage.googleapis.com/download.tensorflow.org/models/mobilenet_v1_1.0_224_frozen.tgz  | tar xzv -C .  labels.txt

label_image.py를 수정합니다.

import tensorflow as tf -> import tflite_runtime.interpreter as tflite

tf.lite -> tflite

모델을 구동합니다.

python3 label_image.py \
  --model_file mobilenet_v1_1.0_224.tflite \
  --label_file labels.txt \
  --image grace_hopper.bmp

mnist 구동

Converter Python API guide - TensorFlow Lite를 참고하여 모델을 변환합니다.

export_dir = 'output/mnist/1'
converter = tf.lite.TFLiteConverter.from_saved_model(export_dir)
tflite_model = converter.convert()
open(export_dir + '/' + "converted_model.tflite", "wb").write(tflite_model)

TensorFlow Lite inference를 참고하여 interpreter를 구현합니다.

import numpy as np
import tflite_runtime.interpreter as tflite
from PIL import Image

# Read image data
test_image = Image.open('mnist_test_image_7.jpg')
pixels = np.array(test_image, dtype=np.float32)/255.0
pixcels = pixels.tolist()

# Load TFLite model and allocate tensors.
interpreter = tflite.Interpreter(model_path="converted_model.tflite")
interpreter.allocate_tensors()

# Get input and output tensors.
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

# Test model on random input data.
interpreter.set_tensor(input_details[0]['index'], [pixels])

interpreter.invoke()

# The function `get_tensor()` returns a copy of the tensor data.
# Use `tensor()` in order to get a pointer to the tensor.
output_data = interpreter.get_tensor(output_details[0]['index'])
print(np.argmax(output_data))

interpreter.close()
Comments