【行動認識 #6】tensorflowでCAE(Convolutional Auto-Encoder)を実装してみた
これの続き
【行動認識 #5】データ量別でCNNの性能差 - MotoJapan's Tech-Memo
今回はCAEの実装をしてみた。
CAEってなに?
CAEとは、Convolutional Auto-Encoderの略で、次元削減/圧縮テクニックの1つである。
AE(Auto-Encoder)のConvolutional版ということで、Convolution層を使い、情報量を少なくして特徴量を抽出する半教師学習。
特にCAEが画像などの多次元データを扱うにはそのままテンソル変換せずに使えるので筋が良い気がするのでこれで今回はやってみる。
構造はencoderとdecoderで構成され、
- encoderの入力は画像等のデータ、出力は圧縮特徴量
- decoderの入力は圧縮特徴量、出力は、画像等のデータ
- decoderの出力とencoderへの入力が一致するように学習していく
活用方法は、次などがある。
- 圧縮した特徴量を抽出できる
- データが少ない場合の事は前学習として用い、encoder部分を再利用する
- モデルの局所最適への落ち込みを回避できるという点。(最近だとデータが多いなら不要という話)
概要イメージは下記。
詳細はいろいろなとこで記事になっているので他に譲ります。
実践
今回は前回に引き続き6行動のCAEを行う。
入力は、6ODF(加速度3軸、角速度3軸)の復号化。
今回のモデルは、Convolution + maxpooling 1 layer (=encoder) + unpooling + Deconvolution (=decoder) 1 layerで実装。
tensorflowだと、decoderは、tf.nn.conv2d_transposeが使える。
注意としては、ピクセル毎に回帰するので最後はsigmoidで0~1に収める必要がある。
結果
結果は例えばWALKを学習してみると、次の正解信号に対して、
学習epochを回す毎にどんどん近づいていく。
(見てておもしろい)
100[epoch]目以降はかなりオーバフィットさせ過ぎている感じもあるのでちょうどよいところ、
(WALKで言えば周期性が見えてくるところで)で打ち切る必要がありそうだ。
他の行動についてもすべてが並べてみるとなかなかの光景。
左上から右下までの順は次の通り。(横方向)
WALKING, WALKING_UPSTAIRS, WALKING_DOWNSTAIRS, SITTING, STANDING, LAYING
学習曲線はこんな感じで学習できている。
今後やりたいこと
- 学習データが少ない状況で、CAEで事前学習
- これで精度が上がるのであればいいなと。
- 生成モデルとしてVAEの実装
以上。
【行動認識 #5】データ量別でCNNの性能差
これの続き
【行動認識 #4】Subjectを考慮してCNN層数別で性能差を確認 - MotoJapan's Tech-Memo
学習データ量別で確認してみる。
概要
もともとの総データ数は、7344件。
7344件 ⇒ ( 7344 x 128 [samples] / 50 [Hz] ) + 0.5 [overwrap rate] ⇒ 2.6 [hour]
これが100%⇒50%⇒25%と変化したときの精度差を確認。
結果
最終精度は下記
condition | accuracy | loss |
---|---|---|
full (100%) | 0.9276 | 0.9687 |
half (50%) | 0.9008 | 0.9108 |
quarter (25%) | 0.8597 | 1.2324 |
tensorboardで学習進捗を書き出すとこんな感じ
- 学習データ量が多いほど精度向上がわかる
- 大体80 [epoch]目でどれも精度的な収束は落ち着きがわかる
- 比較的データが多いほうが初期精度も高い
- データ量が少ないとOverfitによる乖離傾向が強くなる
confusion matrixはどうだろう。
testデータの左からfull/half/quarterの順
- 特に姿勢系のSITTING/LAYINGの精度劣化が著しい(これは結構面白い)
SITTING/LAYINGは、0.87->0.77に落ち込み、誤検出の漏れ先はほとんどが姿勢系
まとめ
- 学習データ量が多いほど、汎化性能は高くなっている
- いろいろな行動パターンが学習できている
- 学習データ量が多いほど、収束タイミングは早くなっている
- epochを回すのもいいがデータが多ければepochをそこまで回さなくてもよいかも
- 姿勢系は遷移系に比べてデータが必要
- 繰り返し動作と単発動作だと、繰り返しの方が特徴量抽出しやすいのかも
以上。
【行動認識 #4】Subjectを考慮してCNN層数別で性能差を確認
これの続き
【行動認識 #3】機械学習/深層学習で人間行動認識 ~CNNしてみる~ - MotoJapan's Tech-Memo
前回はtrainデータでSubject未考慮で精度を検証した。(trainデータ内)
その精度は、93.43%
今回はtrain/testのそれぞれを使って評価
加えて、Convolution+MaxPoolingのペア層の数を変えて評価
前回との差
学習データ | Subject | CNN層数 | |
---|---|---|---|
前回 | trainデータを7:3で分割して評価 (5136件:2194件) | 14名 分割時に未考慮 | (Conv + Pooling) x 2 |
今回 | trainデータ(7344件) / testデータ(2944件) | 20名 予めSubject単位で分割(14名/6名) | (Conv + Pooling) x 1~3 |
【行動認識 #3】機械学習/深層学習で人間行動認識 ~CNNしてみる~
これの続き
【行動認識 #2】機械学習/深層学習で人間行動認識 ~データ確認~ - MotoJapan's Tech-Memo
やりたいことの1つでもあるtensorflowを使った。
結果
1. 精度
下記条件で検証して、精度としてはCNN(Convolutional Neural Network)で93.43%程度でた。
testセットの結果(93.25%時点)
条件
- データは、trainデータをtrainセット/testセットに7:3で分割 (Subject未考慮)
- 精度は、testセットに対して分類した結果
2. tensorflowを使って良かった点
- 実行速度が速い(いちいちpython層まで帰ってこない)
- tensorboardがめちゃ使える
- tensorflow mobileにも使える(まだやってないけど)
- コミュニティが大きく、文献が多い
3. 逆に辛かった点
- chainer上がりなので計算グラフを先に作るという概念なくて最初辛かった(慣れればOK)
- 動的に計算グラフを更新できない(とりあえず簡単にはできなそう)
- 学習中のネットワークのデバックができない(やり方がわからない)
Data
入力データは、前回の通り、下記の計6軸。
# 重力未分離加速度情報
total_acc_x_train、total_acc_y_train、total_acc_z_train
# 角速度情報
body_gyro_x_train、body_gyro_y_train、body_gyro_z_train
ラベルデータは、次の6行動。
WALKING(0), WALKING_UPSTAIRS(1), WALKING_DOWNSTAIRS(2), SITTING(3), STANDING(4), LAYING(5)
1データは、特に前処理せずに1軸あたり128 [samples]ずつ突っ込む。
Network
まず下記の感じで、[Convolution層 + pooling層] x 2で作って回す。
tensorboardでvisualize!
忘れそうだらtensorboardの実行方法を記載。
>tensorboard --logdir=[target_logdir]
ちなみに精度やロスを出すときに、trainとtestのディレクトリを分けておくと、
tensorboardが色分けしてくれる。
Accuracy/loss
精度とロスはこんな感じになりました。
一応、学習はちゃんと進んでいる。
200 epoch 回したが、189 epoch目でtestがbestに。
epoch=189 | train | test |
accuracy | 0.9998 | 0.9343 |
loss | 0.0004 | 0.5572 |
学習曲線は以下。(ありがとうtensorboard)
(※ただ、結局細かいところは自分でダンプした方がいい。)
Accuracy graph
Loss graph
analysis
実行速度(throughput)
環境は、Ubuntu 16.04 LTS / RAM 4G / Core-i7 CPU
このnetworkで 314.039 frame/secでした。
混合行列 (confusion matrix)
200 epoch目の結果で考察
bestの189 epochと比較してもそこまで大きく違わないので。
trainから分かること
- ちゃんとOverfitするだけの表現力がある
testから分かること
- WALK系[WALKING(0), WALKING_UPSTAIRS(1), WALKING_DOWNSTAIRS(2)]と、WALK系以外[SITTING(3), STANDING(4), LAYING(5)]は分離できている。(予想通り)
- ちなみに、WALK系は遷移系統、SITTING/STANDING/LAYINGは姿勢系統の動き。
- WALKING_DOWNSTAIRSの推定はまず間違えない。
- WALKINGは、UPSTAIRS, DOWNSTAIRSの一部であるから、間違える可能性がある。
- 姿勢系統は、ぼちぼちお互いに勘違いするケースがあるが、0.87は精度が出せている。
- 姿勢は、動きが少なく、特徴的な変化が少ないかもしれない。
同一Subjectが含まれる学習でも上記のような結果。
他の考察もそのうち。
【行動認識 #2】機械学習/深層学習で人間行動認識 ~データ確認~
この続き
【行動認識 #1】機械学習/深層学習で人間行動認識 ~事始め~ - MotoJapan's Tech-Memo
データセットは下記
UCI Machine Learning Repository: Human Activity Recognition Using Smartphones Data Set
ライセンスは次の通り。
This dataset is distributed AS-IS and no responsibility implied or explicit can be addressed to the authors or their institutions for its use or misuse. Any commercial use is prohibited.
「Human Activity Recognition Using Smartphones Data Set」『UCI Machine Learning Repository』データセット内 README.txt より。
URL: https://archive.ics.uci.edu/ml/datasets/human+activity+recognition+using+smartphones
データセットについて構造確認
train側だけだとこんなイメージ(test側もあり)
- body_acc_x_train # 重力分離済み加速度情報 (★1)
- body_acc_y_train
- body_acc_z_train
- body_gyro_x_train # 角速度情報 (★1)
- body_gyro_y_train
- body_gyro_z_train
- total_acc_x_train # 重力未分離加速度情報 (★1)
- total_acc_y_train
- total_acc_z_train
- X_train # 特徴量 (★1)
- y_train # 行動ラベル (★2)
分類問題を解くのであれば、★2が正解ラベルであり、★1を駆使して分類する。
今回はより生に近い値でやりたいので、入力は重力未分離加速度情報(ax,ay,az)と角速度情報(gx, gy, gz)のみを利用。
ではデータの中身を眺める。
データセットの中身確認
trainデータだけでも、7352件/21名分あるのでまずこれを味見。
同一被験者/行動違いのデータを確認(時間領域)
被験者1(Subject1)内でのランダムに取り出した各Actionのノルム違い
total_norm_acc_train
body_norm_gyro_train
異なる被験者/同一行動のデータを確認
シンプルそうなSTANDINGで確認。
total_norm_acc_train
body_norm_gyro_train
- total_acc_trainは、Subject3,5はオフセットしているように見える
- これは最初から平均値等でキャンセルした方が良さそう。
- body_gyro_trainは、かなり小さい値なので、その辺りで安定している
- Subject11が持つ0.14[rad/s]付近のデータでも8.02[dps]と考えるとかなり小さい。
同一被験者/異なる動きのデータを確認(周波数領域)
周波数領域についても見たい。
・total_norm_acc_train
SITTING/STANDING/WALKING
[SITTING/STANDING] [WALKING]という分離ができそう
・body_norm_gyro_train
SITTING/STANDING/WALKING
[SITTING] [[STANDING] [WALKING]]という分離ができそう
・SITTINGはかなり限られた低周波が反応
・WALKが高周波の部分が良く反応している
他の分析
同一被験者/異なる試行のデータを確認
SITTING (周期性なし)
WALKING (周期性あり)
- 傾向が見えるものもあるが、たまに特異な動きをするものもある(個人内ばらつき)
- 目視だが、行動によって周期性の無い動き、周期性のある動き、その再現性が確認できる
以上。
簡単なデータ分析だが、組み合わせ次第で分離可能性は確認できる。
次回は学習。
【行動認識 #1】機械学習/深層学習で人間行動認識 ~事始め~
人間行動認識 ( Human Activity Recognition ) の領域の話。
去年の3月頃にやっていたが途中になっていたこともあったので、追試も兼ねて再開。
(tensorflowの勉強もしたいし)
人間行動認識 ( Human Activity Recognition ) とは
私の認識では、カメラやセンサ等、様々な機器から得られた情報を基に、人間の行動を学習/推定する認識技術テーマ。
既存で様々な研究が進んでいて、
データであれば、
- RGB画像、デプスなどの光学系
- 加速度、角速度、気圧などのセンサ系
などがある。
行動であれば、
- Standing, Sittingなどの姿勢系
- Walking, Runningなどの遷移系
- その他、より特徴的な動き
など多岐にわたる。
詳しくは後々まとめる。
データセット
個人的なモチベとしては、スマホでとれるセンサ系データを扱いたい(去年は扱っていた)
まず触ってみるのにいろいろ探したが、一番簡単に扱えそうなUCIから提供されるデータセットを利用。
UCI Machine Learning Repository: Human Activity Recognition Using Smartphones Data Set
一応、日本のデータセットも探した。
特に、大きいところだと、Human Activity Sensing Consortium(HASC)というコミュニティもあるが、簡単にアクセスできるデータが少なかったので今回は諦める。
ちなみに、UCIから提供される上記のデータセットは、2015年のUpdate版もある。
UCI Machine Learning Repository: Smartphone-Based Recognition of Human Activities and Postural Transitions Data Set
An updated version of this dataset can be found at [Web Link]. It includes labels of postural transitions between activities and also the full raw inertial signals instead of the ones pre-processed into windows.
「Human Activity Recognition Using Smartphones Data Set」『UCI Machine Learning Repository』より。
URL: https://archive.ics.uci.edu/ml/datasets/human+activity+recognition+using+smartphones
データについて
重要なことを書き残し
被験者 | ボランティア 30人 |
年齢 | 19-48歳 |
行動種類 | WALKING, WALKING_UPSTAIRS, WALKING_DOWNSTAIRS, SITTING, STANDING, LAYING |
データ収集デバイス | smartphone (Samsung Galaxy S II) |
デバイス上のセンサ | 3軸加速度、3軸角速度 |
サンプリングレート | 50 [Hz] |
ラベリング手法 | 同時に撮影した映像からラベルを手動生成 |
データセット | 学習データ:テストデータ=7:3 (被験者単位で分割) |
データセットについては次の記載がある。
The sensor signals (accelerometer and gyroscope) were pre-processed by applying noise filters and then sampled in fixed-width sliding windows of 2.56 sec and 50% overlap (128 readings/window). The sensor acceleration signal, which has gravitational and body motion components, was separated using a Butterworth low-pass filter into body acceleration and gravity. The gravitational force is assumed to have only low frequency components, therefore a filter with 0.3 Hz cutoff frequency was used. From each window, a vector of features was obtained by calculating variables from the time and frequency domain.
「Human Activity Recognition Using Smartphones Data Set」『UCI Machine Learning Repository』より。
URL: https://archive.ics.uci.edu/ml/datasets/human+activity+recognition+using+smartphones
つまりこういうこと(だよね?)
- 加速度/角速度には、ノイズフィルタを適用
- 各データ(各軸)は128samplesのウィンド、オーバーラップは50%
- 加速度には、バターワスフィルタで重力成分を分離
- 特徴量ベクトルを時間/周波数領域から取得
今日は以上、次回は実際にデータを眺めたりしたい。
【Linebot #3】家の温度をLineで通知するアプリ (BME280使用)
家の温度をサーバーに通知して、自分のスマホに通知したい。
でも開発は最小にしたいので、Linebotとして開発した。
サーバサイドのみの開発で済むしね。
忘れそうなことや注意点を書き残し。
主に、サーバーサイドとクライアントサイドのpython実装とかとか。
できたもの
自動通知された時
日中部屋は地獄のように熱い orz (外の方が涼しい)
温度取得に使ったもの
1. 温度センサ
使用した温度センサはBME280。
温度だけでなく、気圧、湿度も取得可能。
これ↓↓↓
BME280使用 温湿度・気圧センサモジュールキット: センサ一般 秋月電子通商 電子部品 ネット通販
2. Raspberry Pi 3 Model B
https://www.amazon.co.jp/Raspberry-Pi-TSI-PI018-Clear-Pi3-Model/dp/B01D1FR29M
やったこと(忘れやすいことのメモ)
1. raspberry piにraspbianをインストール(割愛)
4. 初期設定とか
$sudo apt-get update $sudo apt-get upgrade
5. I2Cを有効化、ツールインストール
$sudo raspi-config
“5 Interfacing Options” -> “P5 I2C”でEnableを選択
カーネルモジュールがロード確認 (無事、i2c_devがある)
$lsmod
I2C関連ツールをインストール
$sudo apt-get install i2c-tools $sudo apt-get install python-smbus
6. BME280を繋いでI2C接続確認
実際の配線とかは※1を参考にしているので割愛
こんな感じ
接続確認は以下
$ i2cdetect -y 1
7. raspberry piから温度取得(割愛)
※1がわかりやすいのでそちらを参照しました。
8. 温度情報をHerokuに送信する
raspbianはpython2.7系なので、次のコードでクライアントサイドを実装
urllibを使います。
今回はPOSTになります。
#the case of python 2.7 import urllib def post_message(t, p, h): print('post') data = {} data["temp"] = t data["pres"] = p data["hum"] = h server_addr = 'https://xxxxxxxxx.herokuapp.com/info' try: data = urllib.urlencode(data).encode("utf-8") res = urllib.urlopen(server_addr, data=data) res = res.read().decode("utf-8") print(res) except: print('error')
3系だったらこんな感じのはず
#the case of python 3.xx import urllib.request, urllib.parse def post_message(t, p, h): print('post') data = {} data["temp"] = t data["pres"] = p data["hum"] = h server_addr = 'https://xxxxxxxxx.herokuapp.com/info' try: data = urllib.parse.urlencode(data).encode("utf-8") with urllib.request.urlopen(server_addr, data=data) as res: res = res.read().decode("utf-8") print(res) except: print('error')
9. 温度情報をHeroku側で受信する
サーバーサイド。こっちはflaskです。
linebot側はこの辺の知識を活用です。
【Linebot #2】herokuでブックマークアプリを作ってみた - MotoJapan's Tech-Memo
今回はPOSTを受ける。
#the case of python 3.xx @app.route("/info", methods=['POST']) def info(): param_t = float(request.form['temp']) param_p = float(request.form['pres']) param_h = float(request.form['hum']) content = ' temp : {0:3.1f} deg \n hum : {1:2.1f} % \n pres : {2:4.1f} hPa '.format(param_t, param_h, param_p) user_id = 'yyyyyyyyyyyyy' line_bot_api.push_message(user_id, TextSendMessage(text=content)) return 'POST OK!'
注意
GETも同様に書けばよいですが、param_t, param_p, param_hをグローバル変数にいれておいて、GETするのは危険です。
Herokuは定期的に寝てしまうので、寝ると消えるようです。
ちゃんとDBに登録したものを返すようにしましょう。
HTMLを返すとブラウザからはこんな感じで見えます。
10. raspberry piのスクリプトを起動し続ける
普段はteratermから接続していますが、セッションを切るとプロセスもきれる。
なので、次の2つ方法で、永続化をします。
1. rc.localに書き込む
これは起動時に実行されるスクリプトを指定できます。
$sudo emacs /etc/rc.local
重要なのは、「exit 0」の前に書くこと。
sudo python [target].py & #<-ここを追記 exit 0
2. 実行時にnohupを使う
これはセッションを切ってもプロセスを残す方法です。
$nohup sudo python [target].py &
以上、のんびりやっても半日くらいもあればできました!
参考資料
※1: BME280をRaspberryPiから動かす話(すごくわかりやすい)
Raspberry Pi + BME280モジュールで自動で温度・湿度・気圧を測定してグラフ化する - karaage. [からあげ]