Hatena::ブログ(Diary)

Mi manca qualche giovedi`? このページをアンテナに追加 RSSフィード Twitter

2018-08-26 http だと検索で引っかからなくなりましたね〜

はてなブログに引っ越します


はてなダイアリーも https にならないかな……と思ってましたが、どうもならなさそうなので、はてなブログに引っ越します。


木曜不足
https://shuyo.hatenablog.com/

タイトルは日本語にしただけ。中身はインポートしただけなので、おいおい調整。

2018-07-17 銀座VR といっても銀座をVRでブラブラするわけではありません

#銀座VR に WebVR で行けるようにしてみた

5月に発売されたスタンドアローン(ひも無し) VR ヘッドセットの Oculus Go が想像通りの良いものだったので、会社で100人くらいにかぶせて回ったり、Unity や WebVR でなんかちょこちょこ作ってみたりということを最近している。

7/7 に銀座VR という、VR で作ったものを持ち寄るイベントがあるって直前で気づく。

銀座SIXでマーロウのプリンを買って帰ると言ったら簡単に参加許可が下りたので、のこのこ出かけてきた。



一体型VR限定イベント、つまり発売されたばかりの Oculus Go と Mirage Solo がメインターゲットということで時間が足りなかったか、未完成とかコンセプト重視な展示が中心だったかな。

一体型VRの最大のメリットでもある「持ち寄りやすさ」を活かすような展示があって、みんなが自分の Oculus Go を首から下げて歩いている……というの期待しちゃったりして、一応自分の Oculus Go を持ち込んだりもしてたのだが、カバンから出す機会もついぞなかった。無念。

そう思うなら自分で作れということだな。


こういうイベントは見るだけより自分も展示側で参加するほうが絶対に楽しいしんで、次があれば考えたいかも。

今回は間に合うわけもなかったけど、とりあえず Richo THETA で 360度写真を何枚か撮ったので、それをバーチャルツアー的に見せる VR コンテンツを作ってみた。

VR ヘッドセットで見るのが前提(Oculus Go で動作確認、他のヘッドセットでも動くことを期待するコードを書いたつもり)だが、PC や iPad でも見れる。



ブラウザでリンクを開くと、VR ヘッドセットの場合はブラウザ右下のゴーグルをクリックすると VR モードになり、会場の360度写真の中に入る。

自分の下を見ると会場マップがあるので、緑のマーカーをコントローラーで選択すると、その位置に移動する(写真が切り替わる)。

PCの場合は画面をドラッグすると視線の向きを変えられる。同様に下の方にマップがあるので、クリックで移動する。

iPad は、本体を掲げてぐるぐる周りを見ると、その向きの写真が表示される。移動は下向けてマップをタップ。


360度写真を見る&地図をポイントして移動するだけ。

VR コンテンツとしては簡素すぎるが、これでも十分雰囲気を味わえる。

各展示が再生できたり、出展者の Oculus Rooms の入口があったりしたら、ほんとに現地に行かなくても済むようになるかもw


マップを下においたのは思いつきといくつかの事情からの苦肉の策で、正直操作はしにくい。

でもマップと写真の向きがあっていることで、会場がどんな場所かすごく想像しやすくなっている……と思ったのだがどうだろう(身贔屓?)。


こういった VR コンテンツを作るなら、選択肢としては

のどっちか。

Unity は導入と配布のハードルがかなり高いが、ノウハウたんまり、エコシステム充実(アセットストア)、高パフォーマンスと、本格的なものを作るなら正直一択に近い。

でも、もともと Web 屋さんだった身としては、WebVR の可能性をできるだけ追求したいところ。というわけで Mozilla 謹製 WebVR フレームワーク A-Frame をがんばって使ってみている。

しかしかなりの発展途上で、ぶっちゃけ上の VR コンテンツを作るだけでも明文化されていないノウハウをかき集めたり自分で見つけ出したりしないといけない。とはいえ、コンテンツの配布が極めて容易という特大のメリットは捨てがたい。


今回の VRツアーみたいのが HTML+JS 70行程度で書けるのも WebVR の良いところだろう。

Unity だと開発環境を作るだけで何時間かかかるし、変更のたびにかかるコンパイル時間もバカにならない。


というわけで WebVR にも確実に需要はあるので、現時点でいくつかある A-Frame を使うノウハウについては、別途まとめるつもり。

2017-10-02 他にも大きいのを見つけたら追記するかも

「Chainer による実践深層学習」の気づいたこといくつか



Chainer について書かれた数少ない本。

この9月に v2 対応版が出た。が、v3 リリース秒読みの時期に……というツラミはある*1

深層学習ライブラリは現状「泳ぎ続けなければ死ぬ」(アップデート止まったら、終わったのかな? とか思っちゃう)ので、宿命的にしょうがないのかな。


社内でこの本の読書会とかしており、ちょいちょい間違いを見つけてしまう。

細かいのはもういいかなとは思うんだが(全部書いてたら正直キリがない)、せっかくの Chainer 本、読者が誤解すると事故が起きそうなちょっと大きめの間違いを放置するのはもったいないので、ここにメモしておく。

自分で読んだのは RNN 以降なので、主にその範囲。


以下、章・ページやリスト名などの表記は v1 版だが、v2 版でも残っていれば特定は難しくないと思う。

手元にあるのは v1 版で、v2 版では直ってるかもしれない。が、ちら見した感じでは残ってそうだった……。

ちなみに著者の新納先生のサイトに Erratta も出ているので参考に。見つけた間違いはほとんど載っていないが……。


7.7 Chainer による LSTM の実装(p98-99)


LSTM をあえて基本的な部品だけで実装する、本書の白眉


lstm0.py のパラメータ宣言部で、式 Wx+Rh+b を実装するのに W 用の L.Linear と R 用の L.Linear を宣言しているが、両方がバイアス項を持つため、ダブってしまっている。Wx+Rh+a+b という状態。

致命的な悪さはおそらくしないだろうが、メリットは何もない*2ので、片方に nobias=True をつけて、バイアス項を一本化するべきだろう。

学習時間も 5% ほど短くなる。


class MyLSTM(chainer.Chain):
    def __init__(self, v, k):
        super(MyLSTM, self).__init__(
            embed = L.EmbedID(v, k),
            Wz = L.Linear(k, k, nobias=True),
            Wi = L.Linear(k, k, nobias=True),
            Wf = L.Linear(k, k, nobias=True),
            Wo = L.Linear(k, k, nobias=True),
            Rz = L.Linear(k, k),
            Ri = L.Linear(k, k),
            Rf = L.Linear(k, k),
            Ro = L.Linear(k, k),
            W = L.Linear(k, v),
        )

7.7 Chainer による LSTM の実装(p100)


また学習の部分は素の RNN のものと同じでよいのですが、計算時間がかなりかかります。RNN の学習には unchain_backward() という関数を使うことで改善されます。これは長い系列を学習する際に、古い情報を捨てて、計算時間を改善するのに使います。ここでは文の長さが 30 を超える場合に、この関数を起動することにします。


と記述されているが、残念ながらここでの使い方では unchain_backward は全く効果がない。

本書の lstm0.py で unchain_backward を入れたり削ったりしたときに性能が変わったように見えたとしても、それはおそらく初期値の乱数の影響である。


unchain_backward は、L.LSTM のような「前時刻の隠れユニットや記憶の状態をメンバーとして保持しておき、各時刻ごとに __call__ を呼ぶ」タイプの実装を前提として設計されている。RNN のグラフの横方向の辺を切って、計算グラフを小さくするために、例えば 30 時刻ごとに unchain_backward を発行する。加えて、公式のサンプルを含め、多くの LSTM 実装では「1系列=全データをつなげたもの」なので、切らないと大変なことになる。


しかし、本書の lstm0.py は「__call__ には系列全体を渡す。隠れユニットや記憶の状態は __call__ の先頭でローカル変数として宣言&初期化する」タイプの実装となっている。したがって、前の __call__ のあとに unchain_backward を発行しようがしまいが、次の __call__ が呼ばれたときは計算グラフは切れている。


ちなみに本書では「1系列=1文」であり、truncate しなくても死なない。が、隠れユニットが 100 次元しか無いので、適切に切ったほうがおそらく性能は高くなるだろう。

しかし lstm0.py で truncate したいと思っても、学習ループ(特に backward 発行)と時刻のループが別れてしまっているので、簡単な改造では難しそう。同等ではないが、 __call__ の中で、30時刻ごとに h.unchain() と c.unchain() を発行すれば、近いものになるのかな?


8.5 Attention の導入(p123)


Encoder の各時刻の隠れベクトルを Decoder に渡すためのリスト gh を作る部分の説明。


リスト gh に Encoder 側の ¥tilde{h}_i を順番に追加しています。

(中略)

gh に ¥tilde{h}_i を追加する際に、明示的に np.copy を使っていますが、おそらく必要ありません。そのまま ht.data[0] を渡しても問題ないとは思いますが、念のためコピーしました。


コピーしちゃダメーーー!!!


.data やそのコピーではなく Variable のまま渡さないと、せっかくの計算グラフが切れてしまう。

Decoder に渡す変数(もともとの Attention では隠れユニットを渡すが、最近のモデルでは Encoder の出力を渡すのが流行っている?)の計算グラフを切ってしまうと、「Attention にも有効なように Encoder が符号化してくれる」という Attention の嬉しさの一つが消えてしまう。


というわけで、コピーしないで、Variable のまま渡しましょう。

*1:ちなみに v1 版も、Chainer v2 が出た後の出版、しかも v1.10 準拠だった……

*2:aとbが最適解を持たないというデメリットはある

2017-09-27 最近トピックモデルのコードあんまり書いてないなー

無限関係モデル(Infinite Relational Model)の紹介資料+実装


サイボウズ・ラボでは社内向けの機械学習勉強会を 2012年から週1ペースで継続している(前身の PRML 読書会も合わせれば 2011年から)。割り振られた担当者が、書籍や論文など読んだり、実装してみた話などを紹介している。


例えば今年の4月以降の勉強会のネタをピックアップするとこんな感じ。明らかに「いわゆる機械学習」周辺にすら含みようがないネタもポロポロあるが、「機械について学習」くらいまで拡大解釈している、ことにしてほしい(苦笑)。


  • プライバシー保護データマイニング
  • 並行実行制御
  • 強化学習
  • 状態空間モデル
  • 秘密計算(暗号化したまま各種演算)
  • 確率論
  • seq2seqで計算
  • Attention
  • End-to-End Memory Networks
  • WebAssembly
  • 複雑ネットワーク
  • "Why does deep and cheap learning work so well?"
  • "Sliding right into disaster"

この勉強会の資料は一部公開されている。西尾さんの強化学習や、光成さんの暗号系などなど。



中谷も当勉強会で機械学習自然言語処理のネタを紹介してきたのだが、資料はほとんど公開してなかった。口頭の説明やその場での書き込み前提とか、著作権的な配慮が足りてないとか、内部データを使っちゃってるとか、セキララな毒舌が炸裂してるとか、要は内部勉強会なことに甘えて作りがユルかった。

まあでもやっぱりもったいないので、先週から資料を人に見せられるレベルまで改訂して公開週間を始めた。第1弾が Memory Networks で、第2弾がこの無限関係モデル(Infinite Relational Model)。



無限関係モデルは2年くらい前(↓このあたりのブログ記事を書いていた頃)にやったので、上の最近の勉強会ネタリストにはない。



古いネタを掘り起こしてきたのは、実装があるものを優先したため。



この実装では、スライドでも説明しているとおり、ベルヌーイ分布をポアソン分布に替えた「0/1 じゃない関係解析」版を実装してみている。

が、ポアソン分布が外れ値に弱いので、ちょっと多い項目があると1要素のクラスタを作ってしまい、残念ながら使い物にならなかった。負の二項分布あたりを使いたいところだが、全情報付き事後分布を閉じた形で書き下せないだろう……。

CRP を Stick Breaking で書き直して、トピック数の上限入れて、Stan あたりで解かせてみるというのも考えたけど、ちょっと大きくなるだけで死ぬよな。まずはモデルとして意味があるか検証する、ってならアリかもしれない。


「古いネタ」なんて言っちゃったが、引き続き「続・わかりやすいパターン認識」はノンパラベイズについてきちんと詳解してくれている希少な和書だろう。続パタ以外となると、今なら佐藤一誠さんの「ノンパラメトリックベイズ」(MLP青シリーズ)があるので、もう1つ選択肢がある? でも続パタとは難易度がかなり違うので、読者層は重ならないかもしれない(と、えらそうに評してみたが、買っただけでまだ読んでない。ごめん)。


ノンパラベイズ、というかトピックモデルは昨今の深層学習ブームに押されまくっているが、内部の構造を想像しながらモデリングする楽しさは(一般的な)深層学習には無いものなので、またそのうち揺り戻しが来るかも?


というわけで次の資料公開週間は、実装があるので GAN あたりかな(トピックモデル推しの舌の根も乾かぬうちに……)。

GAN の記事や資料はすでに溺れるほどあるのであまり意味ないかもしれないが、Conditional GAN をやってる人は少ないっぽいので、そのあたりはちょっとおもしろいかもしれない。

2017-09-15 次は DCGAN か無限関係モデルか

End-to-End Memory Networks の勉強会資料+補足


前記事で End-to-End Memory Networks の実装を公開してたが、さらに社内勉強会の資料も公開する。

モデルもわかるように一応説明したつもり。



以下、前記事で書き忘れたこと+補足。

  • 実装は CPU / GPU 両対応している。が、GPU の方が遅い(苦笑)。たぶんデータの渡し方が悪い&モデルが小さいので、演算時間がオーバーヘッドを上回れないのだろう。データの渡し方を工夫すれば改善するだろうが、Random Noise がどうせ台無しにするので、そこを頑張るのはやめた。
  • 質問と記憶から応答情報を生成するのが基本。その応答情報を新しい質問とみなしてフィードバックすることで RNN 的な多層ネットワークを構成することができる。表現力が上がる……のかな? 実装では層の数をオプションで指定できるようにしているので、1層と3層で傾向がどのように変わるのか確認してみるのも面白いかもしれない。