Help us understand the problem. What is going on with this article?

ちょいワルQ-Networkの話

More than 3 years have passed since last update.

春の陽気が待ち遠しい今日この頃,皆様いかがお過ごしでしょうか.
はじめまして,休日Deep Learning勢の329と申します.

はじめに

DQNの生い立ち + Deep Q-NetworkをChainerで書いた
http://qiita.com/Ugo-Nama/items/08c6a5f6a571335972d5

東方ProjectをDeepLearningで攻略した…かった。
http://qiita.com/imenurok/items/c6aa868107091cfa509c

これらの記事に影響を受け,
「DQNってもっと面白いことできるんじゃないの」
「DQN,強化学習,Deep Learningに興味を持ってもらうためのライトな記事を書こう」
などと考え,この記事を書きました.

対象読者

  • DQNって聞いたことあるけど.詳しくは知らない(詳しく知るためのモチベが欲しい)
  • DQNの気分を味わい,知った気になりたい

以上のような方に読んで頂き,将来的に面白コンテンツが1つでも増えれば良いと思っています.
DQNの,よりDeeeepな解説は強い技術者・研究者の皆様にお願いしたいと思います.

攻略対象

この記事では,ニューラルネットワークを使って「後出しジャンケン」を攻略します.
相手が出した手を見た後に自分のジャンケンの手を決定し,勝利するDQNなAIを生み出します.

プログラムと解説

github

上記のプログラムは, 状態を入力すると,各行動の良さを出力することを目指して学習します.
後出しジャンケンで言うなら,「相手の手を見た時に,グー,チョキ,パーがそれぞれ何点くらいの価値がありそうかを計算する」ことに相当します.
勝利で1点,負けたら-1点,あいこでは0点が得られることにすると,相手の手を見た後の自分の手の価値は以下のようになります.

グーの価値 チョキの価値 パーの価値
相手がグー 0 -1 +1
相手がチョキ +1 0 -1
相手がパー -1 +1 0

# 後出しジャンケンゲームに関してはこの表があれば既に必勝ですね?

相手の手を入力した際に,対応する列を出力するモデルを学習により獲得します.
以下がニューラルネットワークに関する記述です.

class DqnModel(Chain):
    def __init__(self,num_of_state,num_of_action):
        self.num_of_state = num_of_state
        self.num_of_action = num_of_action
        super(DqnModel, self).__init__(
                state=F.EmbedID(num_of_state, 32),  
                l2=L.Linear(32, 64),
                l3=L.Linear(64, 64),
                l4=L.Linear(64, 32),
                q_action=L.Linear(32, self.num_of_action, initialW=np.zeros((self.num_of_action, 32), dtype=np.float32))
        )

    def __call__(self, state, target, train=True):
        h = self.state(state)
        h = self.l2(h)
        h = self.l3(h)
        h = self.l4(h)
        h = self.q_action(h)
        if train:
            loss = F.mean_squared_error(h, target)
            return loss
        else:
            return h

後出しジャンケンゲームでは状態が3つ,行動が3つ存在するので以下のように初期化します.

model = DqnModel(num_of_state=3,num_of_action=3)

ネットワークの出力が,教師信号に近付くように最適化問題を解きます.
以下の記述で,最適化手法を選択しています.いろいろあります.

optimizer = optimizers.Adam()
optimizer.setup(model)

以上で準備は完了です.あとはデータを用意して,

optimizer.zero_grads()
loss = model(state, target)
loss.backward()
optimizer.update()

とすると最適化問題を解いて,「後出しジャンケンゲーム」の関数近似による攻略を試みます.
githubからcloneたプログラムを実行すると,以下のような結果が得られると思います.

[[ 0.02005649 -0.00832902 -0.01909292]]
相手    :  チョキ
あとだし :  グー

やりました.
後出しジャンケンゲームを「ちょい悪 Q Network」で攻略することができました.

残された課題

私が書いたプログラムでも,「後出しジャンケン」のような小規模なゲームなら攻略することができます.
しかし,以下のような課題からこのプログラムを通常のゲームに用いることは難しそうです.

1.「状態に対する行動の良さ」の測定方法が不明である
2. 状態の番号付けが困難(TVゲームの画面状態って,いったいどのくらいあるの?)

上記の問題は.今回私がお見せしたプログラムが「なんちゃってDQN」だったことに由来しています.
つまり「本物のDQN」は,これらの問題を何らかの方法で解決しているということです.

どうです,気になってきましたか?

おわりに

読んで下さった方がもれなく「私気になります」となったなら私は小躍りでもしそうになるわけですが,
きっとそのようにはならないのだろうと予測しています.
ぜひとも不明な点や間違っている点などなどなどなど,コメントとして投稿して頂ければと思います.

Chainerはいいぞ

_329_
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away