昨日はパラメータをいろいろ変える実験をやってみた。
結論から言えば、そもそも学習がうまくいっていない感じだった。
そして、論文をちょっと調べてみると、○×ゲームに対して関数近似にニューラルネットワーク(+α)を使うものだと、中間層のユニット数に80とか使ってた。
TD Learning of Game Evaluation Functions with Hierarchical Neural Architectures
なので、もっと中間層のユニット数を増やして、学習回数を増やすということをやってみた。
中間層のユニット数を増やす
nn_sarsa_com.rbの動作確認部分を以下のように変えてみて、試してみた。
#==================== # nn_sarsa_com.rb #-------------------- # ニューラルネットワークによる関数近似を使ったSarsa(λ) AI #==================== 〜省略〜 if __FILE__ == $PROGRAM_NAME require "pp" require_relative "game" if ARGV.size == 2 maru_player = NNSarsaCom.load(ARGV[0]) batsu_player = NNSarsaCom.load(ARGV[1]) maru_player.learn_mode = true maru_player.debug_mode = false batsu_player.learn_mode = true batsu_player.debug_mode = false else maru_player = NNSarsaCom.new(Mark::Maru, 128, 0.1, 0.01, 0.6) batsu_player = NNSarsaCom.new(Mark::Batsu, 128, 0.1, 0.01, 0.6) end 1000000.times do |t| game = Game.new(maru_player, batsu_player) if t % 1000 == 0 puts "[#{t}]" game.start(true) else game.start(false) end end maru_player.learn_mode = false maru_player.debug_mode = true batsu_player.learn_mode = false batsu_player.debug_mode = true game = Game.new(maru_player, batsu_player) game.start(true) maru_player.save("nn_sarsa_maru.dat") batsu_player.save("nn_sarsa_batsu.dat") end
これで、1,000,000回、2,000,000回、3,000,000回学習を行わせてみた。
そして、human_com_game.rbを使って、どんな感じか確認。
1,000,000回学習
まずは1,000,000回学習した○から。
$ ruby human_com_game.rb nn_sarsa_maru.1M.dat ... ... ... action 0 value: -0.6384253423315294 action 1 value: -0.915534871351674 action 2 value: -0.9624723176936083 action 3 value: -0.6541022503118152 action 4 value: 0.25946316378451245 action 5 value: -0.7528711154068253 action 6 value: -0.6311246578644901 action 7 value: -0.6530331504039432 action 8 value: -0.5082413661354799 player o selected 4. ... .o. ... <player: x> select index [0,1,2,3,5,6,7,8] 0 player x selected 0. x.. .o. ... action 1 value: 0.18444748366555389 action 2 value: 0.061151779090461884 action 3 value: 0.21488396703965734 action 5 value: 0.2608381850499999 action 6 value: 0.1652323362193739 action 7 value: 0.15561956912672237 action 8 value: 0.1289638820232503 player o selected 5. x.. .oo ... <player: x> select index [1,2,3,6,7,8] 1 player x selected 1. xx. .oo ... action 2 value: 0.2056365582341925 action 3 value: 1.013012032186419 action 6 value: 0.027114708108681718 action 7 value: -0.33521870688406286 action 8 value: -0.18516588956469063 player o selected 3. xx. ooo ... player o win. ... ... ... action 0 value: -0.6384253423315294 action 1 value: -0.915534871351674 action 2 value: -0.9624723176936083 action 3 value: -0.6541022503118152 action 4 value: 0.25946316378451245 action 5 value: -0.7528711154068253 action 6 value: -0.6311246578644901 action 7 value: -0.6530331504039432 action 8 value: -0.5082413661354799 player o selected 4. ... .o. ... <player: x> select index [0,1,2,3,5,6,7,8] 0 player x selected 0. x.. .o. ... action 1 value: 0.18444748366555389 action 2 value: 0.061151779090461884 action 3 value: 0.21488396703965734 action 5 value: 0.2608381850499999 action 6 value: 0.1652323362193739 action 7 value: 0.15561956912672237 action 8 value: 0.1289638820232503 player o selected 5. x.. .oo ... <player: x> select index [1,2,3,6,7,8] 3 player x selected 3. x.. xoo ... action 1 value: -0.20531758438192854 action 2 value: -0.42608861049213714 action 6 value: 0.18744981033893124 action 7 value: -0.18824241617146154 action 8 value: -0.3615798789520989 player o selected 6. x.. xoo o.. <player: x> select index [1,2,7,8] 2 player x selected 2. x.x xoo o.. action 1 value: 0.18500597484534875 action 7 value: -0.3763842415193661 action 8 value: -0.36455079310338945 player o selected 1. xox xoo o.. <player: x> select index [7,8] 7 player x selected 7. xox xoo ox. action 8 value: 0.15997908791792542 player o selected 8. xox xoo oxo draw.
ちゃんと学習できていて、基本的な動きに問題はないことが分かる。
... ... ... action 0 value: -0.6384253423315294 action 1 value: -0.915534871351674 action 2 value: -0.9624723176936083 action 3 value: -0.6541022503118152 action 4 value: 0.25946316378451245 action 5 value: -0.7528711154068253 action 6 value: -0.6311246578644901 action 7 value: -0.6530331504039432 action 8 value: -0.5082413661354799 player o selected 4. ... .o. ... <player: x> select index [0,1,2,3,5,6,7,8] 1 player x selected 1. .x. .o. ... action 0 value: 0.9275310923218346 action 2 value: 0.6236182659350441 action 3 value: 0.6475581770325918 action 5 value: 0.7472332006744651 action 6 value: 0.25701034508012593 action 7 value: 0.014490745597882616 action 8 value: 0.5146151816985466 player o selected 0. ox. .o. ... <player: x> select index [2,3,5,6,7,8] 8 player x selected 8. ox. .o. ..x action 2 value: 0.42225623490039943 action 3 value: 0.5645363300741779 action 5 value: 1.0001798852063186 action 6 value: 0.25894031077052 action 7 value: 0.39390212689375054 player o selected 5. ox. .oo ..x <player: x> select index [2,3,6,7] 3 player x selected 3. ox. xoo ..x action 2 value: 0.12730294609325954 action 6 value: 0.47117886786805424 action 7 value: 0.4711559937367403 player o selected 6. ox. xoo o.x <player: x> select index [2,7] 2 player x selected 2. oxx xoo o.x action 7 value: -0.36212354242755396 player o selected 7. oxx xoo oox draw.
けど、×が2手目で角でなく辺をとったとき、本当なら○は必勝なんだけど、まだ勝ちきれてない。
... ... ... action 0 value: -0.6384253423315294 action 1 value: -0.915534871351674 action 2 value: -0.9624723176936083 action 3 value: -0.6541022503118152 action 4 value: 0.25946316378451245 action 5 value: -0.7528711154068253 action 6 value: -0.6311246578644901 action 7 value: -0.6530331504039432 action 8 value: -0.5082413661354799 player o selected 4. ... .o. ... <player: x> select index [0,1,2,3,5,6,7,8] 2 player x selected 2. ..x .o. ... action 0 value: 0.9777936166398172 action 1 value: 0.6127621228550149 action 3 value: 0.5605556232162823 action 5 value: 0.6789277972000003 action 6 value: 0.05415146624205671 action 7 value: 0.5506402990803502 action 8 value: 0.4952653275565266 player o selected 0. o.x .o. ... <player: x> select index [1,3,5,6,7,8] 8 player x selected 8. o.x .o. ..x action 1 value: 0.07337201293239404 action 3 value: 0.4678394751545193 action 5 value: 1.004183654776937 action 6 value: -0.2892653944483668 action 7 value: 0.6107326257814774 player o selected 5. o.x .oo ..x <player: x> select index [1,3,6,7] 3 player x selected 3. o.x xoo ..x action 1 value: 0.2746474047341685 action 6 value: -0.12908173542987214 action 7 value: 0.6813908808988143 player o selected 7. o.x xoo .ox <player: x> select index [1,6] 1 player x selected 1. oxx xoo .ox action 6 value: -0.36212354242755396 player o selected 6. oxx xoo oox draw.
それと、×が2手目に角をとったときも、3手目に対角の角をとるのが唯一ダブルリーチをかけうる手として有効なんだけど、それは選べていない。
(もっとも、相手が間違わなければ結局引き分けになるので、必ずしもいい手とは言えず、学習できなくても仕方ない部分はある)
今度は×側。
$ ruby human_com_game.rb nn_sarsa_batsu.1M.dat ... ... ... <player: o> select index [0,1,2,3,4,5,6,7,8] 4 player o selected 4. ... .o. ... action 0 value: -0.1900836910211487 action 1 value: -0.8236444973368885 action 2 value: -0.8486270508436535 action 3 value: -0.8873613253712567 action 5 value: -0.758398040197464 action 6 value: -0.8111736412648833 action 7 value: -0.6322622190070192 action 8 value: -0.8725318337820029 player x selected 0. x.. .o. ... <player: o> select index [1,2,3,5,6,7,8] 1 player o selected 1. xo. .o. ... action 2 value: -1.0078805146339507 action 3 value: -0.8830521317774014 action 5 value: -1.002836083869443 action 6 value: -0.833267367145659 action 7 value: -0.1308635352668934 action 8 value: -1.0089831490698378 player x selected 7. xo. .o. .x. <player: o> select index [2,3,5,6,8] 2 player o selected 2. xoo .o. .x. action 3 value: 0.00648881972849324 action 5 value: -0.4155077875418149 action 6 value: 0.9437774338964601 action 8 value: -0.1511934635453121 player x selected 6. xoo .o. xx. <player: o> select index [3,5,8] 3 player o selected 3. xoo oo. xx. action 5 value: 0.20884684703205691 action 8 value: 0.992052568338876 player x selected 8. xoo oo. xxx player x win. ... ... ... <player: o> select index [0,1,2,3,4,5,6,7,8] 4 player o selected 4. ... .o. ... action 0 value: -0.1900836910211487 action 1 value: -0.8236444973368885 action 2 value: -0.8486270508436535 action 3 value: -0.8873613253712567 action 5 value: -0.758398040197464 action 6 value: -0.8111736412648833 action 7 value: -0.6322622190070192 action 8 value: -0.8725318337820029 player x selected 0. x.. .o. ... <player: o> select index [1,2,3,5,6,7,8] 3 player o selected 3. x.. oo. ... action 1 value: -0.7616556192475423 action 2 value: -0.7878774995933671 action 5 value: -0.1632975529245576 action 6 value: -0.996042458814271 action 7 value: -0.8290367119178917 action 8 value: -0.9895632496819957 player x selected 5. x.. oox ... <player: o> select index [1,2,6,7,8] 2 player o selected 2. x.o oox ... action 1 value: -0.5865577446007091 action 6 value: -0.05966381732725559 action 7 value: -0.4815546866904667 action 8 value: -0.8407652821779832 player x selected 6. x.o oox x.. <player: o> select index [1,7,8] 7 player o selected 7. x.o oox xo. action 1 value: -0.06924475636425696 action 8 value: -0.4784696283061711 player x selected 1. xxo oox xo. <player: o> select index [8] 8 player o selected 8. xxo oox xoo draw.
こちらも、○が初手に中央を選んだ場合、うまく動いているように見える。
... ... ... <player: o> select index [0,1,2,3,4,5,6,7,8] 4 player o selected 4. ... .o. ... action 0 value: -0.1900836910211487 action 1 value: -0.8236444973368885 action 2 value: -0.8486270508436535 action 3 value: -0.8873613253712567 action 5 value: -0.758398040197464 action 6 value: -0.8111736412648833 action 7 value: -0.6322622190070192 action 8 value: -0.8725318337820029 player x selected 0. x.. .o. ... <player: o> select index [1,2,3,5,6,7,8] 8 player o selected 8. x.. .o. ..o action 1 value: -0.08580172511858725 action 2 value: -0.1812125333609481 action 3 value: -0.10652277622639911 action 5 value: -0.35044734225024077 action 6 value: -0.1626385143626745 action 7 value: -0.42846579410247126 player x selected 1. xx. .o. ..o <player: o> select index [2,3,5,6,7] 2 player o selected 2. xxo .o. ..o action 3 value: -0.41818270113448186 action 5 value: -0.6936618647126002 action 6 value: -0.10963240068301644 action 7 value: -0.8813137393413762 player x selected 6. xxo .o. x.o <player: o> select index [3,5,7] 5 player o selected 5. xxo .oo x.o player o win.
ただ、3手目に対角の角をとる手には、正しい手を返せていない。
なので、○側がダブルリーチをかけて勝ちに。
... ... ... <player: o> select index [0,1,2,3,4,5,6,7,8] 0 player o selected 0. o.. ... ... action 1 value: -0.930615564169817 action 2 value: -0.3383203438149795 action 3 value: -0.16145724154568342 action 4 value: 0.8866202777561818 action 5 value: -0.3048957449580068 action 6 value: 0.23307798372872368 action 7 value: -0.12866213326407064 action 8 value: -0.2888226579158698 player x selected 4. o.. .x. ... <player: o> select index [1,2,3,5,6,7,8] 8 player o selected 8. o.. .x. ..o action 1 value: 0.5811231027084429 action 2 value: 0.6132616932547067 action 3 value: 0.7458619441626833 action 5 value: 0.676596669785986 action 6 value: 1.0322977006355092 action 7 value: 0.8700908300945057 player x selected 6. o.. .x. x.o <player: o> select index [1,2,3,5,7] 2 player o selected 2. o.o .x. x.o action 1 value: 0.4906398058259285 action 3 value: 0.6359338022378526 action 5 value: 0.7645183783403294 action 7 value: 0.6701144323202824 player x selected 5. o.o .xx x.o <player: o> select index [1,3,7] 1 player o selected 1. ooo .xx x.o player o win.
また、初手角に2手目中央は正しいんだけど、3手目に対角の角をとる手に対しては、正しく対応できていない。
ちょっと注目したいのが評価値で、3手目の手に対して、×は「自分の方がどの手を選んでも悪くはない」と評価している。
本当は2と6は負けで、それ以外なら引き分けというのが正しい評価なのに。
これはおそらく、○側が初手に中央におけば負けはほぼないと学習しているので、初手に角をとる展開の学習があまり進んでいないせいだと思う。
2,000,000回学習
次に、2,000,000回学習した○。
$ ruby human_com_game.rb nn_sarsa_maru.2M.dat ... .o. ... <player: x> select index [0,1,2,3,5,6,7,8] 1 player x selected 1. .x. .o. ... action 0 value: 0.21399304154377707 action 2 value: 0.26680531561272836 action 3 value: 0.07091729329326303 action 5 value: 0.17022912584938454 action 6 value: -0.07516072642342853 action 7 value: -0.414071889709609 action 8 value: 0.18308793785059632 player o selected 2. .xo .o. ... <player: x> select index [0,3,5,6,7,8] 6 player x selected 6. .xo .o. x.. action 0 value: -0.27954744795511255 action 3 value: 0.2241962694735558 action 5 value: -0.13418067959906277 action 7 value: -0.5741938238611988 action 8 value: 0.08886857277736813 player o selected 3. .xo oo. x.. <player: x> select index [0,5,7,8] 5 player x selected 5. .xo oox x.. action 0 value: -0.512101873589874 action 7 value: -0.5184792086645776 action 8 value: 0.12791651090714398 player o selected 8. .xo oox x.o <player: x> select index [0,7] 0 player x selected 0. xxo oox x.o action 7 value: -0.10170807822382194 player o selected 7. xxo oox xoo draw.
2手目で角でなく辺をとったときの変化を見てみたけど、先程と手は違うものの、やはりまだ勝ちきれていない。
そして、問題の×側の学習が進んでいるかどうか。
$ ruby human_com_game.rb nn_sarsa_batsu.2M.dat ... ... ... <player: o> select index [0,1,2,3,4,5,6,7,8] 4 player o selected 4. ... .o. ... action 0 value: -0.1662308645007604 action 1 value: -0.27582649924500646 action 2 value: -0.7479230758108915 action 3 value: -0.6539746305935441 action 5 value: -0.6924270205638651 action 6 value: -0.36107594291264583 action 7 value: -0.25677261799922063 action 8 value: -0.7454031770466045 player x selected 0. x.. .o. ... <player: o> select index [1,2,3,5,6,7,8] 8 player o selected 8. x.. .o. ..o action 1 value: -0.04341244781633334 action 2 value: -0.02891715971133455 action 3 value: -0.38579302323214254 action 5 value: -0.5737850879884117 action 6 value: -0.02070418363911177 action 7 value: -0.20109510048511056 player x selected 6. x.. .o. x.o <player: o> select index [1,2,3,5,7] 3 player o selected 3. x.. oo. x.o action 1 value: -0.45250989282085186 action 2 value: -0.8664153429768638 action 5 value: -0.040576358106760704 action 7 value: -0.6282043508997157 player x selected 5. x.. oox x.o <player: o> select index [1,2,7] 1 player o selected 1. xo. oox x.o action 2 value: -1.0199395126272308 action 7 value: -0.20034837099222863 player x selected 7. xo. oox xxo <player: o> select index [2] 2 player o selected 2. xoo oox xxo draw.
まず、3手目に対角の角をとる手に対しては、引き分けに持ち込めていた。
... ... ... <player: o> select index [0,1,2,3,4,5,6,7,8] 0 player o selected 0. o.. ... ... action 1 value: -0.627934009768803 action 2 value: -0.374295909848463 action 3 value: -0.29471196718617143 action 4 value: 0.8569565557066451 action 5 value: -0.28462818166512854 action 6 value: 0.15738426110486342 action 7 value: -0.017943301932075408 action 8 value: -0.18144418196005707 player x selected 4. o.. .x. ... <player: o> select index [1,2,3,5,6,7,8] 8 player o selected 8. o.. .x. ..o action 1 value: 0.7273312287934622 action 2 value: 0.0022440262089555964 action 3 value: 0.22037801625852388 action 5 value: 0.04569318986109555 action 6 value: 0.9454284821249213 action 7 value: 0.7156208932366872 player x selected 6. o.. .x. x.o <player: o> select index [1,2,3,5,7] 2 player o selected 2. o.o .x. x.o action 1 value: 0.3927525606022284 action 3 value: 0.44136296993650503 action 5 value: 0.35557966662382917 action 7 value: 0.2847452958559024 player x selected 3. o.o xx. x.o <player: o> select index [1,5,7] 1 player o selected 1. ooo xx. x.o player o win.
一方、初手に角をとる手に対しての3手目の対応は、まだダメ。
というか、悪化してる?(5手目でどちらも防いでない)
3,000,000回学習
最後に3,000,000回学習したとき。
まずは○から。
$ ruby human_com_game.rb nn_sarsa_maru.3M.dat ... ... ... action 0 value: -0.9415615592924272 action 1 value: -0.9815831643858545 action 2 value: -0.8517866076452478 action 3 value: -0.892277885110353 action 4 value: 0.15092839421521506 action 5 value: -0.8937533323322292 action 6 value: -0.6534500628697018 action 7 value: -0.585164825122806 action 8 value: -0.558656529425552 player o selected 4. ... .o. ... <player: x> select index [0,1,2,3,5,6,7,8] 1 player x selected 1. .x. .o. ... action 0 value: 0.8031422298251727 action 2 value: 0.5826714986728899 action 3 value: 0.8224045269816568 action 5 value: 0.4445042011149764 action 6 value: 0.4795968812366707 action 7 value: -0.2896421084130507 action 8 value: 0.36150903544957064 player o selected 3. .x. oo. ... <player: x> select index [0,2,5,6,7,8] 5 player x selected 5. .x. oox ... action 0 value: 0.8117220801839892 action 2 value: 0.7619087098275175 action 6 value: 0.6762723899778648 action 7 value: -0.10397670506971057 action 8 value: 0.5343045870951286 player o selected 0. ox. oox ... <player: x> select index [2,6,7,8] 8 player x selected 8. ox. oox ..x action 2 value: 0.5466933746580053 action 6 value: 0.8533138535059319 action 7 value: -0.18131820367785811 player o selected 6. ox. oox o.x player o win.
これはちゃんと勝ち切るようになった。
そして、×側。
$ ruby human_com_game.rb nn_sarsa_batsu.3M.dat ... ... ... <player: o> select index [0,1,2,3,4,5,6,7,8] 0 player o selected 0. o.. ... ... action 1 value: -0.8528004949472243 action 2 value: -0.07257357448318578 action 3 value: -0.08757566990841371 action 4 value: 1.0118214073090024 action 5 value: -0.0893702977427476 action 6 value: 0.26535360081180187 action 7 value: -0.040401331219792204 action 8 value: 0.17497716703464128 player x selected 4. o.. .x. ... <player: o> select index [1,2,3,5,6,7,8] 8 player o selected 8. o.. .x. ..o action 1 value: 0.9635049032162698 action 2 value: 0.7691565704156706 action 3 value: 1.0001644753337855 action 5 value: 1.006700016376803 action 6 value: 1.0139735228068516 action 7 value: 1.0214054482106454 player x selected 7. o.. .x. .xo <player: o> select index [1,2,3,5,6] 1 player o selected 1. oo. .x. .xo action 2 value: 0.5795300922674106 action 3 value: 1.0038826689778526 action 5 value: 1.0020996989646078 action 6 value: 0.8141843688905738 player x selected 3. oo. xx. .xo <player: o> select index [2,5,6] 2 player o selected 2. ooo xx. .xo
惜しい・・・ 2手目は正しく対応できるようになってるんだけど、続く4手目がまだダメ。
ということで、まだダメな部分もあるけど、中間層のユニット数を増やすと、だいぶ良くなっている感じはある。
ただし、これはニューラルネットワークの汎化性に任せているというよりかは、単純に状態関数の近似の誤差が少なくできているからのように思う。
本当は、ゲーム自体の持つ特徴を学習してもらいたいのだけど・・・
ちなみに、また別のインスタンスで学習を1,000,000回、2,000,000回と試したけど、そちらについても大体同じような学習結果になっている。
なので、そこまでバラツキはないのだと思われる。
もちろん、ランダム性があるので、必ずしも同じ学習回数で同程度の性能が出るとは限らないのだけど。
課題
一つ、大きな課題として、○側は初手中央が有利だと分かると、基本的にそればかりやるので、それ以外の手について(×側も含めて)学習が進みにくくなる、というのがある。
なので、人が○側を持ち、初手角とかをやった場合に、×側は学習が足りなくて、途端に弱くなってしまう。
これはクローズなゲーム会とかでもよくある話で、仲間内だけでプレイしていると、プレイが局所最適に陥ってしまって、それ以外の展開に強くなれなかったりすることが起きてくる。
もちろん、そうなってしまったとしても、たまに実験的なプレイが繰り返される中で、局所最適から抜け出すこともあるのだけど、そのためには実験的な手を行った後に続く手がちゃんとしたものになってないといけない。
これはなかなか難しい。
そこで、一つ考えられる手として、複数のインスタンスを用意しておいて、いろんなインスタンスと対戦させるようにするという方法が考えられる。
そうすれば、局所最適に陥ってしまう可能性が低くなりそう。
それについてはまた明日。
今日はここまで!