頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


機械学習で人体頭部の姿勢を得る(4)

機械学習で人体頭部の姿勢を得る(3)
↑の続き。全然あかん、こうなったらヤケクソや!何がなんでもデータセットに含まれる顔の種類を増やすんやあ!ってことでなんとか楽に増やす方法を検討した。

今まではMakeHumanで出力したdaeファイル及びテクスチャ画像をBlenderで再設定してdaeファイルを出力、それをXcodeに持ってきて使ってた。Blenderで設定するのが面倒だったので、以前はあきらめたBlenderを介さない方法を再検討。

1) MakeHumanでのdae出力のオプションでBone orientationをLocal=Globalってのに変更、OrientationはY up, face Z(デフォ)で出力。
2) SceneKitではScene assetsのSettingsでAlways use the Y-up axisのチェックを外す

この状態だとテクスチャが設定されていないのでそこはコードでやる。
髪形や眉毛の形もdaeファイル内の文字列を調べれば設定すべきpngファイルはわかる。

そんなわけでMHでランダムに顔を作成、できたデータから差し替えていった。最終的には140種類の顔でそれぞれ1,000枚で14万のデータセットとなった。
そしてぶん回した。175kあたりで跳ね上がってるあたりからできたデータから順に差し替えてる。

TensorBoardの結果

↑データ差し替えからでもざっくり700時間くらい動かしてる。
その結果がこちら。↓



微妙だ。汎用性を求めるならやはり相当工夫してデータセットを作成する必要があるのか、、、

さらに、iPhone 7 Plusのフロントカメラで自分の顔の姿勢を把握できるか試してみたのが下の動画。むしろこれだけでもできれば、と思ってたが、やっぱり微妙。普通の光源、背景だとグタグタでそれっぽく動く状態にして撮影してこれだからなあ、、、



こういうのができたら自分専用モーションキャプチャーとか作れんじゃね?と思っていたけど、、、

今後はNNの構成を変更するとかカラー化するとかそもそものデータセットに工夫するとか色々手はあるかもしれないけど、機械学習は時間がかかるなあ。さて、どうするかな。



なお、iOSでのMetal Performance Shaderで推論するのに1画像あたり13〜21msec程度なので60FPSは微妙かもしれないけど1秒に数コマなんてことでもない感じ。今は実装してないけどカメラからの画像をMetal(GPU)使って欲しいサイズのデータを得てそのままMPSへ渡せばもっと早くできるんだろうな。



memo
iOS 10.3.2
MakeHuman 1.1.0
Python 3.5.2 :: Anaconda 4.1.1 (x86_64)
TensorFlow 1.0 ← ええかげんアップデートせにゃ!


機械学習で人体頭部の姿勢を得る(3)

機械学習で人体頭部の姿勢を得る(2)
↑この続き。
もう一つうまくいかないのはもしかして教師データが甘かったんじゃなかろうか?と。
例えば正面をゼロとして-15°から+15°までの画像をランダムに作成してデータセットを作成した場合、+45°の画像を入力とした時に正解を推論できるのか?そりゃ無理なんじゃ、、、?

そんなわけで従来より大きく動くようにしてデータセットを作成してみた。
データ数で30,000。従来の100,000は”穏やかな”データに加えて合計130,000個。
これで最初からやった方がいいのかよくわからないので、従来の続きでぶん回してみた。

TensorFlowの途中経過

↑そりゃ、そうなるわなってくらい損失関数の値が跳ね上がった。ここから学習していくのか?って思ってたんだが、なんとか学習は進んでるみたい。

ところが、テキトウな画像に対して推論すると相変わらずよろしくない結果に。こりゃダメだ、、、


機械学習で人体頭部の姿勢を得る(2)

機械学習で人体頭部の姿勢を得る
↑の続き。頭髪なしの男性モデルだけではさすがにダメなのかということで、いろいろと追加してみた。

データセットの一部

↑左上の頭髪なし男性が元々のデータ(データ数40,000)。
下の6パターンが今回追加したもの。
男性に3パターンで髪の毛を付け、女性モデルも追加。各10,000ずつの60,000で合計100,000のデータ数になった。ちなみに女性モデルの右二つは髪のオブジェクトの左右をひっくり返しただけの違い。

データを作る所や使う所はデータが後から増えても簡単に対応できるようにしておかないとあかんね(実は最初の頃はそこまで頭が回ってなかったんだけど)。

15.5エポックぶん回して、、、前と同じ画像で評価してみたのがこちらの動画。



少し改善した気はする。前は岡崎体育さんが正反対向いてたし。
でもまだおかしいのもあるなあ。トレーニングをさらにすれば改善するのかデータの種類を増やせばいいのか、NNの構成を再考すべきか、、、


機械学習で人体頭部の姿勢を得る

3Dのボーン付き人体モデルをSceneKitで使う
↑iOS上でこんな感じでリアルな人体の頭部を動かしてその画像(白黒、64x64)と姿勢データ(neck boneの座標x,y,z、クォータニオンx,z,w、head boneのクォータニオンx,y,z,w)の10個の値(どれも-1から1)を持つデータセットを作成。データ数は40,000個。

頭部のbone構成

↑こんな感じで接続してる。neck boneは軸周りの回転はなしとしてたのでy成分はゼロで実質x,z,wの3個。

損失関数は単に正解との差の絶対値の総和からの平均、という誰でも最初に思い付きそうなモノ。


PythonでTensorFlow使って学習を進めた。
まだ試行錯誤の途中だけど、現時点でのNNの構成は
畳み込み→プーリング→lrn→畳み込み→畳み込み→lrn→プーリング→全結合→ドロップアウト→全結合
てな感じ。Cifar-10のサンプルコードをめっちゃ参考にしてる。

その結果がこんな感じ↓


画面下の小さい画像から白黒の画像データを得て、予測、その結果を人体モデルに反映(画面上部)。
最初の10枚は(訓練用ではなく)テスト用画像のもの。そこそこ姿勢は得られている感じ。
と言っても訓練用もテスト用もたった一人の人体モデルからデータセットを作ってるので、他の人の画像を入力したらどうよ?ってのが後半の10枚。

なんとなくいけてそうなのもあるし、南野陽子さんや岡崎体育さんみたいに反対向いてるのもある。
岡崎体育どっち向いてるねん?!とネタにしたいとこだけど元データがハゲのおじさんデータだけなので仕方ないんだろう。いや、実は頭髪や性別など関係なく目、鼻、口の位置から予測してたらいけるのかも?!なんて期待してたんだけどね。
そんなわけで今後は元データ人体の種類を増やしてみるかなあ。

とりあえずMNISTやCifar-10などのように分類するのと違って出力で複数の値を得る、ということができそうということがわかった、ってとこがここまでの成果か。


TensorFlowのlrn層ってMPSではどう記述するの?

TensorFlowの学習結果をiOSのMPSで使う
↑この続きで畳み込みのある場合のMNISTをやってみたら(珍しく)一撃でうまく行ったのはいいんだけど、その次に別なNNでやろうとしてはまったんよ。

TensorFlowで tf.nn.lrn (local response normalization)ってのがあるけど、これをiOS側のMetal Performance Shadersではどう表現するのかよくわからん。色々調べたり試してみたんだけど、MPSのMPSCNNCrossChannelNormalizationでいいのかなと。
ただ、双方の定義をよくみるとどこからどこの層を対象にするねんってところで双方のパラーメータをどうやっても完全に一致はしないよね?

norm1 = tf.nn.lrn(h_pool1, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm1')
↑こんなTensorFlowのlrn層(値はCifar-10であったやつかな)をMPSで使おうとした時、
kernelSizeは9(これはプロパティじゃなくイニシャライザで設定)
norm.alpha = 0.001;
norm.beta = 0.75;
norm.delta = 1.0;
でいいのかなという気がするんだが、、、?定義からするとalphaの/9は不要と思うんだが、実はこの/9の有無で出力の値に変化がなかったのでよくわからない。まあいい、俺はそうするよ、lrn層後の値は双方似たような値になるし。

ただ、完全に一致するというわけじゃないのよ(入力データは完全に一致するけど)。

そもそもこのlrn層の前の畳み込み層の出力からしてTensorFlowとMPSでは値が微妙に違う。

0.15247595 0.13704236 0.24492025
0.152466 0.136963 0.244873
上がTensorFlow、下がMPSでの畳み込み層後の値。

TensorFlowでは32ビット浮動小数点数を使うけど、MPSでは16ビットだからそのあたりで異なってくるのかなあと思ってる。


↓参考)双方のリファレンス
tf.nn.local_response_normalization  |  TensorFlow
MPSCNNCrossChannelNormalization - MetalPerformanceShaders | Apple Developer Documentation




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad