simplestarの技術ブログ

目的を書いて、思想と試行、結果と考察、そして具体的な手段を記録します。

強化学習の Value Iteration と Q-Learning の違い

強化学習には Value Iteration と Q-Learning の2通りの学習方法が存在します。

Value Iteration で登場する Model が既知か、未知かを見て
未知の場合は、試行錯誤を繰り返す Q-Learning しか選べません。

Value Iteration にて登場する報酬は人間のさじ加減で決めます。
行動と結果の組み合わせを示す Model もまた、人間のさじ加減で決めます。
Model の見当がつかない場合は Q-Learning に逃げます。
Q-Learning とは試行錯誤を続けて、ずっとずっと試行錯誤を続けて、いつの日か人間のさじ加減で決めた報酬が得られたなら、それまでの行動経路の評価値をちょっとだけ上げるという学習方法です。
このときの評価値のちょっとした上げ方も人間のさじ加減で決めます。

いくつか解説を見てきましたが、ハンザツなままとらえている人が多いですね。
私はこんな風に、すっきりととらえてみました。

間違えたら、その行動を避けるようになり
当たったら、それまでの行動を取りやすくなる
これなら確かに、経験から学ぶ人にそっくりな行動を取るのかもしれませんね。

エピソード(思い出)を記録し、呼び起こす強化学習

強化学習について(私が知識を増やすために)学んでいますが、Value Iteration と Q-Learning の違いを書く前に(この後書こうと思っています。)
一つ昔に高校時代の友人から教えてもらった、エピソードに紐づく知識というものとの組み合わせを思いつきました。
simplestar-tech.hatenablog.com

↑この時に友人に教わった。

強化学習は状態とその時選択できる行動に評価値が与えられるというだけで、エピソードまでは思い起こせません。
これから行われるだろう未来は、強化学習時に無数に調べてきたわけですが、実行時は結果的に評価値という数字しか知識に残っていません。

行動選択はできるようになりますが、どうして?と尋ねられても、評価値が高いからという答えしか返せないのです。
そこで、その行動の評価値を大きく変動させた強烈なエピソードを思い出として記録し、未来予測として、どうして?と尋ねられた時に答える。
という、人工知能を作ってみたら、AIからその時の気持ちのようなものを教えてもらえるような気がしてきました。

という、アイディアを忘れないように書き留めておくという記事でした。

AI的な調べもの

最近、社内の勉強会でその存在を再確認したのですが、みなさんは OpenAI をご存知ですか?

OpenAI は組織名のようです。
コンテンツは Gym にあるとのことです。

OpenAI Gymは、強化学習を開発、評価するための プラットフォームです。
色々な環境が用意されているようで、次のリンクで一覧できました。
OpenAI Gym

ところで強化学習というのは、環境に対して行動の選択肢から行動を選択して行動し、その報酬(Reward)を最終的な結果から推定して、何度もこれを繰り返すことにより経験的にその推定Rewardが最大になる行動を選べるようにする手法です。

重要なので「経験的にその推定Rewardが最大」というところを強調しますが、つまりはローカルミニマムでさえなく、今までで一番良かった(かもしれない)試行結果に落ち着くということです。

強化学習について調べていたところ、次のQiitaの記事が、知りたいことをたくさん書いてくれていました。
qiita.com

まぁ、人間もRewardの推定を間違えている人がいますし
頭が良くても、学習データが間違っていると、これもまた誤ったローカルミニマムに陥りますので
「強化学習」=「間違える機械学習」というイメージを持っています。

追記:
時間をおいて深く読んでみたところ、疑問に思うところがあるので別の資料を当たりながら、自分なりの理解メモを追記しておきます。
まず、この等式をBellman equationと言います。と示されている式
選択肢aが複数あり、その中からひとつa選択したときにs'が無数に存在するため、∑計算ができるという式です。
無数にs'が存在することを言及していなかったので、ちょっと悩みました。
次に、value iteration の変数決定について疑問に思いました。
報酬を設定するという操作が、どういう操作なのか、例えば、人が考えるおよその値を設定し、その値をすこしずつ変化させるのか?
それよりも、一体何が収束するのか?書かれていないので調べることになりました。
調べた結果、現在わかっている範囲では初期値にすべての報酬を0とするという手法。
しかし、びっくりしたことに、そうすると計算を繰り返しても0しか返ってきませんので、何も変化が生まれません。
なるほど自分が疑問に思っていることは正しいようだが、利用したい側の立場としてはうれしくないですね。
は!書いていて気づいたことに、0以外になる瞬間が存在していました。
それは、正解が確定した瞬間と失敗が確定した瞬間です。
そのときに報酬が+1,-1になるようにしておけば、その一手前にて報酬が更新されます。
そこから波紋が広がるように、報酬の更新が走るんですね。
その報酬更新がいつか収束することが期待できるようで、このようにして報酬を決める手法がValue Iterationです。
どうやら私はそのValue Iterationの問題点をずっと指摘していたようです。
正解するまで計算を繰り返さないかぎり、値の更新が行われないということは、大量の計算が必要ということを示しており、一般的にValue Iterationでは、解を求めることは難しいケースが多いとのことです。
もう一つ、Q-Learningというものがあるそうで、次はそちらを理解してみたいと思います。

プラス、人間の行動の動機としての、欲求について知りたかったので、心理学の方を調べてみました。

その点について良さそうな記事を見つけました。
人生の学習 - マズローの心理学

なんとも、人生における幸せな生活とは何かについて考えさせられる記事でしたが
同じような欲求をデジタルなAIにも持たせてみようと考えてみました。

マズローの心理学の話で参考になった部分は次の二つ

「ヨナ・コンプレックス」と呼ばれる、欲求に気付くまいと潜在意識に押し込める臆病な行動
「欲求の段階説」という考え方
人の欲求は6つの段階
1.「生理的欲求」食事とか睡眠とかの欲求
2.「安全の欲求」1.が安定すること
3.「社会的欲求と愛・所属の欲求」人間社会で生きる者としては2.と同じかな?と私は思っている
4.「評価欲求」(他の人から価値ある人だと見なされること、他の人の中で価値ある人であること)
5.「自己実現の欲求」(道徳的であること、問題解決、先入観を持たないこと、事実を受け入れること)
6.「自己超越の欲求」(創造性、自発性、子供のような素朴さ、文化の超越、至高体験

なるほど、これらについて強化学習のRewardを設計してみようかと思います。

調べることから始めていたのですが、ここで目的がだんだん形になってきました。
頑張って言葉にすると、AIが行動するマイクロワールドを作り、それを観察できるオンラインゲームを作ってみたいと考えています。

いつかの AI の記事を書いているときに、AI に身体性を持たせる必要があると結論づけて終わっていたと思います。(終わっていなかったらごめん、あとで確認する)
その身体性をマイクロワールドの中で与えてあげようという試みです。

次回は、本当に簡単なものを作ってみようと思います。

UnityでMMDのPMXを表情モーフ付きでダンスするFBXとしてアセット利用する話

今回のトピックは Unity で MMD モデルにモーション付けて再生するというものです。

みなさんご存じ(?)のMikuMikuDance(MMD)と呼ばれるソフトウェアは、VPVPにて公開されているの3DCG動画作成ツールです。

表情豊かに歌って踊る3DCGコンテンツを探すと、ほとんどMMDに関わるものであり、データの形式はPMX, VMDです。
これらを Unity で扱う FBX 形式のデータに変換して再生する方法を紹介します。

まずは Unity 5.5.0f2 (64-bit) リリース: November 25, 2016 を起動します。
何もアセットが無い状態で、そのままだと空のシーンとなっています。

まず初めに行うのが Stereoarts Homepage さんのページに行き、MMD4Mecanim (Beta) の最新版を入手し
解説にあるチュートリアル(基本編)に従って操作し、任意の PMX ファイルを FBX に変換してシーンに配置します。

今回は任意の PMX に
3d.nicovideo.jp
からダウンロードしてきた、ぽんぷ長式の「村雨」を使うことにします。

チュートリアルを間違えなければ、このようにモデルを配置できると思います。

f:id:simplestar_tech:20161127160653j:plain

次に、踊ってもらいたい楽曲と楽曲用のモーションを選びます。

今回は Girls(EasyPop) にしようと思います。
楽曲を購入し(iTunesだと200円でした、やしぃー!)
iTunesの編集→設定メニューからインポート設定をいじってmp3に変換できるようにし、mp3ファイルを用意します。
これを Unity の Audio Source に設定すれば Audio Clip の完成です。

再生すると、ゲーム内で楽曲が響き渡ります。

次はモーションの VMD ファイルです。
bowlroll.net
こちらからダウンロードしてきました。

MMD4Mecanimのチュートリアルに従い、VMDを読み込ませてFBXのアニメーションとします。
変換にけっこう時間かかります。
出来上がったFBXにはアニメーションが含まれるようになっていて、これを Unity の Animator Controller のステートに設定すれば
ステート遷移したときに、踊ってくれるようになります。

表情やリップのVMDも一緒に変換していればFBXにアニメーションとして入っているのですが、モーフは再生されません。
f:id:simplestar_tech:20161127180733j:plain

最後に表情モーフをつける方法を紹介します。
対象となるキャラクターオブジェクトのコンポーネントに次のスクリプトコンポーネントを追加します。
MMD4MecanimAnimMorphHelper.cs
表情やリップのVMDの変換を終えていれば.animファイルが作られていますので、これらをそれぞれのMMD4MecanimAnimMorphHelperに設定します。
f:id:simplestar_tech:20161127181801j:plain
再生するアニメーション名の欄が空欄になっているので、それぞれ「表情」「リップ」を書き込みます。
(アニメーション名を任意に変更しているのであれば、その名前を使います)

※公式の記述を見つけていませんが、スクリプトコンポーネントを追加する順番でモーフは上書きされる仕様のようです。
リップが再生されない場合は、後から追加した AnimMorphHelperコンポーネントの方にリップを追加しましょう。
リップが表情に上書きされるようになり、口パクしてくれるようになると思います。(私の環境では、実際になりました。)

これで、全身のモーションに加えて、表情とリップのモーフが付くようになります。
f:id:simplestar_tech:20161127181655j:plain

おまけ:
購入した楽曲と、モーション付けに参照された曲がちょっとずれていました。
え、今までの人たちはオリジナルの曲を使っていない!?
仕方なく、私は購入した楽曲の余白を調整して、音ズレを回避しています。

参考までに mp3 ファイルの余白調整には
mp3DirectCut - Fast MP3 and AAC editor and MP3 recorder
を使いました。

UnrealEngine4.13で頂点シェーダー

頂点シェーディング方法を探して次のプロジェクトを見つけたのですが
github.com

確かにコンピュートシェーダーとピクセルシェーダは機能していました。
描画ターゲットに結果を書き出して利用する分にはこれが良いかもしれません。

しかし、ずいぶんとトライ&エラーしづらい作りのようです。

ふと World Position Offset に頂点座標ごとのオフセット量を与えられたら
自分の目的が達成できるのではないかと思い、確かめてみました。

こちら、自身の頂点座標(ローカル)の値を使って頂点位置をずらすマテリアルを適用した結果です。

f:id:simplestar_tech:20160912002916j:plain

できたじゃないですか。

どうやって?
こうやって↓

f:id:simplestar_tech:20160912003444j:plain

位置と法線が得られつつ、頂点位置を変更できるとなると
Shape Matching 法とか、弾性体表現が実装できそう。

今日は良い技法を発見しました。

VRHMDのポジショントラッキングについて

VRHMDといっても、今の時代
HTC Vive ですか?
Oculus Rift ですか?
PSVR ですか?
と大きく三つのVRHMDを想像できる時代となりました。
(え、そんなの知らない?そんな方は、この記事は読めないかも。)

今回は Oculus Rift や PSVR で使われている HMD のトラッキングシステムについて
実際に作れるところまで原理を詳しく解説していきたいと思います。

HMD をIR成分も撮像できるカメラ越しに見てみましょう。
すると、次のように小さなLEDが何個も光っていることが確認できます。

f:id:simplestar_tech:20160828175047j:plain
url:http://virtuix1.rssing.com/chan-14788923/all_p2.html

上の写真は Oculus DK2 の頃の様子
現在リリースされている最新の製品版 Rift では次のような配置になっています。

f:id:simplestar_tech:20160828175434j:plain
f:id:simplestar_tech:20160828175442j:plain
url:https://tinhte.vn/threads/ben-trong-oculus-rift-cv1-de-sua-chua-day-gon-gang-cham-diem-7-10.2566840/

これらの LED をカメラで追跡することで、HMDの位置姿勢を求めています。
ん?どのカメラ?

それは、以下のようなカメラです。

f:id:simplestar_tech:20160828175957j:plain
url:http://www.pcworld.com/article/2138461/eyes-on-oculus-rifts-position-tracking-dev-kit-2-vr-headset-blows-the-first-dev-kit-away.html

こちらは DK2 時代のものですね。

f:id:simplestar_tech:20160828180053j:plain
url:http://www.snapvrs.org/how-to-set-up-the-oculus-rift/

そしてこちらが Rift 製品版のカメラ

これらカメラなしでポジショントラッキングを実現しようとしても、できないことに気付くでしょう。
そう、先ほども述べたように、このカメラで HMD の複数の LED を追跡することで HMD の位置姿勢を求めています。

カメラで HMD の複数の LED を追跡することってどういうこと?
とイメージできない人が多いと思いますので、実際にそれを行っている様子が載ったページを以下に紹介します。

www.roadtovr.com

ここまでの話をまとめると、HMD の LED をカメラで追跡しているということです。
あとはこの追跡情報を使って HMD の位置姿勢を求める計算の部分に焦点を当てて、説明していきます。

f:id:simplestar_tech:20160828181651g:plain
url:http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MARBLE/high/pia/solving.htm

イメージ平面に投影された影から元の三次元空間のオブジェクトの位置姿勢を求める計算をすることになります。
ここに良い例が示されていますが、3点の対応だけでは、姿勢が一意に定まらないことがイメージできます。

数学についての知識を得るときは、図形的解釈を伴うように、つねに右脳を働かせて問題をイメージすることが大切です。(たぶん)

そして、問題を具体的に解くためには定式化しなければなりません。
ここで現在のオブジェクトの位置姿勢から考えられるイメージ平面での投影点と、実際に観測されたイメージ平面での投影点とのイメージ平面での距離(イメージスペースエラー)を小さくするように、位置姿勢を修正していくことで問題を解きたいと思います。

上の言葉で示したのが、右脳を働かせて得たイメージです。
そして、そのイメージスペースエラーは式に落とし込めます。

最終的に E = Σe^2 の誤差二乗和で評価関数を定義して
これの多次元でのお椀の底を目指して最適化問題を解きます。

この式、よく見ると求めるパラメータに対して非線形となっているため
非線形最小化問題を解くアプローチを取ることになります。

非線形最適化問題を解く方法として、さまざまなものがあります。
勾配降下法、ニュートン法ガウス・ニュートン法、レーベンバーグ・マーカート法など
微分できない場合についても含めると、もっとあるのですが、私の勉強不足のため今はこれくらいしかうまく説明できません。

さて、ポジショントラッキングは最初にある程度正しい姿勢を求めることができたなら、その後はワープでもしない限り前回の計算結果に似た姿勢となることが期待できます。
そこで、ある程度解に近いことを条件として与えられますので、ガウス・ニュートン法を選択すると効率的に答えに安定してたどり着けると考えられます。
そのガウス・ニュートン法を用いて得られるのは、姿勢情報の更新量です。
得られた更新量を初期姿勢に適用して、解となる HMD の位置姿勢を得るのです。

はい、ここまでの話をすべてまとめると

1.LEDを4点以上カメラで追跡する
2.イメージスペースエラーの式を立てる
3.最適化数学を解く

どんな問題も、最後は誤差関数の最小化に帰着されるそうです。
数学は基礎ですが、訓練が必要なので、いきなり超えられる壁ではありません。
なので、先にわかっている人からイメージを聞き出して、まずは同じイメージを持つことが大切です。

わかっている人が周りにいない場合は、理系の大学に行きましょう。
大学の准教授や教授はこうしたイメージをもっています。
お金を払って聞きましょう。

さて、書きたいことを書いたので、ここで終わりにします。

Windowsから重力方向を求める

加速度センサの情報を拾うコードは次の通りらしい
Using Windows 8* WinRT API from desktop applications | Intel® Software

Unreal Engine 4 からの取得方法を知りたかったのですが
すでにサポート済みであり
そこは Motion をキーワードにすると良いらしいです。

docs.unrealengine.com

最初のアプローチが分かったので
サンプルコードが実際にデバイス情報を返したら、追記したいと思います。