🏌️

Raspberry Pi Pico で独自学習した TensorFlow Lite のモデルを使う

2021/02/12に公開

はじめに

Raspberry Pi Pico 楽しいですよね。先日は、Raspberry Pi Pico のボタンを使って Go の if err != nil {...} を自動入力するボタンを作りました。

https://twitter.com/mattn_jp/status/1358067345088892928

先日から、Raspberry Pi Pico で TensorFlow Lite を動かすのを試していたのですが、独自モデルでどうしても動かずハマっていた問題が昨日解決しました。

できあがったもの

XOR ゲートを推論するモデルを組み込み、シリアルポートからの入力で LED を付けたり消したりします。

https://twitter.com/mattn_jp/status/1360041410930429953

まずはモデルを作る

といっても難しい事はなく、単に普通の学習をさせるだけです。

import tensorflow as tf
from tensorflow import keras
import numpy as np

x_train = np.array([[0, 0],
                    [1, 0],
                    [0, 1],
                    [1, 1]]).astype(np.float32)

y_train = np.array([0,
                    1,
                    1,
                    0]).astype(np.float32)


model = tf.keras.Sequential()
model.add(keras.layers.Dense(16, activation='relu', input_shape=(2,)))
model.add(keras.layers.Dense(16, activation='relu'))
model.add(keras.layers.Dense(1))
model.compile(optimizer='adam', loss="mse", metrics=["mae"])
history = model.fit(x_train, y_train, epochs=500, batch_size=4)
model.save('saved_model')


def representative_dataset():
    for i in range(4):
        yield([x_train[i]])


converter = tf.lite.TFLiteConverter.from_saved_model("saved_model")
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.float32
converter.inference_output_type = tf.float32
converter.representative_dataset = representative_dataset
model_tflite = converter.convert()

with open('xor_model.tflite', 'wb') as f:
    f.write(model_tflite)

気を付ける点としては、quantization 無しで作る所くらいです。

コードを書く

出来上がった tflite のモデルファイルを xxd というツールを使ってC言語のバイト配列に置き換えます。

$ xxd -i xor_model.tflite > model.c
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"

#define TF_LITE_STATIC_MEMORY
#include "tensorflow/lite/micro/all_ops_resolver.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "tensorflow/lite/version.h"

alignas(8) const unsigned char xor_model_tflite[] = {
  0x20, 0x00, 0x00, 0x00, 0x54, 0x46, 0x4c, 0x33, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x12, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00,
  0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x12, 0x00, 0x00, 0x00,
  0x03, 0x00, 0x00, 0x00, 0x8c, 0x0b, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00,
  0x00, 0x03, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
  0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x0b, 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, 0xb8, 0x02, 0x00, 0x00,
  0xa4, 0x02, 0x00, 0x00, 0x48, 0x02, 0x00, 0x00, 0xe4, 0x01, 0x00, 0x00,
  0xd0, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
  0x64, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
  0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe6, 0xfd, 0xff, 0xff,
  0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x35, 0x2e,
  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x10, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xfd, 0xff, 0xff,
  0x00, 0x00, 0x00, 0x00, 0x36, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
  0x10, 0x00, 0x00, 0x00, 0x81, 0xb8, 0x46, 0x3e, 0xfd, 0x20, 0x1f, 0xcc,
  0xbb, 0xd8, 0x5a, 0xde, 0x19, 0xf2, 0xe1, 0xc4, 0x00, 0x00, 0x00, 0x00,
  0x56, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
  0xf1, 0x30, 0xd2, 0x18, 0x0c, 0xb8, 0x14, 0x99, 0xcc, 0xdb, 0x4e, 0x08,
  0x1d, 0xea, 0x7f, 0xfc, 0x3b, 0x10, 0xb0, 0x0a, 0x24, 0xe4, 0xdb, 0x1a,
  0x4c, 0xc9, 0xd1, 0x00, 0x4a, 0xb0, 0xaf, 0x1f, 0x40, 0x17, 0x48, 0x4c,
  0x34, 0x3c, 0x24, 0x20, 0x20, 0xd2, 0x5a, 0x5a, 0x49, 0x59, 0x08, 0xb3,
  0x98, 0xdc, 0x67, 0x4f, 0xbb, 0xeb, 0x39, 0xcb, 0xb7, 0x10, 0x93, 0x39,
  0x12, 0x29, 0xd5, 0x19, 0x0f, 0xba, 0xeb, 0xd3, 0xdb, 0x04, 0xdc, 0x25,
  0x4a, 0x3b, 0xe7, 0xed, 0xad, 0xb7, 0xae, 0x43, 0x3b, 0x1c, 0x25, 0x19,
  0x4e, 0xd0, 0xb6, 0x53, 0xfa, 0xf2, 0xbd, 0xde, 0x27, 0x1a, 0x0d, 0x4b,
  0x56, 0x17, 0x67, 0xee, 0xf4, 0x04, 0xf8, 0x71, 0x03, 0xe4, 0x1c, 0xdf,
  0xe9, 0x3a, 0x0c, 0x4e, 0xeb, 0xf0, 0x30, 0xbd, 0x42, 0x39, 0xec, 0xf9,
  0x4b, 0x49, 0x22, 0xc1, 0xbe, 0x21, 0xf5, 0xcd, 0xf3, 0xe6, 0x12, 0x18,
  0xe5, 0xc8, 0xd9, 0xbb, 0xef, 0x05, 0x4d, 0x07, 0x45, 0xff, 0xb5, 0xc5,
  0x29, 0x26, 0x1a, 0xd8, 0x38, 0xb9, 0xec, 0x09, 0xf9, 0xb2, 0x2f, 0xf7,
  0xd5, 0xb0, 0xff, 0x44, 0x41, 0x5d, 0x23, 0x47, 0xc8, 0x33, 0xdb, 0x16,
  0x1c, 0xd0, 0x5c, 0x3e, 0xe5, 0x4e, 0xfe, 0xc2, 0x42, 0xad, 0xd3, 0x35,
  0x48, 0xc9, 0xf4, 0x42, 0xf2, 0x1f, 0x43, 0xad, 0x2f, 0xbb, 0x15, 0xc0,
  0x0f, 0xef, 0x06, 0x53, 0x29, 0xef, 0xe5, 0x55, 0x11, 0xe5, 0x3c, 0x19,
  0xee, 0x1b, 0xda, 0x1e, 0xe3, 0x0a, 0xb0, 0xd1, 0xe8, 0xe9, 0x1a, 0x20,
  0xb1, 0xba, 0x4b, 0xd3, 0xaf, 0x14, 0xd9, 0x33, 0x19, 0xf7, 0xfd, 0x2a,
  0xbe, 0x40, 0x19, 0x35, 0x02, 0xae, 0xce, 0x15, 0xf8, 0x12, 0xab, 0xb3,
  0x2c, 0x3e, 0x34, 0xa4, 0x1a, 0x0e, 0x26, 0x1f, 0x37, 0xc4, 0x0d, 0x01,
  0x1c, 0xf1, 0x9b, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x66, 0xff, 0xff, 0xff,
  0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x99, 0x72, 0x97, 0x59,
  0x55, 0xb2, 0x35, 0xef, 0x2b, 0x32, 0xa9, 0x58, 0xaf, 0x07, 0x9b, 0x5b,
  0xaf, 0x9c, 0x16, 0x47, 0xc6, 0x23, 0xab, 0x54, 0xd8, 0xe1, 0x68, 0x9b,
  0xe6, 0x14, 0x81, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x96, 0xff, 0xff, 0xff,
  0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x49, 0x09, 0x00, 0x00,
  0xa6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
  0xc7, 0x27, 0x00, 0x00, 0xfc, 0xe8, 0xff, 0xff, 0x1a, 0x14, 0x00, 0x00,
  0xf8, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x14, 0x00, 0x00,
  0xbf, 0x11, 0x00, 0x00, 0x53, 0xdb, 0xff, 0xff, 0x97, 0xe8, 0xff, 0xff,
  0xef, 0xee, 0xff, 0xff, 0xdf, 0x21, 0x00, 0x00, 0xcb, 0x33, 0x00, 0x00,
  0xf2, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xe3, 0xff, 0xff,
  0x0a, 0xe7, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
  0xe6, 0xf5, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xc9, 0x12, 0x00, 0x00, 0xfc, 0xed, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  0x3a, 0xf6, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x49, 0xea, 0xff, 0xff, 0x95, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x1a, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x50, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0xff, 0xff,
  0x0f, 0x00, 0x00, 0x00, 0x4d, 0x4c, 0x49, 0x52, 0x20, 0x43, 0x6f, 0x6e,
  0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x2e, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x04, 0x00,
  0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00,
  0x58, 0x01, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00,
  0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
  0x04, 0x01, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
  0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1a, 0xff, 0xff, 0xff,
  0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x09, 0x00, 0x00, 0x00, 0xca, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x08,
  0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
  0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x10, 0x00,
  0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x00, 0x00, 0x00,
  0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xba, 0xff, 0xff, 0xff,
  0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x08, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00,
  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
  0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
  0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x0a, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
  0x68, 0x06, 0x00, 0x00, 0xf4, 0x05, 0x00, 0x00, 0x8c, 0x05, 0x00, 0x00,
  0x38, 0x05, 0x00, 0x00, 0x8c, 0x04, 0x00, 0x00, 0xd8, 0x03, 0x00, 0x00,
  0x24, 0x03, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00,
  0x90, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0xc8, 0xff, 0xff, 0xff, 0x28, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x49, 0x64, 0x65, 0x6e,
  0x74, 0x69, 0x74, 0x79, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x10, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
  0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
  0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x00,
  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x60, 0xfa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x6c, 0x00, 0x00, 0x00,
  0x0a, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
  0x01, 0x00, 0x00, 0x00, 0x4c, 0xfa, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00,
  0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0x01, 0x00, 0x00, 0x00, 0x76, 0x80, 0x80, 0x3b, 0x01, 0x00, 0x00, 0x00,
  0xe6, 0xff, 0x7f, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0xb4,
  0x0d, 0x00, 0x00, 0x00, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79,
  0x5f, 0x69, 0x6e, 0x74, 0x38, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xfa, 0xff, 0xff,
  0x00, 0x00, 0x00, 0x09, 0xf4, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
  0x50, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
  0xcc, 0xfa, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
  0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
  0x41, 0x32, 0x38, 0x3b, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x7a, 0x37, 0x3f,
  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00,
  0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64,
  0x65, 0x6e, 0x73, 0x65, 0x5f, 0x31, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b,
  0x53, 0x74, 0x61, 0x74, 0x65, 0x66, 0x75, 0x6c, 0x50, 0x61, 0x72, 0x74,
  0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, 0x61, 0x6c, 0x6c, 0x2f,
  0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64,
  0x65, 0x6e, 0x73, 0x65, 0x5f, 0x31, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b,
  0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64,
  0x65, 0x6e, 0x73, 0x65, 0x5f, 0x31, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41,
  0x64, 0x64, 0x3b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x66, 0x75, 0x6c, 0x50,
  0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, 0x61,
  0x6c, 0x6c, 0x2f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61,
  0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x31, 0x2f, 0x42, 0x69,
  0x61, 0x73, 0x41, 0x64, 0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe8, 0xfb, 0xff, 0xff,
  0x00, 0x00, 0x00, 0x09, 0xec, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x50, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
  0xd4, 0xfb, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
  0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
  0x6b, 0x57, 0xed, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x14, 0x6a, 0xec, 0x3e,
  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00,
  0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64,
  0x65, 0x6e, 0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b, 0x53, 0x74,
  0x61, 0x74, 0x65, 0x66, 0x75, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74,
  0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, 0x61, 0x6c, 0x6c, 0x2f, 0x73, 0x65,
  0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e,
  0x73, 0x65, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b, 0x73, 0x65, 0x71, 0x75,
  0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65,
  0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, 0x64, 0x64, 0x3b, 0x53, 0x74, 0x61,
  0x74, 0x65, 0x66, 0x75, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69,
  0x6f, 0x6e, 0x65, 0x64, 0x43, 0x61, 0x6c, 0x6c, 0x2f, 0x73, 0x65, 0x71,
  0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73,
  0x65, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, 0x64, 0x64, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
  0x52, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x9c, 0x00, 0x00, 0x00,
  0x07, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0xc4, 0xfc, 0xff, 0xff, 0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
  0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x14, 0xcb, 0xef, 0x3b, 0x01, 0x00, 0x00, 0x00,
  0x10, 0xf1, 0x28, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xeb, 0x6d, 0xbf,
  0x4b, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69,
  0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x32, 0x2f, 0x4d,
  0x61, 0x74, 0x4d, 0x75, 0x6c, 0x3b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x66,
  0x75, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65,
  0x64, 0x43, 0x61, 0x6c, 0x6c, 0x2f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e,
  0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x32,
  0x2f, 0x4d, 0x61, 0x74, 0x4d, 0x75, 0x6c, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0xfe, 0xff, 0xff,
  0x00, 0x00, 0x00, 0x09, 0x9c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
  0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x74, 0xfd, 0xff, 0xff,
  0x30, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x1d, 0x80, 0xaa, 0x3b, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x2b, 0x29, 0x3f,
  0x01, 0x00, 0x00, 0x00, 0x36, 0xab, 0x11, 0xbf, 0x4b, 0x00, 0x00, 0x00,
  0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2f, 0x64,
  0x65, 0x6e, 0x73, 0x65, 0x5f, 0x31, 0x2f, 0x4d, 0x61, 0x74, 0x4d, 0x75,
  0x6c, 0x3b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x66, 0x75, 0x6c, 0x50, 0x61,
  0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43, 0x61, 0x6c,
  0x6c, 0x2f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
  0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x31, 0x2f, 0x4d, 0x61, 0x74,
  0x4d, 0x75, 0x6c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
  0x10, 0x00, 0x00, 0x00, 0xb2, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09,
  0x94, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x24, 0xfe, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00,
  0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x28, 0x01, 0x92, 0x3b, 0x01, 0x00, 0x00, 0x00,
  0xdf, 0xc6, 0x01, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x26, 0xdd, 0x10, 0xbf,
  0x47, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69,
  0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x2f, 0x4d, 0x61, 0x74,
  0x4d, 0x75, 0x6c, 0x3b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x66, 0x75, 0x6c,
  0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x43,
  0x61, 0x6c, 0x6c, 0x2f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69,
  0x61, 0x6c, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x2f, 0x4d, 0x61, 0x74,
  0x4d, 0x75, 0x6c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x00, 0x5a, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02,
  0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x4c, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x89, 0xac, 0x37,
  0x09, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f,
  0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0xaa, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x00,
  0x03, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x9c, 0xff, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd4, 0x12, 0x1e, 0x37,
  0x09, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f,
  0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0c, 0x00,
  0x10, 0x00, 0x14, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
  0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
  0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xbc, 0x93, 0x92, 0x37,
  0x09, 0x00, 0x00, 0x00, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x5f,
  0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
  0x14, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x10, 0x00,
  0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x14, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x09, 0x7c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x5c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
  0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00,
  0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
  0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
  0x81, 0x80, 0x80, 0x3b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
  0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f,
  0x69, 0x6e, 0x74, 0x38, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
  0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00,
  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
  0x00, 0x72, 0x0a, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00,
  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00

};

namespace {
  tflite::ErrorReporter* error_reporter = nullptr;
  const tflite::Model* model = nullptr;
  tflite::MicroInterpreter* interpreter = nullptr;
  TfLiteTensor* input = nullptr;
  TfLiteTensor* output = nullptr;
  constexpr int kTensorArenaSize = 2000;
  uint8_t tensor_arena[kTensorArenaSize];
}

int main() {
  stdio_init_all();
  gpio_init(25);
  gpio_set_dir(25, GPIO_OUT);

  // NOLINTNEXTLINE(runtime-global-variables)
  static tflite::MicroErrorReporter micro_error_reporter;
  error_reporter = &micro_error_reporter;

  model = tflite::GetModel(xor_model_tflite);

  if (model->version() != TFLITE_SCHEMA_VERSION) {
    TF_LITE_REPORT_ERROR(error_reporter,
                         "Model provided is schema version %d not equal "
                         "to supported version %d.",
                         model->version(), TFLITE_SCHEMA_VERSION);
    return 1;
  }

  // This pulls in all the operation implementations we need.
  // NOLINTNEXTLINE(runtime-global-variables)
  static tflite::AllOpsResolver resolver;

  // Build an interpreter to run the model with.
  static tflite::MicroInterpreter static_interpreter(
      model, resolver, tensor_arena, kTensorArenaSize, error_reporter);
  interpreter = &static_interpreter;

  // Allocate memory from the tensor_arena for the model's tensors.
  TfLiteStatus status = interpreter->AllocateTensors();
  if (status != kTfLiteOk) {
    TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
    return 1;
  }

  input = interpreter->input_tensor(0);
  output = interpreter->output_tensor(0);

  while (true) {
    int c1 = getchar();
    printf("%c\n", c1);
    int c2 = getchar();
    printf("%c\n", c2);
    input->data.f[0] = c1 == '1' ? 1.0f : 0.0f;
    input->data.f[1] = c2 == '1' ? 1.0f : 0.0f;
    status = interpreter->Invoke();
    if (status != kTfLiteOk) {
      TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
      continue;
    }
    int on = output->data.f[0] > 0.5 ? 1 : 0;
    printf("XOR(%d, %d) = %d\n",
      c1 == '1' ? 1 : 0,
      c2 == '1' ? 1 : 0,
      on);
    gpio_put(25, on);
  }
  return 0;
}

ここで注意なのですが、ソースに埋め込んでモデルを作る場合は TF_LITE_STATIC_MEMORY を定義しておく事です。どうやらこれを付けないと期待していない delete オペレータが埋め込まれてしまう為、正しく動作しない様です。

// C++ will automatically create class-specific delete operators for virtual
// objects, which by default call the global delete function. For embedded
// applications we want to avoid this, and won't be calling new/delete on these
// objects, so we need to override the default implementation with one that does
// nothing to avoid linking in ::delete().
// This macro needs to be included in all subclasses of a virtual base class in
// the private section.
#ifdef TF_LITE_STATIC_MEMORY
#define TF_LITE_REMOVE_VIRTUAL_DELETE \
  void operator delete(void* p) {}
#else
#define TF_LITE_REMOVE_VIRTUAL_DELETE
#endif

ビルドして転送

ビルドするには pico-examples の直下に tflite/tflite_xor というディレクトリを作り tflite の直下に1つ CMakeLists.txt を作成

if (NOT PICO_NO_HARDWARE)
    add_subdirectory(tflite_xor)
endif ()

そして tflite_xor の下にも作ります。

link_directories(${CMAKE_SOURCE_DIR}/lib)

add_executable(tflite_xor
main.cxx
)

set_target_properties(
  tflite_xor
  PROPERTIES
  COMPILE_FLAGS -fno-rtti
  COMPILE_FLAGS -fno-exceptions
  COMPILE_FLAGS -fno-threadsafe-statics
  COMPILE_FLAGS -nostdlib
)


# Pull in our pico_stdlib which aggregates commonly used features
target_link_libraries(tflite_xor pico_stdlib pico-tflmicro)

pico_enable_stdio_usb(tflite_xor 1)
pico_enable_stdio_uart(tflite_xor 0)

pico_add_extra_outputs(tflite_xor)

# add url via pico_set_program_url
example_auto_set_url(tflite_xor)

target_include_directories(tflite_xor
  PRIVATE
  "c:/dev/pico-tflmicro/src"
  "c:/dev/pico-tflmicro/src/third_party/flatbuffers/include"
)

Windows で開発しているのでフルパスが入ってしまっていますが、ご自身の環境に合わせて修正下さい。シリアルポートを使うのであれば pico_enable_stdio_usb を 1 で設定するのをお忘れなく。

出来上がった pico-examples/build/tflite/tflite_xor/tflite_xor.uf2 を Raspberry Pi Pico に転送したら完成。

おわりに

TF_LITE_STATIC_MEMORY に気付かず半日ほど時間を溶かしてしまいましたが、なんとか動きました。カメラやディスプレイ、Wi-Fi が繋げられる様になると HTTP 経由で画像の推論も出来る様になるかもしれませんね。

まぁシリアルポートに mime/multipart なボディを流し込んで JSON で応答してもらう様な物でも実現できなくないので、時間があったら試そうと思います。

Discussion