前回の記事“小型IoT端末開発キット「SensorTile.box」 を使って機械学習を体験③”からの続きです。
今回は、ディシジョン・ツリーの評価テストを行います。前回作成した機械学習モデルをSensorTile.boxに設定して動作検証してみます。
1. ~ 4. (機械学習セットアップ)
→ 記事③を参照してください
データ収集およびUnico-GUIツールを使った機械学習作業を紹介しています。
5. 評価
今回の学習データはインターンシップ学生さんに協力してもらい収集しました。評価(Test)は別の人間(当記事執筆者)が行っているので、最低限の汎用度の確認はできると思います。
5-1. 準備
スマートフォンのセットアップ
スマートフォンをパソコンに接続し、前回作成したucfファイルをスマートフォン内の任意のフォルダにコピーします。
今回は、STMicroelectrnics\MLC以下に適当なフォルダ(“ucf_Test”)を作ってそこに置きました。
STBLESensorにて、MLCが使えるようにセットアップします。まずは以下の手順でExpert modeから新規アプリ作成へ進みます。
まず入力センサとしてMLC Virtual Sensorを選択します。その後セットした入力センサの編集ページに入り、“SELECT A UCF FILE”をクリックして先ほどスマートフォンにコピーしたucfファイルを指定します。
アプリを保存して完了です。
ここではアプリ名を“mlc stop&walk”としました。
スマートフォン側のセットアップはこれで完了です。
取り付け
データ収集時と同じように、左足首に取り付けます。軸の向きも同じ方向に合わせます。
5-2. 結果 & 検証
試験 1
実際に各動作を行ってみます。
歩行時はほぼ正しく判定されましたが、直立時や座っている時に誤判定される場合がありました。
ディシジョン・ツリー | 直立 | 座る&リラックス | 座る&貧乏ゆすり | 歩行 | ゆっくり歩行 |
---|---|---|---|---|---|
(1)Mean_ACC_X 判定 | △ | △ | △ | ○ | ○ |
△例: 直立静止状態でも、”walk”と表示される場合など。
検証 1
今一度ディシジョン・ツリーを見直してみます。
「ACC_X値のMeanが0.99gより大きい → 歩いている」
というディシジョン・ツリー内容ですが、SensorTile.boxのX軸が鉛直の場合ほぼ1gになるので、これでは足首が地面に対して垂直で静止している時でも「歩いている」と判断されてしまいます。
arffファイルには各Featureとして演算された結果が格納されているので、Meanデータについてグラフ化してみました。
見方としては、左半分が静止時(1~25 : stop1~5)で、右半分が歩行時(26~50 : walk1~5)です。
確かにwalk1~5についてはACC_Xの値が1を超えてるので判定ラインとして使えそうですが、stop1(直立)およびstop2(座って貧乏ゆすり)あたりの値もほぼ1に近いので、かなり微妙です。
(グラフ解説)
このグラフは、各モーションを全て横に繋げたようなイメージで、以降のグラフも同様です。横軸は時間と考えて問題ありません。“stop1”(直立)などの1モーション(1ファイル)は約10秒間分の記録です。センサODR = 26、Window Length = 52設定の場合、約2秒おきにFeatureが算出されるので(52/26)、1モーション区間に約5個のデータ・ポイントが存在します。
試験 2 Featuresを“Variance”に設定して評価
ディシジョン・ツリー作成時に選択したFeatureは、ACC_X軸のMean(平均値)でした。
別のFeatureも試したいので、個別に選択して再度作りなおします。Unico-GUIに戻り、Variance(分散)のみ選択して再度ucfファイルを作成します。
実行&結果2
5-1.準備にてSTBLESensorで作った“mlc stop&walk”アプリの編集ページを開き、ucfファイルを置き換えます。同じように試験すると、今度は正常に判定されました。
ディシジョン・ツリー | 直立 | 座る&リラックス | 座る&貧乏ゆすり | 歩行 | ゆっくり歩行 |
---|---|---|---|---|---|
(2)Variance_ACC_X 判定 | ○ (=stop) | ○ (=stop) | ○ (=stop) | ○ (=walk) | ○ (=walk) |
検証 2
ディシジョン・ツリーは以下のように生成されました。
「ACC_X値のVarianceが0.06836より大きい → 歩いている」
試験1同様、arffファイルでグラフ化してみましょう。
貧乏ゆすり時のデータ(Stop2あたり)が少しふくらんでいますが、その他の静止時期間についてはほぼゼロに近く、おおむね区別できそうです。
試験3 その他のFeatures
その他3つのFeaturesも試してみます。同じように1つずつFeatureを選択してucfファイルを作成後、各動作を試験しました。
- Energy
- Peak-to-Peak
- Zero-Crossing
実行&結果3
EnergyとPeak to Peakについては少し誤判定がありましたが、おおむね問題ないようです。
ディシジョン・ツリー | 直立 | 座る&リラックス | 座る&貧乏ゆすり | 歩行 | ゆっくり歩行 |
---|---|---|---|---|---|
(3)Energy_ACC_X 判定 | ○ (=stop) | ○ (=stop) | ○ (=stop) | ○ (=walk) | △*1 |
(4)PtoP_ACC_X 判定 | ○ (=stop) | ○ (=stop) | ○ (=stop) | ○ (=walk) | △*1 |
(5)Zero-cross_ACC_Y 判定 | ○ (=stop) | ○ (=stop) | ○ (=stop) | ○ (=walk) | ○ (=walk) |
*1 ゆっくり歩く程度によってはstop判定になる場合あり
Energy 検証
“Energy”は、最初に作成されたディシジョン・ツリーにおけるMean(平均値)とグラフ的には似ています。
こちらもACC_Xが判定値として採用されてますが、Meanの時と同様に判定ラインとしてはきわどい感じがします。取り付け方向がズレた場合、判定エラーになりそうなので、方向に依存しない ACC_V を使った方がベターです。
Peak-to-Peak 検証
“Peak-to-Peak”はVarianceのグラフと似てます。
ここでもACC_Xが採用されていますが、貧乏ゆすり時(Stop2)の値が判定ラインと近いです。より激しい貧乏ゆすりの場合オーバーしてしまう可能性があります。今回の設置方向条件では、(貧乏ゆすり時の振動方向と関係なさそうな)ACC_Yを使った方がより安全な判定ができるでしょう。
Zero-Crossing 検証
“Zero-Crossing”は、設定された振れ幅値(ヒステリシス→Threshold: gで設定)を超えた回数 をカウントします。今回、ディシジョン・ツリー作成時にThreshold = 0.3gに設定したので、± 0.3gを超える振れ幅がカウント対象です。これまではACC_Xばかり判定値として採用されていましたが、今回はさすがに使えなかったようで、ACC_Y が選択されていました。ACC_Xを選択した場合、貧乏ゆすり時(Stop2)の値が大きいので、Walk時との判別ができないのは明らかです。
ちなみに、Zero-CrossingのThreshold値を変えてみると様子が変わりました。
Thresholdを2倍(0.6g)にすると、貧乏ゆすり時のカウントがほぼ消えています。振動の振れ幅が把握できるのであれば、最適なThreshold値を設定するのもひとつの手です。
5-3. 全体感想
今回の動作モデルでは、arffデータグラフの様子から、 Variance(分散) や Peak-to-Peak、Zero-CrossingなどのFeatureが適していると予想できます。なお、Mean(平均値)では、静止状態と歩行状態の区別が難しいということもわかりました。
判定自体が2択とシンプルだったので、グラフ観察によりマニュアル的に適切な判定Featureを予想できましたが、実際にはデータがもっと複雑・大量で、判定クラスも多種になるケースもあるはずです。その場合、人間の観察眼だけで行うと手間がかかる上に面倒なので、機械学習ツールの活用が有効です。
Unico-GUIツールFeature設定についての注記
データ内容やConfiguration設定、クラス分け条件に依るのかもしれませんが、複数のFeaturesをセットしても上の方にあるFeatureばかりが条件式として採用される傾向にあります。Features設定項目は上から順にMean→Variance→Energy→・・・と並んでいるので、Meanばかりが採用されるケースが多いようです。
最適なFeatruesを選んでいるというより、“上から順にFeaturesを試していって、それで判定できればOK”といった印象です。また、今回5つのFeaturesを試しましたが、最後のZero-Crossを除き全てX値での判定でした。各軸についてもX→Y→Zという順番で評価されているようで、明らかにXよりYの方が判定値として適切では?と思われるケースでも、Xが選択されていました。そのため、ディシジョン・ツリー作成作業におけるFeatures設定時に、最適な軸を自分で選ぶことを推奨します。
応答時間と安定度の関係
この記事では省略しましたが、WL(Window Length)値設定条件によっても判定の安定度・応答時間(例:座った状態から歩き始めて、判定結果が“stop”→“walk”に変化するまでの時間)が変わる様子が観察されました。ここまでの記事内では、すべてWL = 52と設定していたので、判定確定には約2秒(52/26)かかる仕様になっています。応答時間をもう少し早めたいという場合、単純にWLを小さくすると判定間隔は短くなります。例えばWL = 26とすると1秒ごとの判定になりますが、各Featuresのarffグラフで見たところ、下図のようにデータが暴れるため注意が必要です(→Features演算前のフィルタ設定により改善できる可能性はあります)。そこで、Meta-Classifierを使って判定結果の安定度を高める方法もあります。しかし、Meta-Classifierは遅延的な要素を含んでいるので、せっかくWLを小さくして応答を早めようとしても、Meta-Classifierを追加したことで鈍い反応になってしまう可能性もあります。
今回のようなアクティビティ検出動作モデルの場合、最初の試行としては、WLについて26~52の間で最適な値を選ぶことを推奨します。
6. 最後に(次回予定)
今回の記事では、当初の予定どおり静止/歩行の2判定のみとしましたが、次回はもう少し判定種類(クラス数)を増やした場合の学習を試してみたいと思います。
補足
記事③内で少しコメントしましたが、SensorTile.boxとData recorderアプリを使ってデータ収集を行う場合に知っておくべき補足情報です。
補足A.
SensorTile.boxの向きと各内蔵センサの向きの関係
SensorTile.boxのData recorderアプリで加速度センサ・データをログすると、実際のセンサ側(センサ個体)のオリエンテーションとは異なる向きに変換後、記録されます。
ログ記録例(SDカード):3つの加速度センサをオン
(アプリ作成時、センサ選択画面でチェックを入れた順番にログのカラム(列)が左から並ぶので、メモしておく必要がああります。下表の順番とは限らないので要注意)
SensorTile.boxは縦置き(USBコネクタ部上向き): Y値 = +1g
各センサ個別の軸向きは違うはずだが、全て“SensorTile.box”本体としての向きに統一 されている。
センサに設定するucfファイルの内容はあくまでセンサ側から見た軸(に基づくデータ)に合わせる必要があります。Unico-GUI→MLC作業開始時のデータ入力の前段階で、csvファイルの列を操作するなどの変換処理を行っておいてください。例えば、LSM6DSOXの加速度センサ・データを入力する際、以下のような変換が必要です。
補足B.
Unico-GUIへの入力データ・フォーマット
Unico-GUIの仕様として、csvファイル入力時の各カラムは 加速度X-Y-Z、ジャイロX-Y-Zの順番 にデータ列が並んでいる必要があります(仮にcsvファイルの先頭カラム名が“accX[mg]”などとあったとしても、そのカラム名を認識してUnico-GUIの“Acc X”列に取り込まれるわけではない = 取り込み時、csvファイルにある先頭行のカラム名は無視され、単に左列から“加速度X”、“加速度Y”、・・・の順番で取り込まれる)
今回ジャイロ・データは使用しませんでしたが、STBLESensorでのData Recorderアプリ作成時にジャイロセンサを先に選んでしまうと、ジャイロ・データ列が一番左にくるのでUnico-GUIへ正常に入力されません。なお、タイムテーブル列に関しては自動で無視されるので、RTC(Time)やRTC(Date)を先に選択しても問題ありません。
~ 補足終わり