前回は学習済モデルを使用したため、あまりAIやってる感がありませんでしたが、今回は実際の開発フローと同じように学習から推論まで行ってみました。
TensorflowとKeras、STM32Cube.AIを使って、XORの論理演算を学習させ、STM32マイコンで推論させてみました。
ターゲットマイコンとしてSTM32F747G-Discoveryを使用しました。
【準備物】
・STM32F747G-Discovery
・KerasとTensorflowインストール済みのPython3環境
・STMCubeMX5.1& Cube.AIパッケージv3.4
・SW4STM32やTrue Studioなどの開発環境
■PCでXOR論理演算学習
@XOR論理演算を学習させます。
KerasとTensorflowインストール済みの環境でXOR.pyコードを実行します。
「python XOR.py」
学習させた結果、accが最終的に1になっていることを確認してください。
0.75といったように1になっていない場合は何度か実行し直してください。
また、最後に学習モデルを使って推論を実行しています。
[0,0]、[0,1]、[1,0]、[1,1]をテストデータとしてそれぞれ与えており、
0,1,1,0と表示されれば、XORの推論ができていることが分かります。
A学習モデルの保存
コード実行後はコードと同じディレクトリにモデルがXOR.h5として保存されます。後でCubeMXで取り込んで使用します。
■CubeMXを使ったCube.AIプロジェクト作成
CubeMXにCube.AIのパッケージを追加する方法は前回の記事を参考にしてください。
@ターゲットボードの選択
「Access to Board Selector」からSTM32F746G-Discoveryを選択します。
Aペリフェラル設定
ボード選択後のペリフェラル設定はデフォルトモードyesを選択します。
「Computing」項目の「CRC」を有効化します。
STM32F746DiscoはUSART1でPA9、PB7でSTLinkで接続されています。
推論結果等をシリアルコンソールで表示するため、
Connectivity→Usart1を有効化し、ボーレートを設定します。
また、必要に応じてデバッグ用のSTLinkを有効化します。
CORTEX_M7をクリックし、IとDのCacheを有効化します。
Bクロック設定
デフォルトは16MHzのため、最大の216MHzを入力します。
他の欄をクリックするとクロックウィザード確認がでるため、
OKボタンを押して他のクロックも合わせて自動設定します。
CCube.AIパッケージ追加
「Additional Softwares」をクリックして、X-Cube-AI/Application内の設定を有効化します。
Coreライブラリにチェックを入れ有効化し、Applicationは「Application template」を選択して「OK」ボタンで画面を閉じます。
Dライブラリ設定
「Additional Software」に「X-CUBE.AI」が追加されます。
「X-CUBE.AI」をクリックして、「Artificial Intelligence Core」、「Artificial Intelligence Application」にチェックを入れて有効化します。
ECube.AI設定
「Additional Software」の「X-CUBE.AI」をクリックします。
「Add network」をクリックし、「XOR」モデルを追加します。
ライブラリに「Keras」、「Saved model」を選択し、先ほど学習させたModel「XOR.h5」を選択します。「Analyze」ボタンをクリックします。
今回はXOR論理演算で簡単な処理のため、RAM40Byte、Flash:132Byteと圧縮なしでも非常に小さく実装できることが分かります。選択した学習済モデルで正常に推論できるか確認します。
今回はXOR論理演算のため、ランダムを入力するよりも論理演算として想定されるデータを入れて確かめた方がよいため、「Validation from」からカスタムデータai_inputs.csv を選択します。
「Validation on desktop」をクリックし、「Validation status」がSuccessとなれば正常に処理が終了したことを示します。
下記のフォルダにアクセスして、ai_valid_outputs_model.csv、ai_valid_outputs_c_model.csvを確認してください。正常に処理が終了すると処理結果がcsvファイルとして出力されているはずです。
C:\Users\(ユーザー名)\STM32Cube\Repository\Packs\STMicroelectronics\X-CUBE-AI\(バージョン)\Utilities\windows
[1,1]の入力に対して約0.06
[1,0]の入力に対して約0.94
[0,1]の入力に対して約0.95
[1,0]の入力に対して約0.04
値を丸めると
[1,1]の入力に対して0
[1,0]の入力に対して1
[0,1]の入力に対して1
[1,0]の入力に対して0
ということでXOR論理演算の推論ができていることが分かります。
Fプロジェクト設定とコード生成
HEAPサイズを0x200から0x2000に設定して、
他の設定は使用する開発環境等に合わせて設定し、
「Generate Code」をクリックします。
なお、学習済データ等はMiddlewares\ST\AI\AI\data、Middlewares\ST\AI\AI\src
Cube.AIライブラリ等はMiddlewares\ST\AI\AI\include、Middlewares\ST\AI\AI\lib
ユーザーが呼び出す関数群はsrc\app_x-cube-ai.cに入っています。
また、学習済モデルXOR.h5から推論の入力数、出力数は自動で設定されます。
Gprintf設定
CubeMXで生成したプロジェクトを開発環境にプロジェクトを追加します。
floatの結果を出力するため、プロジェクトのプロパティからいつも通り下記を追加して設定します。
-u_printf_float
ビルドします。
Hコード追記
main.c内に推論を行うための関数、コードを記述します。
今回はmain.cのみ手を加えました。
他のコードは自動生成されたコードです。
コードはこちらを参照してください。
aiTest()を呼び出して推論機能の初期化と実行をしています。
XORの学習モデルに合わせて入力に2次元の配列、出力に1次元の配列を与えています。
なお、自動で生成されるMX_X_CUBE_AI_Process()は空です。
Iマイコンへ書き込みと推論実行
シリアルUartで出力させ、teratermでデバッグ表示させてみました。
学習させたXOR.h5モデルを使用してSTM32マイコン上で入力に対してXORの推論ができていることが分かります。
XOR論理演算を学習させてSTM32マイコンで推論させてみました。
XORモデルは非常に小さいため、ターゲットマイコンがSTM32F3シリーズでも実現できそうです。
今回はマイコン側のXORの入力は固定値ですが、スイッチ入力やセンサ、ADCなど変化する値にするとAIがより機能的だと実感できると思います。
例えば、入力を1x2でなく、もう少し大きな配列にしてアナログ値やセンサ入力等を学習させて、それに応じて音や光といった結果を返すことも実現可能です。
今回作成したコードとプロジェクトはこちらにアップしてあります。
今回はSTM32F7-Discoveryのディスプレイを全く使用していないため、今後はタッチパネルを活用して推論させたりしてみたいと思いました。