Matlab Mobile実用編-機械学習を添えて-

#概要
スマホでMatlabを使える、誰得アプリ[Matlab Mobile](https://play.google.com/store/apps/details?id=com.mathworks.matlabmobile&hl=ja)。

[前回の記事](https://qiita.com/drafts/87759ae27ef67e7d83e4/edit)でスマホデータの取得法を示したけれど、せっかく取ったデータを面白いことに使ってみたい。ということで、簡単なプログラムの開発フローについて紹介します。

機械学習の部分については Neural Network Toolboxを使っていますが、他の部分についてはMatlab単体で実施可能と思います。
(FFTを特徴量としているので、ゲイン最大値を判定基準にしたりすれば機械学習なしでも出来ると思います)

##１．開発するプログラム
File Exchangeのサンプルに、[人の活動状態識別](https://jp.mathworks.com/matlabcentral/fileexchange/64268-neural-network-for-sensor-data-analysis)というものがあります。
人が立っているのか、歩いているのか、階段昇降しているのか・・・を識別するもの。

<img src="https://qiita-image-store.s3.amazonaws.com/0/302506/9bc101c1-2738-0adf-320e-5ce3e586dd74.png" width="400" border="5">

これはこれで秀逸なサンプルなのですが、与えられたデータを使うのでは面白くない。
なので、<b>自分のスマホで教師データを取得、機械学習にかけてモデルを作成、そのモデルを使って活動状態識別</b>するプログラムを作ります。

##２．開発環境
Matlab Mobileのみだと作業効率が悪いので、開発はPCにインストールされたMatlabを使います。MobileとPCの連携には[Matlab Drive](https://jp.mathworks.com/products/matlab-drive.html)を使います。
<b>やってみて分かりましたが、これ超便利です。本ページで最も主張したいのはこの部分と思うぐらい。</b>PCで書いたコードが即反映されるので実機検証が非常に楽ちん。

役割分担を絵に書くと下記です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/302506/51749d3d-29af-2147-66c1-c411f1afe8b4.png)
Matlab Mobileのデータ保存場所はデフォルトでMatlab Driveなので特に設定不要です。PC側は<b>Matlab Driveをインストール</b>し、Matlabの作業フォルダをMatlab Driveに紐づけたフォルダに指定する必要があります。(デフォルトなら名前が MATLAB Drive のフォルダが新規作成され、そこに紐づけられる)

##３．開発
###3-1 スマホデータの取得
[前回の記事](https://qiita.com/drafts/87759ae27ef67e7d83e4/edit)では、データをスマホ上のワークスペースに保存しましたが、今回はMatlab Drive上に保存します。「センサー」画面にて「ログ」に設定することで可能です。
<img src="https://qiita-image-store.s3.amazonaws.com/0/302506/77381dd5-cb18-77de-14ac-43d46f53ca38.png" width="300">
加速度データ取得を有効にしてから「開始」をタップ、データ取得してから数秒後に「停止」をタップ。データのファイル名を指定して保存します。
活動状態識別をしたいので、歩きながらデータを取ったときは「walk.mat」に保存、停止時は「stand.mat」などにしておくと後処理が楽です。

著者は、停止・歩行の２種のデータを取得することにしました。サンプル周期は50Hzで、10秒ほど同じ動作を繰り返したデータを１つずつ保存しました。(10秒のデータをMatlab内で分割することでデータ数を水増ししている)

###3-2 スマホデータをPC側Matlabに読み込み
データはPCの　MATLAB Drive\MobileSensorData　に保存されています。今回はここを作業フォルダとします。
ファイルの読みこみは通常のMatlabコマンドでＯＫです。

```matlab
stand = load('stand.mat');
walk = load('walk.mat');
```

下記では、簡単さを重視してY軸の加速度データのみを使います。
また機械学習の入力データとしては加速度の生データではなく、FFT値を使います。
データの取りだし方は下記を参照下さい。

```matlab
%データをサンプリングする際の長さ
width = 50;
%シフト量 widthより小さい値に設定することで教師データ水増し
shift = 25;

%サンプリング
for j = 1:2
    switch j
        case 1
            data = stand;
        case 2
            data = walk;
    end
    point = 1;
    for i = 1:100 %100は適当な数字。whileループでももちろんＯＫ
        endpoint = point+width-1;
        if endpoint > length(data.Acceleration.Y)
            break;
        end

        %Y軸の加速度データを取りだし
        Y = data.Acceleration.Y(point:endpoint);

        %機械学習の入力としてFFT値を使用
        %Yから平均値を引いてからFFTを実施
        Yfft = abs(fft(Y-mean(Y))/length(Y));
        Yfft = Yfft(1:fix(length(Y)/2)+1);
        Yfft(2:end-1) = 2*Yfft(2:end-1);
        
        %活動状態 state とFFT結果 Yfft を配列に保存
        %ループの最初の１回だけ初期化処理が必要
        if i == 1 &&  j == 1
            state = j;%立っているなら1,歩いているなら2
            Yfftdata = Yfft;
        else
            state = [state  j];
            Yfftdata = [Yfftdata Yfft];
        end
        point = point + shift;
    end
end
```

###3-3　機械学習モデルの作成(PC作業)
[浅いニューラルネットワーク](https://qiita.com/masahiro_isono/items/ad5d36483f27ff4bcb95)を用いました。理由は単純に自分の勉強用です。

```matlab
statevec = full(ind2vec(state));%数値stateをベクトルに変換

%浅いニューラルネットワークを作成、学習実行
net = patternnet(20);
net = train(net, Yfftdata, statevec);

%教師データそのもので動作検証
statevec_es = net(Yfftdata);
plotconfusion(statevec, statevec_es);

%学習したネットワークに名前を付けて保存
StepNet = net;
clearvars -except StepNet;%これをやらないとネットワーク以外も保存される
save StepNet;
```

上記コマンドの結果、学習したネットワークが<b>StepNet.mat</b>に保存されます。このmatファイルはのちほどスマホ側でも使います。
参考までに、ネットワークの動作検証結果は下記です。教師データそのものを使うため、精度100%の結果となりました。
<img src="https://qiita-image-store.s3.amazonaws.com/0/302506/83915303-bc88-1ca4-9b67-df74c7969b22.png" width ="300">

###3-4　実行ファイルの作成(PC作業)
下記コマンドを<b>StateCheck.m</b>として保存します。名前はなんでもよいですが、後でスマホから呼ぶので分かりやすい名前がよいでしょう。

下記はあくまで最も簡単なコードなので、慣れてきたらclear allせず、loadやmobiledevはMatlab Mobile立ち上げ後しかやらないようコード変更するとよいでしょう。この場合、一番下の行のログデータ消去を行わないとデータが蓄積されてしまい、FFTの対象となる加速度データが最新のものにならない点に注意してください。

```matlab
%全データをいったんクリア
clear all;

%学習したネットワークを読み込み
load('StepNet.mat')

%スマホデータ取得用のオブジェクトを作成
m = mobiledev;

%活動状態判定結果を表示する用のラベル
Labels = {'stand','walk'};

%オブジェクトの設定を変更。加速度データ取得有効、サンプル周期50Hz
m.AccelerationSensorEnabled = 1;
m.SampleRate = 50;

%データ取得を実施(２秒間)
m.Logging = 1;
pause(2);
m.Logging = 0;

%Y軸加速度データを取りだし
[a, t] = accellog(m);
ay = a(:,2);

%学習時と同じサイズのデータを切り出してFFTを実施
point = 1;
width = 50;
endpoint = point+width-1;
Y = ay(point:endpoint);
Yfft = abs(fft(Y-mean(Y))/length(Y));
Yfft = Yfft(1:fix(length(Y)/2)+1);
Yfft(2:end-1) = 2*Yfft(2:end-1);

%学習済みネットワークに今取ったデータを入力
Result = StepNet(Yfft)

%結果を数値に変換、結果をディスプレイに表示
classes = vec2ind(Result);
Labels{classes}

%ログデータを消去
discardlogs(m);
```

###4　スマホにて開発プログラムを検証
再びMatlab Mobileを起動、作成したStateCheck.mを実行します。
準備として、左上「ファイル」から、StepNet.mat 及び　StateCheck.m を保存したフォルダに移動する必要があります。(本ページの場合は MATLAB Drive\MobileSensorData)
<img src="https://qiita-image-store.s3.amazonaws.com/0/302506/d599ed96-529a-5439-f2be-9b67a7db3d0c.png" width ="400">
該当フォルダに移動するとStepNet.mat、StateCheck.m の存在が確認できるはずです。
ここで StateCheck.m をタップして開いてもよいですが、<b>日本語が猛烈に文字化けする</b>ので開かないほうが吉です。

ファイルの実行は左上「コマンド」に戻り、StateCheck を入力して行います。SteteCあたりまで入力したらサジェトが出るのでタップしましょう。

実行するとMatlab Mobileに「実行中」の文字が現れ、終了まで出続けます。これはmファイルがmathworksのサーバ上で動いているためで、途中経過などを見ることは現状出来ません。

実行結果は下記です。
<img src="https://qiita-image-store.s3.amazonaws.com/0/302506/c50be8fc-ebfb-8874-6fb1-88ccec13354e.png" width="200">
教師データも特徴量の作りこみも甘いので、外れる場合もありますが<b>自分のスマホで教師データ取得、モデル作成、モデル実行まで自己完結</b>できた感動はひとしおです。


なおMatlab Mobileを使う上で最も大変と思われるのはデータ取得および検証です。
なぜなら、<b>本手法で正確なデータを取得するには歩きスマホを強いられるから</b>です。検証の様子を参考までに。
![Step.gif](https://qiita-image-store.s3.amazonaws.com/0/302506/69173150-a856-56e7-23ee-e6a5ebb31c99.gif)


活動状態識別の種類を増やそうと思うと、小幅歩きスマホや大幅歩きスマホ、階段昇降スマホをする必要も出てきます。これはプログラムの工夫で対策が可能ですが、前処理が増えるデメリットがあるので今回は紹介しません。

##５．まとめ
・Matlab Drive超便利。
・Matlab Mobileはデータ取得および検証用ツールとしては秀逸。
・コーディングはやはり本家Matlabでやるに限る。
・データ取得法は工夫の必要あり（ただし前処理が増える）
<b>・みんな、Matlab Mobileはいいぞ。
　本ページを参考に、とりあえず遊んでみて下さい。</b>
・[ThingSpeak](https://thingspeak.com/)と組み合わせることで、遊びの幅はさらに広がりそう。