シンギュラリティと怠惰

この記事は VOYAGE GROUP techlog / Advent Calendar 2016 の記事として書いています。ダラダラした記事になっているのでお暇な時にどうぞ。

今年の個人的な流行語を挙げると「今夜勝ちたい」と「シンギュラリティ」になるでしょうか。前者は今年1年間、ストリートファイター5を毎夜練習しては負け、練習しては負けを繰り返した気持ちが強く現れている良いワードです。弊社はゲームサークルがあり、日夜練習に励んでいるので興味がある方は連絡ください。後者はなんか今年のワードな気がしたのですが、以下を見ると 2014 年から盛り上がり続けているようですね。

このもし来るかもしれないシンギュラリティ後の世界、人工知能が人間を上回った世界とされていますが、これによりロボットに支配されちゃうー、とか仕事がなくなっちゃうー、とか色々想像されていますね。

f:id:jewel12:20161220181142j:plain

ところでこれは生筋子(450gほど)を塩水につけて、菜箸でほぐしているところです。

人間のやることがなくなっても時間と自由がある限り、生筋子を菜箸でほぐすとか色々おもしろいことに挑戦できるようになったりするのではないかと僕は楽観的です。あ、でもやっぱりごろごろしてるだけの怠惰な生活を送るかも……。

さて、僕は人工知能はプログラムを書けるのかというものに興味があります。プログラムを書いてくれるならだらだらゲームをして過ごせるので

プログラムを自動生成する方法で自分が考えつくのは、大量のコードを集めてそれらを何らかのブロックで分割し、期待した結果がでるようにブロックを並べ替えできるよう機械学習していくことです。なのでそのようなものを作ります。下の記事でも Python コード片を集めて、それっぽく動きそうなコードを生成しています。

postd.cc

f:id:jewel12:20161221152122j:plain

次は筋子の筋を取り除くために塩水で洗っていきます。手でかき混ぜて浮いてきたゴミをすくって捨てる、を数回繰り返します。

f:id:jewel12:20161221153143j:plain

洗った後です。きれいになりましたね。ちょいちょい筋が残っているのは取り除くのがだるくなったからです。

それっぽいコード生成する太郎は残念ながら自分で仕事を見つけてくれないので、いったんお仕事を与えましょう。今回は数列のソートをしてもらうことにしました。ちなみに機械にソートさせることすら放棄した記事はこちらです。

ソートをするための簡単な DSL を組んで、コード辺の組み合わせを選んでいく強化学習を目指します。強化学習というとあれです。人工知能Atari 2600 の Pong を攻略する動画を見たことある人もいるのではないでしょうか。ざっくり言うと、ある状態で、ある操作をした結果の報酬をもらい、たくさん報酬がもらえるようにどういう操作をすればよいのか学習していくというものです。僕もたくさん報酬がもらえるように日々頑張っています。(゚∀゚)人(゚∀゚)ナカーマ

f:id:jewel12:20161221155926j:plain

醤油・酒・みりん・昆布を入れて沸騰させた様子です。つけ汁になります。

DSL を組むと言いましたがやっぱり面倒なのでやめましょう。操作できることをもう少し単純化して、数値の入れ替えを繰り返すことでソートを目指すようにしました。コード片の入れ替えではなく、213 の 1 番目と 2 番目を入れ替えるというような操作の学習になります。もはやコードを書かせるという目的はなくなりましたが仕事ができれば良いのです。

実際にコードをアウトプットすることの利点は、人間が理解できる(かもしれない)アウトプットにすることにより、人間による調整の余地があるところかなと思います。まあ人の手を介さずになんかいい感じにちゃんと動けばええのや。

実際はレジスターなどを作ってもう少し複雑な操作をできるようにした結果、人間には理解できないような操作が有効に働くのではみたいな、ほのかな期待があったのですが面倒なのでやめましょう。

f:id:jewel12:20161221162458j:plain

おっ、もしかしてこれはいくらですかね?そうですね。美味しいです。

今回は Q-leaning という手法を使います。詳細は以下が分かりやすいです。

qiita.com

Q-learning で必要なものは以下の 3 つです。

  • 状態
  • 操作
  • 報酬

状態は今回の場合、0123456789 のような数列になります。その状態下でどう操作(入れ替え)をしたらどういう状態になったか、その結果の報酬はどうだったかということを知り、操作に対する期待値を学んでいきます。

報酬はどうやって設定すればよいでしょうか。ちゃんとソートできたら 1, それ以外は 0 にしましょう。良い報酬を与えるとよく働いてくれるかもしれませんが良い報酬を考えるのも面倒ですね。

学習の時、次にどういう操作をしようかというのを決める方法に ε-greedy というものがあるのでこれを使います。これは通常時は期待値の高い操作を選んでいき、ある確率でランダムに操作を選ぶ方法になります。たまに横道にそれるともっといい方法があったみたいなのを生み出します。

f:id:jewel12:20161221164028j:plain

おっとここでカニが登場だー!昨日はカニ鍋をしました。欲望に忠実ですね。

今回は要素数が 7 の数列を並べ替えます。

学習をせずにランダムに入れ替えていくと、10271 回で並び替えられました。頑張ったね。5 回学習すると、15 回の並び替えでうまくいきました。本当は入力値を何回も変えてその結果の平均を見たりするべきですが面倒さがあります。

入れ替えの様子です。実行したコードはこちらになります。

input: 6,4,5,2,1,3,0

...
-----------
step 10, SwapPosAAndPosB(6,4)
[4, 3, 1, 0, 6, 2, 5] -> [4, 3, 1, 0, 5, 2, 6]
max_q: 0.000000
-----------
step 11, SwapPosAAndPosB(3,2)
[4, 3, 1, 0, 5, 2, 6] -> [4, 3, 0, 1, 5, 2, 6]
max_q: 0.512000
-----------
step 12, SwapPosAAndPosB(5,0)
[4, 3, 0, 1, 5, 2, 6] -> [2, 3, 0, 1, 5, 4, 6]
max_q: 0.640000
-----------
step 13, SwapPosAAndPosB(2,0)
[2, 3, 0, 1, 5, 4, 6] -> [0, 3, 2, 1, 5, 4, 6]
max_q: 0.800000
-----------
step 14, SwapPosAAndPosB(5,4)
[0, 3, 2, 1, 5, 4, 6] -> [0, 3, 2, 1, 4, 5, 6]
max_q: 1.000000

知ってる状態までランダムに入れ替えまくって、知ってる状態になったらどんどんゴールを目指していくという感じですね。

100 回学習では 4 回の入れ替えです。よくやった。

step 0, SwapPosAAndPosB(6,0)
[6, 4, 5, 2, 1, 3, 0] -> [0, 4, 5, 2, 1, 3, 6]
max_q: 0.512000
-----------
step 1, SwapPosAAndPosB(4,1)
[0, 4, 5, 2, 1, 3, 6] -> [0, 1, 5, 2, 4, 3, 6]
max_q: 0.640000
-----------
step 2, SwapPosAAndPosB(5,2)
[0, 1, 5, 2, 4, 3, 6] -> [0, 1, 3, 2, 4, 5, 6]
max_q: 0.800000
-----------
step 3, SwapPosAAndPosB(3,2)
[0, 1, 3, 2, 4, 5, 6] -> [0, 1, 2, 3, 4, 5, 6]
max_q: 1.000000
-----------

早くなってよかったみたいなこと言ってますが、学習により知識が増えた結果、知ってる状態に早く到達できるようになっただけです。早くソートしてほしいなら、入れ替えステップ数に応じて報酬を減らしたり増やしたりする必要がありそうです。問題が複雑になると報酬についてもやはり色々考えないといけなくて面倒ですね。

強化学習をベースにしたやり方で良いなぁと思うのは、入力に偏りがある場合それに最適化されたソート方法が学習されるかもしれないというところです。便利やーと思ったのですが、今回やったのと似たような研究があるよと同僚に教えられたのでままならない。

f:id:jewel12:20161221174540j:plain

これは曇っていますが、カニの出汁をよく吸った雑炊といくらですよ。

素数 7 桁で頑張ってましたが、10 桁にしたら学習に異常な時間がかかるようになりました。最初の知識が少ない状態で、ランダム入れ替えによるゴール到達が難しくなったからだと思います。学習のコードは雑に書いたような気がしますが、遅くなった理由はプログラマーの腕がヘボだからだったというだけではありません。たぶん……

Pong を人工知能にクリアさせる場合、どれくらいの状態があるのか考えるだけでお腹いっぱいです。ここでニューラルネットワークが出てきます。Q-learning にニューラルネットワークを組み込んだ DQN (Deep Q Network)というものがあり、先のリンク先に詳しく書かれています。DQN で頑張るところまでやりたかったですが、いくらや鍋を作るのに夢中になって面倒になりました。

来年は怠惰にならないよう頑張ります。年始は人工知能と共に暮す生活を夢見たいです。

次の VOYAGE GROUP Advent Calendar の記事に期待!