tomohxxの日記

麻雀プログラミング

麻雀AI開発DL編(1)

はじめに

以前の記事でディープラーニングを使った麻雀AIを開発すると書きました。今回はその途中結果についての記事です。

なぜディープラーニングを使うのか

なぜディープラーニングを使うのか念のため振り返っておくと、それは押し引きを明示的に作りこむのが難しいからです。つまり押し引き判断の部分をニューラルネットワークに行わせることを目的としています。

モデル

Suphxの論文を参考にしながら一部で独自の工夫を施しました。Suphxでは100層、フィルタ数256のResNetをすべての行動(打牌・リーチ・ポン・チー・カン)に共通して用いています。ここでSuphxモデルの特徴について簡単に解説します。

一般的にCNNを使って手牌をエンコードする場合、34 x 4 x 1の配列の高さ(幅)方向を使って各牌の枚数をエンコードすることが多いです。ところがSuphxは34 x 1 x 4の配列の奥行(チャネル)方向を使って手牌をエンコードしています(
図があるとわかりやすいです。気が向いたら用意します。)。これによりデータの密度を上げられるというメリットがあります。例えばカテゴリカルデータをエンコードする場合、1つのシートを0か1で埋める必要がありますが、前者では136個の要素を使うのに対し後者では34個の要素を使うだけで済みます。そのため学習中に使うメモリを節約することができます。ちなみにResNetはニューラルネットワークを多層化するテクニックとしてよく用いられるみたいです。

では、特徴量についても説明します。Suphxの論文では、どの特徴量を使っているのか、特徴量をどのようにエンコードするのか、を完全には明らかにしていないと思います。主な特徴量は以下です。

  1. 牌の集合型の特徴量:手牌、ドラ
  2. シーケンス型の特徴量:河
  3. 整数型の特徴量:持ち点、壁牌の枚数
  4. カテゴリカルデータ:局番号、親、連荘、リー棒

これらに加えて先読み特徴量といって自分が何点であがれそうかを表す特徴量があります。私も基本的にこれらの特徴量を使いました。

レーニン

天鳳鳳凰卓の牌譜を使って打牌選択モデルと立直判断モデルを作りました。前者の牌譜一致率は73.3%、後者の牌譜一致率は79.0%でした。ちなみにSuphxではそれぞれ76.7%、85.7%になっています。

実験

自作の麻雀AIをManueと対戦させました。例のように一局戦1000試合です。なお、鳴きの判断の部分は手違いがあってヒューリスティックにしました。今後、鳴き判断もニューラルネットワークして実験したいと思います。

項目 データ
試合数 1000
局数 1000
和了 0.28
放銃率 0.13
リーチ率 0.18
副露率 0.50
平均得点 5641
平均失点 6054
平均順位 2.28
1位率 37.4
2位率 20.4
3位率 19.0
4位率 23.2

平均順位が以前に開発したAIよりもかなり良いです(以前は2.35でした)。副露率が高すぎる気がしますがこれは私の調整によるものです(鳴かないよりは鳴いた方がいいかなぐらいのざっくりとした調整です)。以降で具体的な打ち筋について牌譜のスクリーンショットを交えて考察していきます。

牌譜検討

守備意識

f:id:tomohxx:20210503164354p:plain
牌譜1

打9sとした場面です。手があまりよくないので字牌安牌を抱えています。攻撃がない場面でも守備を意識しているようです。

f:id:tomohxx:20210503165141p:plain
牌譜2

打3pとした場面です。守備を意識して3pから逆切りしています。

押しすぎ

f:id:tomohxx:20210503165923p:plain
牌譜3

打7pとした場面です。平和赤ドラ2が見えますがここから押すのは厳しそうです。

降り

f:id:tomohxx:20210503171018p:plain
牌譜4

打8sとした場面です。あがる見込みのない場面では降ります。その際に発ではなく直前に上家が切った8sを選択しています。手牌の安全度を理解しているようです。

5ブロック理論

f:id:tomohxx:20210503172005p:plain
牌譜5

打7pとした場面です。現在のブロック数は6ですが強いブロックを残すというわけで打7pとしたようです。三色同順に関係する部分に手をつけないのもポイントです。

立直判断

f:id:tomohxx:20210503180524p:plain
牌譜6

打8s立直とした場面です。特に立直をかけない理由はないです。

f:id:tomohxx:20210503173202p:plain
牌譜7

打4mとした場面です。タンヤオドラ3で打点十分なので立直をかけませんでした。

待ち取り

f:id:tomohxx:20210503173613p:plain
牌譜8

打4sとした場面です。この局では最初から七対子に向かっています。テンパイしたときにあがりやすいように一九字牌を多く抱えています。ここではツモ5pなのですが、2p8pがすでに河にあるので他家から見て無筋4sよりも中筋5pの方があがりやすいと判断したようです。

まとめ

目的の押し引き判断についてある程度はできているようです。ただ立直に対して押しすぎな面があり、これが平均失点が6000点超えと高くなっている理由だと思われます。今回のように牌譜一致率を高めるというトレーニングではすべての局面を同じ重みで評価してしまうので、例えば対立直での牌譜一致率を重視するということができません。ちなみにこのうなトレーニングは強化学習の範疇なのではないかと思います。今後は放銃率を下げる方向で改善していきたいと思います。

おわりに

切り順や待ち取りは今回の目的ではなかったのですが、思いがけず学習してくれたみたいでディープラーニングのすごさを思い知りました。ディープラーニングの特徴として、人間が明示的に特徴を教えなくても勝手に特徴を見出す、とどこかで読んだ気がするのですがまさにその通りだなと思いました。いくつか課題はありますがとにかく麻雀の基本的な行動を学習できたのでよかったです。次回は鳴き判断にもニューラルネットワークを使ってAIを作ろうと思います。