DeepLearning講座(第9回)を受けてきたよ
8/3にDeepLearning講座の9回目を受けてきました。
ついにラスト2回。結構長かったな。。
今回は、強化学習とYOLO(実装)を学習しました。で、その前に
前回書ききれなかったこと
まずは前回力尽きた部分の続きから。生成モデルVAEとGANについて。二つとも画像の生成ができますが、現在の主流はGANです。
VAE(Variational Auto Encoder)
学習データを与えると、その学習データに似ているデータを生成できる生成モデルです。その名の通り、Auto Encoderを使っています。
AutoEncoderは、入力層にデータを入れるとデータをEncodeして隠れ層に渡し、データをDecodeして出力層から出力します。VAEではXとYが同じものを出力するようにモデルを学習させます。
サンプリングしたXを使ってX=Yになるように学習するため、「ノイズが取り除かれ」かつ、「似てるものは近くに、そうでないものは遠くになる」ようにガウス分布(正規分布)からサンプリングします。
実際にはガウス分布の平均μと分散σ^2を出力する部分とそこからサンプリングする部分に別れています。
ガウス分布を使うと数学的に扱いやすくなるので、学習もしやすいのですが、生成データがぼやけてしまうという欠点があります。そのため、VAEが使われなくなったのです。
GAN
GANはGenerative Adversarial Networksの略で、2014年にGoodfellowが提案したもの。VAEのようにデータに対する仮定が少なくて済むのですが、とにかく学習が大変なのです。
ですが、こんなこともできます。(実務では使わないそうです)
ラーメン二郎でProgressive Growing GANを試してみました。生成画像サイズは256,128,64,32pxですが、全画像256pxサイズに揃えてあります。2万2千枚の画像で各ステージ100epoch学習 #ラーメン二郎 #GAN pic.twitter.com/wVwek7qBWn
— Kenji Doi (@knjcode) November 14, 2017
GANの仕組みは下図のように、GeneratorとDiscriminatorという2つのニューラルネットワークを使います。
以下のようなフローで、Generatorが本物と見分けがつかないようなデータを生成するようになります。
- Generatorが生成したデータと本物のデータをランダムにDiscriminatorに入力する
- Discriminatorは入力されたデータが、「Generatorが生成したものか」それとも「本物のデータ」かを判別する
- GeneratorはDiscriminatorに「ニセモノ」だということがバレないように性能をあげる
- Discriminatorは「ニセモノ」であることを正確に判断できるように性能をあげる
最初に生成するデータがメチャクチャなので、どうしてもDiscriminatorが「ニセモノ」と判別しやすくなってしまいます。したがって、最初はDiscriminatorの精度を落としておくことが重要で、この調整が非常に面倒なのです。
最終的にはDiscriminatorは不要になります。
GeneratorはDiscriminatorに見抜かれる確率を最小化し、DiscriminatorはGeneratorが生成した画像を見抜く確率を最大化します。それを満たすための式が以下の通りです。
- D(x): 入力が学習データからきている確率
- x~pdata(x): 学習データの分布に従うデータ
- x~pz(z): Gから生成された出力の分布に従うデータ
- E [ X ]: 期待値
DCGAN
GANではどのようなネットワークを構築すればキレイな画像が生成されるかまでは言及されていませんでした。DCGAN(Deep Convolutional Generative Adversarial Networks)では、以下の指針を出しています。
- Batch Normalization を使う(最も重要)
- Discriminatorでは pooling ではなく stride=2 の畳み込みにする(poolingを使うとぼやける)
- Generatorではdeconvolutionを使う(convolutionで画像を大きくする)
- 全結合層をなくしてGlobal Average Pooling(Pooling時に全体の平均をとる)にする
- DiscriminatorではLeaky ReLU (α=0.2) を使う
- Generatorでは基本的にReLUを使い、出力層だけtanhを使う
で、ここからが本題。
強化学習
教師データは明確でないが、最終的な目標だけが設定されているようなタスクです。例えば、将棋など1手がいいのか悪いのかという正解が与えられないが、最終的なゴールだけは明確なものを指します。AlphaGoなどは強化学習を使っています。
基本的な流れ
以下のことを延々と繰り返して、方策を学習していきます。(強化学習は時間がかかる)
- 最初はランダムに行動する。
- どの行動をとるかは「過去どんな状態だったか」を入力として導き出す。(方策という)
- 行動を何回か取っていくと、報酬が手に入る
- 報酬がプラスだったら「今までの行動はよかった」と学習し、マイナスだったら「今までの行動は悪かった」と学習する
エージェントというソフトウエアが環境ないで観察に基づいて行動をとり、それと引き換えに報酬を受け取ります。うまく行動すれば報酬がもらえて、うまく行動できない場合は罰を食らう、ということを繰り返してだんだん学習していきます。
実際のところ、深層強化学習はキビシイ(by Google Brain Robotics team)のです。
Reward Hackingが起きやすく、報酬を得るために望まない行動をしてしまうからです。(ラクしてしまう)
探索と利用のトレードオフ
「今まで学習してきた中で一番いい方法」だけ取っていてもより良い解は得られないし、「これまでやったことがない方法」だけ取っていても学習の意味がありません。
これらのトレードオフを考慮して、より良い方策を短時間で見つけることが重要です。
強化学習における2つのタイプ
強化学習には多くの種類があるのですが、大きく分けて価値ベースの考え方と方策ベースの考え方という2つのタイプがあります。
価値ベースの方法
ある状態がどれぐらい良いか(例:盤面の状態がどれぐらい優勢か)ということをベースにする方法で、より良い状態にするための行動をします。価値反復法がこれに当たります。
方策ベースの方法
状態は関係なく、方策自体を丸ごとモデル化する方法です。
価値反復法
行動価値
行動価値関数Q(s,a)で表す。状態sの時行動aをとると、どれぐらいの価値が見込めそうかを算出します。
状態価値
状態価値関数V(s)で表す。今の状態sは将来にわたってどれぐらいの価値が見込めそうかを算出します。
今取るべき行動が何かを知りたいという意味で、aが入っているQの方が扱いやすいので、Qをベースに考えていきます。
Q学習
強化学習の中で一番有名なもので、初期状態で確率の遷移と報酬がわからない時に合わせて価値反復アルゴリズムを修正したものです。
期待していた報酬よりも多かった場合はQ(s,a)の値を大きくし、少ない場合は小さくしていくことで、報酬の予想と実際の値が一致してきます。
問題点としては、状態が多すぎるということです。将棋であれば10の220乗あるので、メモリに乗り切らないです。近似するためにニューラルネットワークを使いますが、以下のような工夫が必要です。
Experience Replay
強化学習は時系列データになることが多いのですが、データ間の相関が強いです。(相関が強いとうまくいかない)一旦、状態・行動・報酬を全て保存してそこからランダムにサンプリングして利用します。(将棋であれば、盤の状態、手、その後の情勢を保存しておく。)Q学習と相性がいいです。
報酬クリッピング
強化学習は報酬が非常に重要と言われてきましたが、現実的にはうまくいきませんでした。(大差で勝てば+5点、僅差なら+1点など)
そこで、「良いなら+1」「悪いなら-1」と固定してしまうというのが報酬クリッピングです。調整の余地はなくなりますが、人間の介入がない分学習自体はうまくいくようになります。
Fixed Target
Q値は見込みの値であり毎回変わってしまうので、教師データとして使うには不安定なものです。そこで、ミニバッチを抽出して期待値の計算をしている間だけは重みを固定しておくという方法です。
方策勾配法
価値ではなく、方策そのものを直接モデル化したものです。AlphaGoでもこの方法が取り入れられています。が、ニューラルネットワークで方策勾配法を学習すのはかなり難しいです。AlphaGoで提案されたテクニックは以下の通りです。
- Batch Normalization は必須
- ResNetを使うとよい
- L2正則化を使うとよい
- πとVを1つのネットワークで表現し、πは交差エントロピー、Vは平均二乗誤差(MSE)で、2つの和を損失関数にする
YOLO(オブジェクト認識)
今回は、YOLOというリアルタイムでオブジェクトを認識するフレームワークを使ってみました。
実際のソースはこちら
ではでは。