はじめに
アドベントカレンダーに初めて参加します!
大学2年生の時にオセロの必勝法を探そうと全件探索のプログラムを書いたことをきっかけにオセロのAIを作り始めました。
今まで作ってきたAIは、ランダムで打つAI、アルファーベータ法と評価関数を用いたAI、原子モンテカルロ法、ニューラルネットワークで評価関数を作成したAI、DQNを使ったAIとかれこれたくさんあります。
昔作ったのはソースコードどこにいったか分からないのでご了承を。
今回はDeep Learningを用いたものだけに焦点を当てて紹介していきます。
それでは、AIについて話していきたいと思います!
アーキテクチャ
ソースコードはここにあります。
私が作ったプログラムはjavaとpythonの両方で書かれています。
javaにはAIとオセロのゲームのアルゴリズム、pythonにはニューラルネットワークのモデルがあります。
javaで棋譜の生成(学習データ用)、pythonとTensorflowを用いてニューラルネットワークの最適化を行っています。
理由は初めにjavaでDeep Learningを用いていないAIをつくっていため、Tensorflowを使おうと思った時に、全部pythonに書き換えるのがめんどくさかったので、Thriftという多言語間で通信できるツールを用いてjava -> pythonという形をとっています。
評価方法
私自身オセロが強くないので評価方法に困っていました。
定量評価するために、打てるところをランダムに打つAIにどのくらい負けないのかを評価基準としています。
ちなみに原子モンテカルロ法でプレイアウト200回だと、勝率57%になります。
ニューラルネットワークを用いたAI
盤面の評価にニューラルネットワークを用いたAIについて紹介します。
一日動かして勝率は99%近くまで行きました。
ニューラルネットワークの入力は盤面で8*8のどこに黒石が置かれているかと、白石が置かれているのかの128サイズ。
出力は勝つ確率、負ける確率、引き分ける確率の3サイズでソフトマックス関数を使っています。
ニューラルネットワークのハイパーパラメータは
- 中間層 128*5
- 活性化関数 ReLU
- ドロップアウト なし
- 損失関数 二乗誤差
- 最適化関数 再急降下法
- 学習率 0.1
となります。
学習のデータの作成は同じニューラルネットを使ったAI同士の棋譜と、定期的に評価するのでその時に負けた棋譜を用いています。
AIは次の盤面の一覧から一番勝ちそうな手(1-負ける確率を評価関数としている)を選んでいる。
ただし10回に1回はランダムな手を選んでいる。
このAI同士で100回戦わせた棋譜を用いて学習している。
これに加えて、100回戦わせて学習させるを10回繰り返したところで、評価(ランダムなAIと対戦)して負けた棋譜をその後の10回の学習全てに加えて学習させています。
一日走らせると大体46手以降の勝ち筋は見えているようで、それ以前はほぼ同じ勝率をかえしています。
DQN
最近DQNでAIをつくりなおしました。
使ったテクニック
- ε-greedy
- neural fitted Q
- 体験再生
AlphaGoでは黒白空白の3つの入力をとっていると聞いたので、真似して883の192にしました。
自分の石が白か黒かという情報も入れたほうがいいのかな?とおもい、白と黒の2を足して入力サイズは194としました。
出力は8*8のどこに打つかなので64サイズ。値は-1~1の間にするために活性化関数をtanhにしました。
ハイパーパラメータは
- 中間層 200 * 3
- 活性化関数 ReLU
- ドロップアウト 0.9
- 初期学習率 0.2 1000setpごとに*0.97
- 勾配の最大値を4で固定
- 最適化関数 Adam
- 損失関数 二条誤差
打てない手に関しては-1でで埋めてあげました。(打てない手を打って負けるという学習はしてない)
結果は、、、、学習しませんでした。
損失が小さいと思い、二条誤差の平均ではなく、最大値にしてみたのですが(Q*のアップデートは一箇所だけなので)うまく行かなかったです。
原因は現在調査中です。
今後
CNN使ってみたらもっとつよくなるのでは?と最近思い始めました。
昔はCNNは画像のズレとかに対応するために生まれたと聞いて、オセロって一個ずれたらだいぶ違うから使うのはまずくない?とおもっていたのですが、オセロも隣接している石ほど関係性が高くなるので、CNNを使うともっと効率的に学習できるのではないのかなと思いまいした。
今度はDQN + CNNでオセロのAI作って見たいと思います!