QoreSDKを使って筋トレ推定アプリを作った

## tl;dr

- 筋トレ推定アプリを作った
- Qoreはリザーバコンピューティングというアルゴリズムを使っている
- スマホで取得できる加速度データから時系列データの分類タスクを行った
  - [コード](https://github.com/hnishi/muscle_QoreSDK_AdvCal2019/blob/master/muscle_QoreSDK.ipynb)
- 精度はかなりいい
  - テストデータで、精度 99.6%
- これで筋肉エンジニアになれる   っはず

## 戦略

- スマホ（iphone）で加速度センサーデータを収集
- x, y, z軸3つの成分をもつ時系列データが手に入る
- 腕立て、腹筋、スクワット、腹筋ローラーの４種目の筋トレで学習
- スマホだけで、どんな筋トレをしたかがわかる

## データの収集

- スマホを、ズボンのポケットに入れたまま筋トレする
  - 今回は、いずれの筋トレにおいても、同じ向きでスマホをポッケに入れる
  - 違う向きにしたりすると、より推定は難しくなると思われる
- 加速度測定には、以下のアプリを使わせて頂いた
  - [「加速度・ジャイロスコープ・磁力センサーロガー」](https://apps.apple.com/jp/app/%E5%8A%A0%E9%80%9F%E5%BA%A6-%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AD%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97-%E7%A3%81%E5%8A%9B%E3%82%BB%E3%83%B3%E3%82%B5%E3%83%BC%E3%83%AD%E3%82%AC%E3%83%BC/id448070865)
  - 測定間隔は 0.1 sec
- 行った筋トレ回数
  - 腕立て：２１回（~35 sec）
  - 腹筋：２０回 (~66 sec)
  - スクワット：２０回 (~51 sec)
  - 腹筋ローラ（座りコロ）：１２回 (~50 sec)
- データ量を増やすためには、もっと筋トレしなければならない
  - いずれマッチョになれるはず

- 以下が、実際に測定できた加速度の生データ
- 腕立て伏せ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99215/c79f9186-1783-dd99-ae45-2bafa42ecf82.png)

  - 腹筋

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99215/6601eb92-9a7e-0dd0-26a9-e6faa6331bfe.png)

- スクワット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99215/d6e4fe46-c2e8-2be3-aed4-a73d25b1a7bf.png)

- 腹筋ローラー（座りコロ）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99215/2aff66d9-f38b-1301-e14e-ef5492e453bb.png)

- 周期的になっていて、思ったよりキレイなデータが取れた

## データの前処理

- QoreSDKが提供する、[qore_sdk.utils](https://qcore-info.github.io/advent-calendar-2019/index.html#module-qore_sdk.utils) を使ってみた
  - [sliding_window](https://qcore-info.github.io/advent-calendar-2019/index.html#qore_sdk.utils.sliding_window)
    - 時系列を複数の小時系列に分割する
    - APIにデータを渡すために必要な前処理である（3次元にする）
  - [under_sample](https://qcore-info.github.io/advent-calendar-2019/index.html#qore_sdk.utils.under_sample)
    - クラス当たりのサンプル数を揃える
    - 実測したデータには、データ数の偏りがあった
    - 普通、機械学習では、データ数の大きいデータに精度が引っ張られてしまうので、一番数が少ないクラスのデータ数に合わせた
- なお学習の際には、入力データのサイズに制限がある
  - N\*T\*V < 150,000 && N*T < 10,000
  - 最初、各アルファベットが指す意味がわからなかったが（もと生物物理系なので、カノニカルアンサンブルか！？とも思ったが）、以下だと思われる
    - N: 小時系列データ数
    - T: 小時系列の長さ（time?）
    - V: 特徴量の数（今回の場合は、x, y, zの加速度3個）

## 学習と推論

- 学習と推論は、[サンプルコード](https://github.com/qcore-info/advent-calendar-2019/blob/master/Qore%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB1_with_UCI.ipynb)とまるっきり同じ
- 以下で、アカウント情報を設定

```python
client = WebQoreClient(username=username, 
                       password=password, 
                       endpoint=endpoint)   
```

- 以下で学習

```python
res = client.classifier_train(X=X_train, Y=y_train)
print(res)
# {'res': 'ok', 'train_time': 7.2200915813446045}
```

- 学習は、7.2秒ほどで終わりました
  - 結構早い
- テスト（推論）

```python
res = client.classifier_test(X=X_test, Y=y_test)
print(res)
{'accuracy': 0.9964285714285714, 'f1': 0.9964301018846474, 'res': 'ok'}
```

- 精度は、0.9964
  - 高い！

## 線形回帰、簡単な深層学習と比較

- これもサンプルコードのままです
- 線形回帰
  - 学習時間:0.28547000885009766\[sec\]
  - 精度: 0.9964285714285714
- MLP (Using Sklearn) 
  - 学習時間: 0.7626857757568359\[sec\]
  - 精度: 0.9928571428571429
- 両者とも、わずかにQoreSDKより低いが、依然精度高い
- 問題が簡単過ぎたか？

## 使ってみた感想

- SDKはシンプルで使いやすかった
- 精度は高かったが、線形回帰とMLPでも十分な精度が出てしまった
  - 問題が簡単過ぎた可能性がある
  - もっと難しい推定タスクを試してみたい
- 今回、試せなかった[qore_sdk.featurizer](https://qcore-info.github.io/advent-calendar-2019/index.html#module-qore_sdk.featurizer)を使うとどうなるか検証してみたい（時間があれば）

# 以下、調べたことや整理したこと

## Qoreのアルゴリズム

以下の記事（アドベントカレンダー１日目）に、簡単な解説が載っている。

[リザーバコンピューティングの世界 ~Qoreとともに~ - Qiita](https://qiita.com/ryoppippi/items/f607c8828238094eade0#qore%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)

> リザーバコンピューティングを応用し、いくつか手を加えたものとなっています。

> 独自に改良を重ね、リザーバ内部はもちろん、前処理と後処理にも独自の仕組みを開発することで、小さなリザーバサイズでも高精度なモデルを実現

とのことらしい。

下記論文がベースになってるっぽい？  
Van der Sande, Guy & Brunner, Daniel & Soriano, Miguel. (2017). Advances in photonic reservoir computing. Nanophotonics. 6. 561-576. 10.1515/nanoph-2016-0132.

時間があるときに読んでみたい。

## 具体的な手順のコード

以下のレポジトリに、jupyter notebookを公開しました。
手順に関しては、READMEとノートブックのスクリプトをご覧ください。

[GitHub - hnishi/muscle_QoreSDK_AdvCal2019](https://github.com/hnishi/muscle_QoreSDK_AdvCal2019)

## QoreSDKでできること

- classification 分類タスク 
  - [classifier_train](https://qcore-info.github.io/advent-calendar-2019/index.html#qore_sdk.client.WebQoreClient.classifier_train)
- regression 回帰タスク
  - [regression_train](https://qcore-info.github.io/advent-calendar-2019/index.html#qore_sdk.client.WebQoreClient.regression_train)
- 時系列の周波数分解による特徴抽出（使った場合と使わない場合で比較したい）
  - [Featurizer](https://qcore-info.github.io/advent-calendar-2019/index.html#qore_sdk.featurizer.Featurizer)
- 時系列を複数の小時系列に分割（使いやすかった）
  - [sliding_window](https://qcore-info.github.io/advent-calendar-2019/index.html#qore_sdk.utils.sliding_window)
- ラベルの数合わせをする関数（使いやすかった）
  - [under_sample](https://qcore-info.github.io/advent-calendar-2019/index.html#qore_sdk.utils.under_sample)

- せっかくなので、QureSDKの機能をフルに使いたいと思った
- 変化点検知や異常検知ができるようになってほしい

## 公式ドキュメントリンク

advent repo
[GitHub - qcore-info/advent-calendar-2019: 深層学習以外の機械学習と応用技術 by QuantumCore Advent Calendar 2019](https://github.com/qcore-info/advent-calendar-2019)

QoreSDK doc
[QoreSDK 0.1.0 documentation](https://qcore-info.github.io/advent-calendar-2019/index.html#document-index)

# 2019/12/22 追記

## Featurizer を使うと、精度がさらに上がった

class 数 40 になるように、周波数分解による特徴抽出を行う。

```python
n_filters = 40
featurizer = Featurizer(n_filters)
X = featurizer.featurize(X, axis=2)
```

テストデータに対する QoreSDK 精度が以下

acc= 1.0
f1= 1.0
elapsed_time:52.20956110954285[sec]

精度 １ という結果。

なお、逆に、ロジスティック回帰と MLP では、Featurizer を使う前より精度が下がった。

```
===LogisticRegression(Using Sklearn)===
elapsed_time:0.2480778694152832[sec]
acc= 0.6291666666666667
f1= 0.630372638509498
===MLP(Using Sklearn)===
elapsed_time:8.673331499099731[sec]
acc= 0.95
f1= 0.9502859082452324
```

## 筋トレをしていない状態を追加

筋トレをしていない状態を、分類タスクのクラスに追加した。
（昼食の準備をしているところを、コントロールとしてデータ収集を行った。）
この場合も、精度は 1 となった。

作業に使ったノートブックはこちら。
https://github.com/hnishi/muscle_QoreSDK_AdvCal2019/blob/master/muscle_QoreSDK_v2.ipynb

## 新規に取得したデータで検証

学習の時に使ったのとは別のデータセットを、腹筋ローラーで作成。
このデータを使って推論を行った。

作業に使ったノートブックはこちら。
https://github.com/hnishi/muscle_QoreSDK_AdvCal2019/blob/master/muscle_QoreSDK_v2.ipynb

結果、この検証データに対する精度は以下

- QoreSDK
    - acc= 0.6855791962174941
    - f1= 0.8134642356241235
- LogisticRegression(Using Sklearn)
    - acc= 0.20094562647754138
    - f1= 0.3346456692913386
- MLP(Using Sklearn)
    - acc= 0.27423167848699764
    - f1= 0.43042671614100186

QoreSDK で約 7 割の正解率となった。
もっと精度をあげるためには、筋トレのそれぞれの種目に対して、様々なパターンの学習データを拡充して学習させる必要がありそう。