【Python】IMU値を統計値にして機械学習させたら賢くなった<特徴量は分散が良い>

IMUを機械学習させる実験で、
現在の特徴量は、IMUのGravityAccx,y,zの3個だけで静止の場合は100%正答率がでます。
しかし、振ったりして動かすと、50%近くまで落ちてしまうので、賢くない機械学習になってしまいました。

静止状態の姿勢なら、正解率100%近くで判別できるのですが、動かすと、50-60%まで正解率が落ちるという結果です。
これでは、ちっとも賢くないので、feature(特徴量)をどうすべきか、IMUを使った事例を調べたら下記論文にあたりました。

●スマホIMUで人間の行動を識別する研究論文
Multi-stage activity intereface for locomotion and transportation analytics
of mobile users

2018年10月の奈良先端科学大学院大学の研究でした。
人の行動で、静止、歩行、ラン、自転車、自動車、バス、列車、地下鉄
を区別する機械学習のテーマです。センサは、9軸IMUの6種出力と気圧センサの7種類の生データを特徴量に処理して、機械学習アルゴリズムを3種類で評価した論文です。
ここで使っている特徴量を参考にさせていただきました。
時間軸系の統計値 Max, Min, Mean ,Standard deviation ,Interquartile range ,Kurtosis,Variance の7個です。

●やり方
1:トレーニング(機械学習モデルを作る)
    ①データ測定:IMUからLinearAccx,y,zを3クラス(3方向の往復動作)の動作をしてサンプリングして imu.csv ファイルに保存して次に渡す。
  ②特徴量作成:統計計算して7個のパラメータを特徴量として行列を作って、 stat_darrs.csv ファイルで保存して次に渡す。
     ③機械学習モデル作成:scikit-learnのSVCでfitさせて、機械学習データファイル model.savを保存

2:テスト(実際にIMUを振って機械学習させた結果と合っているかテスト)
  ①試行:MUを任意の方向へ振ってサンプリングしたデータを imu.csv ファイルに保存して次に渡す。
    ②特徴量作成:統計計算して7個のパラメータを特徴量として行列を作って、 stat_darrs.csv ファイルで保存して次に渡す。
③予測:predictへ特徴量を渡して、予測結果を得る。クラス番号がでるので、どの方向に振ったかあたっているかテストする

●統計量7個での結果
https://gist.github.com/dj1711572002/53d9e6105f29c2a6604cc49320a07daa
特徴量が21個もあるので、自動でグラフが書けないので、自分でExcelでとトレーニングデータのグラフを書いてみました。
3本のクラス(1がX軸方向振り、2がY軸方向振り、3がZ軸方向振り)で区別が一番つきやすいのは、分散のvar_x.var_y,var_zでした。標準偏差stdの2乗なので値が大きく差が見からです。
この21個の特徴量でのトレーニングデータを機械学習した結果は、正答率100%のテスト結果でOKでした。

 

●分散に絞ったプログラムにして、グラフをだした結果
https://gist.github.com/dj1711572002/3a254e362e5e589c1089a007a3bb565a

①トレーニング
分散1個のデータなので、点が真ん中にあるだけで、アルゴリズムが適当に境界線を引いてくれます。人力ではなかなかできないです。
この学習MODELでテストをすると上記21個特徴量と同様に正答率100%でしたので、分散が一番強い特徴量だとわかりました。

 

②テスト結果 1,2,3と振った方向で判別して正答を返してくれました。

———————-statics(gn,chn): END——————————
df= gnum var_X var_y var_z
0 1.0 92.639563 5.531745 8.346046
df1= var_X var_y var_z
0 92.639563 5.531745 8.346046
darr1=[[92.6395631 5.53174481 8.3460459 ]]
tdarrs=[0. 0. 0. 0.]
tdarrstr=[‘0.0’ ‘0.0’ ‘0.0’ ‘0.0’]
=================Test Input MODE================
********************This gesture is No. [‘1.0’]———————-statics(gn,chn): END——————————
df= gnum var_X var_y var_z
0 1.0 1.545021 68.447783 1.864353
df1= var_X var_y var_z
0 1.545021 68.447783 1.864353
darr1=[[ 1.54502054 68.44778285 1.86435261]]
tdarrs=[0. 0. 0. 0.]
tdarrstr=[‘0.0’ ‘0.0’ ‘0.0’ ‘0.0’]
=================Test Input MODE================
********************This gesture is No. [‘2.0’]———————-statics(gn,chn): END——————————
df= gnum var_X var_y var_z
0 1.0 5.167056 1.952147 132.17658
df1= var_X var_y var_z
0 5.167056 1.952147 132.17658
darr1=[[ 5.16705581 1.95214712 132.17658031]]
tdarrs=[0. 0. 0. 0.]
tdarrstr=[‘0.0’ ‘0.0’ ‘0.0’ ‘0.0’]
=================Test Input MODE================
********************This gesture is No. [‘3.0’]

 

●プログラムの備忘録
特徴量7個:https://gist.github.com/dj1711572002/53d9e6105f29c2a6604cc49320a07daa
分散のみ:https://gist.github.com/dj1711572002/3a254e362e5e589c1089a007a3bb565a
メモ1:scikit-leranに渡す行列のデータの型は、strでもfloatでもよいみたいでした。ただし、2次元の行列でないといけないので、1行のデータでも[[ 1,2,3]]と二重カッコに加工しないといけません。

df = pd.read_csv("stat_darrs.csv", sep=",", header=None,names=('gnum','var_X','var_y','var_z')) #pandas dataframeとしてcsvファイルを読み込んだ
#df=  gnum      var_X        var_y         var_z
#0    1.0     5.167056     1.952147        132.17658
df1=df.loc[:,'var_X':'var_z'] # クラス番号gnuはテスト入力では要らないのでdataframeから切り取ったdf1を作成
#df1=      var_X     var_y         var_z
#0         5.167056   1.952147    132.17658
darr1 = df1.values #scikit-learnに渡すためには、pandas dataframe ではダメなので、numyの行列データに変換するためにdf1.valuesとして行列に変換 二重カッコになっていることが重要

#darr1=[[ 5.16705581 1.95214712 132.17658031]]

統計処理したデータファイルstat_darrs.csvをpandas データフレームdf として読み込んでから、scikit-learnに渡すためには、numpyの行列に変換しないといけませんので、

 

●感想
IMUのパラメータを追加して統計処理して、EXCERLで特徴量を眺めながら、どの動作には、どの特徴量が良いか、確認してながら、特徴量エンジニアリングをすることが重要なことがわかりました。
特徴量エンジニアリング

 

●以後
自分の動作をサンプリングしながら、特徴量を調べて、どの動作にはどういう特徴量が良いのか、収集してみます。スキーでも歩行でもいろいろな動作を収集すると面白そうです。
IMU以外でもRTKにも使えるはずなので、スキーターンの種類を区別することはできるとおもいます。下手くそなパラレルとか区別はつけられるはずです。
BIGデータの世界にSTA24から踏みいれることになります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です