11
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RNN(LSTM)で藤井聡太と羽生善治と加藤一二三の将棋AI作ってみる〜フルスクラッチで挑戦!!

Last updated at Posted at 2018-08-27

はじめに

藤井聡太くんや加藤一二三さんなどで今年少し話題になっている将棋ですが
今勉強しているRNNでなんか面白いことはできないかと思ってやってみたものです

細かい話抜きで、実際に使ってみたい方は後ろの方の使ってみたい方へ〜をご覧ください

今回のAIは,パラメータが保存されているので,githubからクローンしていただければ使用できます

sports_syougi_taikyoku_suit.png

将棋.JPG

最近勉強していることリンク集

目標

藤井聡太と羽生善治と加藤一二三の戦略を持つ将棋AIを作る
ここでいうAIは,実際のゲームなんかで相手の手と自分の手を打ったら,
この手がいいんじゃない?と提案を行ってくれるものとします

※AIという表現はいまいち不適切かと思いますが,いろんな方に理解していただきたく,この表現にしました!

結果と結論

なんとなく形になるものができました
実際のゲームに使うことができそう!!?

いろいろと問題はありますが
途中までAIを使って,戦況を有利にできるかもしれません!

環境

  • windows10(Linuxだと棋譜のテキストファイルがasciiになっていて開かないので、今度時間があるときにLinuxでもできるようにします)
  • python3.6.6
  • anaconda
  • matplotlib 2.2.2
  • numpy 1.14.3

従来の将棋AI作成法

ゲームに対してよく用いられるのは強化学習です
強化学習については,こちらで,触れているように,価値が高くなるように自身の行動を決定します
簡単にいうと,たくさんプレイしてみて,覚えている中で一番いいなこれっていう場面になるように,自分のアクションを決定するってことです
詳細は,上記のリンクをみてください(0から説明しています)

ただ,これはいろんな人が提案しているし,囲碁ではAlpha碁なんかでも話題になりましたし,ちょっと実装するには手間がかかります
ゲームの詳細情報も作らなきゃだし,特に将棋は取った駒を使えるので難しいみたいですね

なので今回は簡単にやってみたいという思いから違う手法をとります

今回のアプローチと考え方

LSTMを用います
LSTMは時刻歴のデータを学習する手法です
つまり,言葉の流れなんかを学習できるわけです

翻訳や,画像の文章生成,文章生成などなどたくさんの言語の問題に応用されています

でふとおもったのですが

将棋の手の流れを学習することはできないかなぁということです

将棋は,

’4三歩’

のように,自分の打った手を表現することができます
そして,これらは棋譜として,記録されています

ということは

プロ棋士たちの戦いの棋譜を学習できるのではないかと考えたわけです

数学的な話に置き換えると
ある手が出てきたときに,次の手が’・・・’になる確率を求めることができれば,プロ棋士たちの指し手を表現できるのではないか?

ということです
これは言語モデルの考え方を参考にしています

さらに,加藤一二三や,藤井聡太の棋譜ばかりあつめれば,彼らの手(流れ)を知っているAIができるのではないかというわけです!!

game_syougi.png

参考として

  • ゼロから作るDeep Learning ❷ ―自然言語処理編 斎藤 康毅 オライリージャパン
  • ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装 斎藤 康毅 オライリージャパン
  • 詳解 ディープラーニング ~TensorFlow・Kerasによる時系列データ処理~ 巣籠 悠輔 マイナビ出版

を使ってます

データセット作成法

将棋 棋譜 ダウンロード
で調べるとサイトが出てくるので,
藤井聡太,羽生善治,加藤一二三の棋譜のデータをダウンロード

とりあえず,KIF形式で出力して保存しまくる

集められたのは

  • 藤井聡太 18対戦
  • 羽生善治 150対戦
  • 加藤一二三 100対戦

で,集めた棋譜のデータを

開始

投了

で,一つの対戦の棋譜のデータを一つの配列にします

こんな感じ

['開始' '2六歩' '3四歩' '7六歩' '4四歩' '4八銀' '4二銀' '6八玉' '4三銀' '5八金右' '3二金' '2五歩'
 '8四歩' '2四歩' '同歩' '同飛' '2三歩打' '2八飛' '8五歩' '7七角' '5四歩' '4六歩' '3三桂' '4五歩'
 '同歩' '4四歩打' '5二銀' '8八銀' '3一角' '4七銀' '7四歩' '7八玉' '7三桂' '2六飛' '6四角' '3六飛'
 '4二玉' '3四飛' '4六歩' '5六銀' '3八歩打' '1六歩' '3九歩 成' '1七桂' '6二銀' '2五桂' '同桂' '3二飛成'
 '同玉' '4三歩成' '同玉' '1一角成' '3三歩打' '4五香打' '4四 桂打' '2一馬' '3四玉' '4四香' '3七桂成'
 '5四馬' '4七歩成' '4五馬' '2五玉' '2六歩打' '投了']

で,これらをダウンロードした棋譜データすべてにおこない,extendして,一つの配列にします


['開始' '2六歩' '3四歩' ... '同歩' '3三金打' '投了'] # all kifu data

そしたら,これを一つの文章と見立てて,corpusを作成します
corpusはID化された文章のことです
NNは,文字のままいれても計算することができませんので,それぞれIDに変換しておくことで学習を行えるようにします


[  0   1   2 ...  14 225  61] # corpus

でこのcorpusで1つずらして(時系列的に),テストデータと教師データを作成します

xs = corpus[:-1] # 入力データ
ts = corpus[1:] # 教師データ

これで準備完了です
なお,ID化されているものは
word_to_id と id_to_wordで表現され以下の感じで収納されています

# id_to_word
{0: '開始', 1: '2六歩', 2: '3四歩', 3: '7六歩', 4: '4四歩', 5: '4八銀', 
6: '4二銀', 7: '6八玉', 8: '4三銀', 9: '5八金右', 10: '3二金', 11: '2五歩',
 12: '8四歩', 13: '2四歩', 14: '同 歩', 15: '同飛', 16: '2三歩打', 
17: '2八飛', 18: '8五歩', 19: '7七角', 20: '5四歩', 21: '4六歩', 
22: '3三桂', 23: '4五歩', 24: '4四歩打'...

# word_to_id
... '5四馬': 56, '4七歩成': 57, '4五馬': 58, '2五玉': 59, '2六歩打': 60, 
'投了': 61, '7八金': 62, '8六歩': 63, '3三角': 64, '5八玉': 65, '6二玉': 66, 
'9六歩': 67, '9四歩': 68, '3六歩': 69, '8二歩打': 70, '7七桂': 71, '7六飛': 72, 
'3七桂': 73, '5五角': 74, '8七金': 75, '7五飛': 76, '3八銀': 77, ' 9五歩': 78, 
'4四角': 79, '9六歩打': 80, '2四飛': 81, '3五歩 打': 82, '3六歩打'...

ワンポイント

さて,ここからが大切です

今集めたデータの流れを学習させるとプロ棋士同士の戦いの流れを知っているものになります
しかし,流れだけを学習しても,もちろん勝てません

なので,データセットを
先攻用(先攻が勝ったデータセット)

後攻用(後攻が勝ったデータセット)

に分けてそれぞれのデータセットで,ネットワークを作成します

そして自分が先攻の時と後攻の時でネットワークを切り替えることで勝利を目指します

なので正確にいうとひふみんたちのスタイルを学習できるわけではないです
必ずひふみんたちが勝っているわけではないので
羽生さんはめっちゃ強いですけど

ネットワーク構成

これは言語モデルを模倣するので基本的には

image.png

になります
実際の忠実なネットワーク構成ではありません,あくまで基本形です

詳しくはNNs_shogi.pyをご覧ください

分類だとmany to manyで、下の図でいう

image.png

右上の左下です

学習法

これはこの前まとめた話ですが,今回は1つの大きな流れを学習すると仮定します
なので,シーケンシャルに与えます(シャフルしないバージョン)

image.png

学習結果

検証用データがないので過学習してるかなどは行ってませんが
とりあえず,収束していることはわかります

オレンジが先攻
下のepochの表示おかしくなっているので気にしないでください

Figure_1.png

戦ってみる

さぁ戦ってみましょう!
http://www14.big.or.jp/~ken1/application/shogi.html
にて勝負を申し込みます

将棋.JPG

僕が先攻とします
やっていくと...

最初の方は定石の提案なのでしょうか?
それとも過学習しているからかもしれませんが,,,

この辺まではほぼAIの予想通りの展開

  • 20手までの盤面

20手まで.JPG

  • 20手までのコマンドの画面

20手まで2.JPG

  • 30手までの盤面

30手まで.JPG

  • 30手までのコマンドの画面

30手まで2.JPG

  • 40手までの盤面

40手まで.JPG

  • 40手までのコマンドの画面

40手まで2.JPG

  • 50手までの盤面

50手まで.JPG

  • 50手までのコマンドの画面

50手まで2.JPG

だんだん盤面が複雑になってくると厳しいですね...
相手の動きが,選択肢のない手を書かないといけなくなってきますね...

ただ,持っているコマを打ってくださいの指示も出てきますしすごいですね

最終的に,自分の手が選択肢の中のもので打てなくなって,難しくなってきたので,くしくもここで諦めました...
残念
さて考察

考察

問題点

お気づきの通り,トレーニングデータの中にない,手があると,エラーでとまります
つまり,未知の手には対応ができないわけです
ここは強化学習にたいしては大きく劣るところです

さらに,もっと大きな問題点は,ありえない手が出てきてしまうことです
どうしても,ゲームの条件で縛っていないので,あり得ない手を出力してしまいます
一応流れを学習しているので,そこになんとなく対応していないかと期待していたのですが
ゲームの中盤になると厳しそうです

これも学習データに左右されるところはあると思います

やっぱり強化学習なのかなぁ
あり得ない手をどう学習するかがポイントになりそうですね

良い点

良い点は簡単にできることと,データセットの増やし方次第ではかなり強いものが作れるのではないかと考えています
上記の問題点はデータセットが増えれば増えるほど解消に向かう可能性があるからです
ただ、将棋は選択肢が多いので、難しいところではありますが、、、

ハイパーパラメータやネットワーク構成によっては性能の向上が期待されますので
やってみたい方はぜひ!

実際に使ってみたい方へ

githubリンク

投了までうまくいくのは難しいですか,
実際に使ってみたい方向けにどうやって使うかを説明します

githubにプログラムが上がっていますのでまずそちらをクローンなどしてください

ファイルの中から

play_game.py

を実行

説明文が以下のようにでます


先攻=1ですか?後攻=0ですか?,数字は半角で入力
1

なので,試しにまず先攻を選択するために
半角で1を入力してください(後攻選択でももちろんできます)

8四歩,のように打ってください,棋譜の数字は全角です
王はすべて玉で打ってください

一番初めは,開始と打ってください

でこのコマンドが出るので

開始

と打ってください
すると
このような出力がでますので

開始
 60.0 % で,7六歩 という手を提案します
 35.4 % で,2六歩 という手を提案します
 2.4 % で,開始 という手を提案します
 0.89 % で,3五歩 という手を提案します
 0.4 % で,5六歩 という手を提案します
あなたのターンです(上記から実際に打った手を入力してください)

なのでここで上のやつから自分の好きな手を打ってみてください
(もちろん打てるもので!)

ここでは

7六歩

と打ってみましょう

7六歩
[ 12   2  10 ... 804 349 761]
 82.3 % で,8四歩 という手を打ってくると思います
 17.5 % で,3四歩 という手を打ってくると思います
 0.0 % で,3二金 という手を打ってくると思います
 0.0 % で,5四歩 という手を打ってくると思います
 0.0 % で,4四歩 という手を打ってくると思います
相手のターンです(上記から実際に打たれた手を入力してください)
8四歩
[  1 112 401 ... 144 454  44]
 89.3 % で,2六歩 という手を提案します
 9.3 % で,6八銀 という手を提案します
 0.6 % で,7八飛 という手を提案します
 0.3 % で,1六歩 という手を提案します
 0.2 % で,7八銀 という手を提案します
あなたのターンです(上記から実際に打った手を入力してください)

後は敵が打った手と自分の打った手をコマンドプロンプト上に打っていけば,勝手にAIが良いなと思う手がでてきます

数字もすべて全角でうってください

プログラムについて

自身の棋譜データを使いたい方や学習の中身を知りたい方向けにプログラムの説明をしておきます

  • main_shogi
    これが学習のmainプログラムです
    ここの中のハイパーパラメータやpathを再設定することでオリジナルのものが作れるかと思います
    先攻用と後攻用で学習データを変えています
    なお,ハイパーパラメータについては一切調整していません

  • data_read_function
    棋譜データを読み込むための関数が入ってます
    今回の棋譜データは

1 7六歩(77) (00:00/00:00:00)
2 3四歩(33) (00:00/00:00:00)
3 2六歩(27) (00:00/00:00:00)

のような形で保存されていることを想定しています
windowsで保存したのでasciiになってます
Linux用のプログラムを後日上げます

  • layers_shogi
    NNのレイヤーが入ってます

  • functions_shogi
    NNに使う関数が入っています

  • NNs_shogi
    NNを作成しています
    ネットワーク構成についてはこちらをご覧ください

  • trainer_optimizer_shogi
    NNの最適化手法と学習法です

  • play_game
    上記で説明したゲームを遊ぶためのものです

11
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?