xiao-edgeimpulse-train について
xiao-edgeimpulse-trainは、XIAO ESP32S3向けのEdge Impulseモデル学習手順で、edge-impulse-cliではなくREST APIを使います。データセットのアップロードからインパルス作成、学習、Arduinoライブラリの取得、デバイスへの統合や問題対処までを案内します。
主な機能
- 01音声・画像データセットのアップロード
- 02音声またはビジョンのインパルス作成
- 03REST APIによる特徴生成とモデル学習
- 04Arduinoライブラリのビルドとダウンロード
- 05ESP32-S3のメモリと推論統合のガイド
活用シーン
- 01XIAO ESP32S3向けキーワード検出モデルの学習
- 02ボード向け画像分類モデルの学習
- 03Arduino推論ライブラリの取得とインストール
- 04ビジョン処理のメモリやカメラ統合の問題解決
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ shain1912/ esp32-skills --skill xiao-edgeimpulse-trainインストール後、Claude Code で/xiao-edgeimpulse-trainを入力して読み込まれたか確認します。
詳細
XIAO ESP32S3 向け Edge Impulse トレーニングパイプライン(REST API、検証済み)
以下はすべて、エンドツーエンドで実行し、検証済みです(2026-07)。
edge-impulse-cli は不要です。インストールしないでください(その
serialport@8 依存関係は Node 22 以降で VS C++ ビルドツールを必要とします)。
ステップ 0 — API キー(ユーザーに確認)
Edge Impulse の admin API キー(ei_...)をユーザーに確認するか、ユーザーから指定があれば
プロジェクトの .env(EI_API_KEY=...)から読み取ります。
- 自動作成されたプロジェクトキーのロールは「Ingestion & deployment」です。このキーでは
データをアップロードできますが、インパルスの作成やトレーニングの開始はできません(症状:
insufficient permissions (valid roles: [admin]))。 - 必要に応じて、ユーザーに次のように案内してください:Studio → Dashboard → Keys → Add new API key → Role Admin (full access) → キー全体をすぐにコピーします(その後、一覧では末尾が省略されます)。
- プロジェクト ID を取得します:ヘッダー
x-api-keyを指定してGET https://studio.edgeimpulse.com/v1/api/projects→projects[0].id。 - PowerShell の注意点:
$pidは読み取り専用の予約変数です。$projを使用してください。
ステップ 1 — データセットをアップロード(取り込み API)
ファイルごとに 1 回 POST します。ラベルは x-label ヘッダーから取得されます:
curl.exe -s -X POST -H "x-api-key: $key" -H "x-label: $cls" `
-F "data=@$($f.FullName)" https://ingestion.edgeimpulse.com/api/training/files
WAV:16 kHz、16 ビット、モノラル。画像:jpg/png をそのまま使用します。すべてをアップロードしたら、
自動でトレーニング/テストに分割します:POST /v1/api/$proj/rebalance。
1 つのプロジェクトにつきモデルは 1 つです。別のタスク向けに再トレーニングする場合は、まず次を実行して消去します:
POST /v1/api/$proj/raw-data/delete-all(デプロイ済みの lib zip があれば、先にアーカイブしてください)。
ステップ 2 — インパルスを作成
POST https://studio.edgeimpulse.com/v1/api/$proj/impulse(PUT ではなく POST)。
音声(キーワード検出)— MFCC ブロックで implementationVersion: 4 が
必須です。これを指定しないと v1 が使用され、特徴量の生成に失敗して
「mel filterbank contains all zeros」が表示されます:
{"inputBlocks":[{"id":1,"type":"time-series","name":"Time series data","title":"Time series data","windowSizeMs":1000,"windowIncreaseMs":500,"frequencyHz":16000,"padZeros":true}],
"dspBlocks":[{"id":2,"type":"mfcc","name":"MFCC","axes":["audio"],"title":"MFCC","implementationVersion":4}],
"learnBlocks":[{"id":3,"type":"keras","name":"Classifier","dsp":[2],"title":"Classification"}]}
ビジョン(画像分類、MobileNet 転移学習):
{"inputBlocks":[{"id":1,"type":"image","name":"Images","title":"Image data","imageWidth":96,"imageHeight":96,"resizeMode":"squash"}],
"dspBlocks":[{"id":2,"type":"image","name":"Image","axes":["image"],"title":"Image","implementationVersion":1}],
"learnBlocks":[{"id":3,"type":"keras-transfer-image","name":"Transfer learning","dsp":[2],"title":"Transfer learning (Images)"}]}
ステップ 3 — 特徴量を生成してからトレーニング
# start: returns a job id
POST /v1/api/$proj/jobs/generate-features body: {"dspId":2,"calculateFeatureImportance":false}
# poll until finished (10-15 s interval):
GET /v1/api/$proj/jobs/$jobId/status -> job.finished / job.finishedSuccessful
# on failure read newest-first logs:
GET /v1/api/$proj/jobs/$jobId/stdout -> stdout[0..] .data
# train (after features succeed):
POST /v1/api/$proj/jobs/train/keras/3
# audio body: {"trainingCycles":100,"learningRate":0.005}
# vision body: {"trainingCycles":20,"learningRate":0.0005}
精度はトレーニングジョブの標準出力にある val_accuracy の行で確認できます。各ポーリング
ループの合計待機時間は、ツールのタイムアウト時間未満にしてください。一度に長時間スリープするのではなく、
新しい呼び出しでポーリングを再開してください。
ステップ 4 — Arduino ライブラリをビルドしてダウンロード
POST /v1/api/$proj/jobs/build-ondevice-model?type=arduino body: {"engine":"tflite-eon"}
# poll job, then:
GET /v1/api/$proj/deployment/download?type=arduino -> save as <name>.zip
インストール:arduino-cli config get directories.user でスケッチブックの場所を確認し、
<sketchbook>\libraries\<project>_inferencing に展開します。zip には通常 1 つフォルダーが含まれるため、
src\<project>_inferencing.h が存在するように中身を移動します。
タスクごと(音声/ビジョン)に zip をアーカイブしてください。タスクを切り替えるとライブラリが上書きされます。
ステップ 5 — デバイス上での修正(ESP32-S3、ビジョンでは必須)
- ライブラリを入れ替えた後、最初のコンパイルで
--cleanを指定します。 arduino-cli のキャッシュには、同じライブラリ名/バージョンの古いオブジェクトが残ります。 症状:objs.a ... is not an objectというリンクエラー、または変更しても何も変わらないように見える(バイトサイズが同一)。 - テンソルアリーナのオーバーフローによるクラッシュ(
Failed to allocate persistent buffer ... EI_MAX_OVERFLOW_BUFFER_COUNT+起動時の Guru Meditation):src\edge-impulse-sdk\porting\ei_classifier_porting.hを編集します。 末尾近くの#if defined(CONFIG_IDF_TARGET_ESP32S3)では、#ifndef ガードなしでEI_MAX_OVERFLOW_BUFFER_COUNT 30が固定定義されているため、-D フラグと モデルファイルのデフォルト値はすべて無視されます。30を2048に変更してから、--cleanを実行してください。 - アリーナを PSRAM に配置します — スケッチに追加し(SDK のアロケーターは
weak シンボルです)、
--board-options PSRAM=opiを指定してビルドします:
#include "esp_heap_caps.h"
void *ei_malloc(size_t size) {
void *p = heap_caps_aligned_alloc(16, size, MALLOC_CAP_SPIRAM);
if (!p) p = heap_caps_aligned_alloc(16, size, MALLOC_CAP_DEFAULT);
return p;
}
void *ei_calloc(size_t n, size_t s) { void *p = ei_malloc(n*s); if (p) memset(p,0,n*s); return p; }
void ei_free(void *ptr) { heap_caps_free(ptr); }
ステップ 6 — 推論スケッチの統合
- 静的バッファーパターン(
signal.get_data)でデータを渡してください。EI の例の<I2S.h>コードは使用しないでください(esp32 core 3.x では動作しません。ESP_I2S.hを使用してください)。 - ビジョンの特徴量のパッキング:1 ピクセルにつき 1 つの浮動小数点数を使用し、
(r<<16)|(g<<8)|bとします。 - XIAO Sense のカメラ映像は 90°回転して表示されます。縮小しながら時計回りに回転してください(
sx = y*W/H; sy = H-1-(x*H/W))。そうしないと精度が大幅に低下します。向きを実際に検証するには、1 フレームを 3 通り(回転なし/時計回り/反時計回り)で分類して比較してください。 - 音声レベルの差:マイクの音声は、フルスケールのトレーニング用 WAV よりもはるかに小さいです。最適な対処法は、デバイスのマイク自体を通してトレーニングデータを収集することです。
- カメラの AWB にはウォームアップが必要です。本番の撮影前に約 8 フレームを取得して破棄してください。