Tech Blog

TinyML を試してみる

Cover Image for TinyML を試してみる

社内で TinyML の話題が上がったので、身の回りにあるもので環境を構築して Hello World する
* ハンズオンのみ Machine Learning, TesnsorFlow Lite 等詳しい内容には触れません

今回の環境

TL;DR

1. TensorFlow 環境構築

  // .devcontainer/devcontainer.json
+ // For format details, see https://aka.ms/devcontainer.json. For config options, see the
+ // README at: https://github.com/devcontainers/templates/tree/main/src/debian
+ {
+   "name": "tflite-micro",
+   // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
+   "image": "mcr.microsoft.com/devcontainers/base:bullseye",
+
+   // Features to add to the dev container. More info: https://containers.dev/features.
+   "features": {
+     "ghcr.io/devcontainers/features/git:1": {},
+     "ghcr.io/devcontainers/features/python:1": {
+       "version": "3.11.8",
+       "installJupyterlab": true
+     }
+   },
+
+   // Use 'forwardPorts' to make a list of ports inside the container available locally.
+   // "forwardPorts": [],
+
+   // Use 'postCreateCommand' to run commands after the container is created.
+   // "postCreateCommand": "pip3 install --user -r requirements.txt",
+
+   // Configure tool-specific properties.
+   "customizations": {
+     "vscode": {
+       "extensions": [
+         "ms-toolsai.jupyter"
+       ]
+     }
+   }
+
+   // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
+ 	// "remoteUser": "root"
+ }
+

2.Jupyter Notebook ファイルを入手する

* この記事執筆時点では train_hello_world_model.ipynbtensorflow/tflite-micro #1822 で削除されているため過去のコミットから復元する

git init
Initialized empty Git repository in ../tflite-micro/.git/
git remote add origin git@github.com:tensorflow/tflite-micro.git
git fetch origin 1df426d984288894367f6aa3a914eb998494e3bd
Warning: Permanently added the ECDSA host key for IP address 'XXX.XXX.XXX.XXX' to the list of known hosts.
From github.com:tensorflow/tflite-micro
 * branch            1df426d984288894367f6aa3a914eb998494e3bd -> FETCH_HEAD
git restore --source FETCH_HEAD -- tensorflow/lite/micro/examples/hello_world/train/train_hello_world_model.ipynb

ARM マシンに対応した tensorflow パッケージ (AWS の tensorflow-cpu-aws) は 2.10 以降のため最新の安定バージョンを指定する

  // tensorflow/lite/micro/examples/hello_world/train/train_hello_world_model.ipynb
  ...
      {
        "cell_type": "code",
        "execution_count": 2,
        "metadata": {
          "colab": {
            "base_uri": "https://localhost:8080/"
          },
          "id": "cr1VLfotanf6",
          "outputId": "510567d6-300e-40e2-f5b8-c3520a3f3a8b"
        },
        "outputs": [
          {
            "name": "stdout",
            "output_type": "stream",
            "text": [
              "Requirement already satisfied: tensorflow==2.4.0rc0 in /usr/local/lib/python3.6/dist-packages (2.4.0rc0)\n",
              "Requirement already satisfied: termcolor~=1.1.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.4.0rc0) (1.1.0)\n",
              "Requirement already satisfied: gast==0.3.3 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.4.0rc0) (0.3.3)\n",
  ...
            ]
          }
        ],
        "source": [
-         "! pip install tensorflow==2.4.0"
+         "! pip install tensorflow==2.15.0"
        ]
      },
  ...

3.TensorFlow モデルの構築と TensorFlow Lite モデルへの変換

Run All で全て実行する
* 詳しい処理内容を知りたい人は順番に沿って実行

train_hello_world_model.ipynb

cat ./tensorflow/lite/micro/examples/hello_world/train/models/model.cc
unsigned char g_model[] = {
  0x1c, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x14, 0x00, 0x20, 0x00,
  0x1c, 0x00, 0x18, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
  0x98, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x1c, 0x03, 0x00, 0x00,
  0x2c, 0x03, 0x00, 0x00, 0x30, 0x09, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x60, 0xf7, 0xff, 0xff,
  0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
  0x44, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x73, 0x65, 0x72, 0x76,
  0x65, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x73, 0x65, 0x72, 0x76,
  0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xbc, 0xff, 0xff, 0xff,
  0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
  0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x34, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x76, 0xfd, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
  0x0d, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x32, 0x5f,
  0x69, 0x6e, 0x70, 0x75, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
  0x08, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x13, 0x00, 0x00, 0x00, 0x6d, 0x69, 0x6e, 0x5f, 0x72, 0x75, 0x6e, 0x74,
  0x69, 0x6d, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00,
  0x0c, 0x00, 0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x48, 0x02, 0x00, 0x00,
  0x34, 0x02, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00,
  0x6c, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
  0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
...
  0x0c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x09
};
unsigned int g_model_len = 2488;

4.Microcontroller 環境構築

  // .devcontainer/devcontainer.json
+ // For format details, see https://aka.ms/devcontainer.json. For config options, see the
+ // README at: https://github.com/devcontainers/templates/tree/main/src/debian
+ {
+   "name": "myproject",
+   // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
+   "image": "mcr.microsoft.com/devcontainers/base:bullseye",
+   "features": {
+     "ghcr.io/devcontainers/features/git:1": {}
+   },
+
+   "workspaceFolder": "/workspaces/myproject",
+   "workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/myproject,type=bind,consistency=cached",
+   "mounts": [
+     "source=/dev,target=/dev,type=bind,consistency=consistent"
+   ],
+
+   // Use 'forwardPorts' to make a list of ports inside the container available locally.
+   // "forwardPorts": [],
+
+   // Use 'postCreateCommand' to run commands after the container is created.
+   "postCreateCommand": ".devcontainer/postcreate.sh",
+
+   // Configure tool-specific properties.
+   "customizations": {
+     "vscode": {
+       "extensions": [
+         "sony-spresense.spresense-vscode-ide"
+       ]
+     }
+   },
+
+   "remoteEnv": {
+     "EDITOR": "code --wait"
+   }
+
+   // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
+   // "remoteUser": "root"
+ }
+
  # .devcontainer/postcreate.sh
+ #!/bin/sh
+ # vim:sw=4:ts=4:et
+ set -e
+
+ git config --global --add safe.directory $(pwd)
+
+ sudo usermod -a -G dialout $(whoami)
+
+ cd /tmp
+ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/sonydevworld/spresense/master/install-tools.sh)"
+
+ cat << EOF | sudo tee -a /etc/profile > /dev/null
+ source ~/spresenseenv/setup
+ EOF
+
+ sudo chown $(whoami) /workspaces
+ cd /workspaces
+
+ if [ ! -d "/workspaces/spresense" ]; then
+     git clone --depth 1 --recursive https://github.com/sonydevworld/spresense.git
+ fi
+

5. IDE 設定

コマンドパレット > Spresense: Workspace setup wizard

Spresense: Workspace setup wizard

コマンドパレット > Spresense: Serial port selection

Spresense: Serial port selection

6. ビルド

source tools/build-env.sh
Warning: Spresense user application directory is not set.
         Please run
         $ spr-set-approot <application home directory>
=======================================
   SDK_VERSION = SDK3.2.0
 NUTTX_VERSION = 12.3.0
 SPRESENSE_SDK = /workspaces/spresense
SPRESENSE_HOME =
   GCC_VERSION = arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824 (release)
          HOST = Linux aarch64
=======================================
tools/config.py examples/hello
make -j
Create version.h
make[2]: Nothing to be done for `context'.
make[2]: Nothing to be done for `context'.
make[2]: Nothing to be done for `context'.
make[2]: Nothing to be done for `context'.
make[2]: Nothing to be done for `context'.
...
IN: /workspaces/spresense/sdk/apps/libapps.a -> staging/libapps.a
make[3]: `libboard.a' is up to date.
LD: nuttx
Generating: nuttx.spk
tools/cxd56/mkspk -c2 nuttx nuttx nuttx.spk;
File nuttx.spk is successfully created.
Done.

7. Spresense を接続

Spresense

8. 書き込み

tools/flash.sh -c /dev/cu.usbserial-210 -b 115200 nuttx.spk
>> Install files ...
install -b 115200
Install nuttx.spk
|0%-----------------------------50%------------------------------100%|
######################################################################

159632 bytes loaded.
Package validation is OK.
Saving package to "nuttx"
updater# sync
updater# Restarting the board ...
reboot

9. 確認

Teleplot

参考にしたページ