自作麻雀AI「Occam」

戻る

1.概要 自作麻雀AI「Occam(オッカム)」を開発し実験を行った。 特徴は最終順位期待値ベースで判断を行うところである。 まうじゃんで対戦させた所「アカギ」というAIとほぼ同等の強さだった。 (追記) すいませんこのレポートのOccamはアカギより弱いです。詳細を追記しました(3−1−1)。 第一東風荘で332試合対戦させたところ安定レートは1421となった。
2.プログラムの内容 2−1 概要 既存の麻雀ゲームの作り方は公開されていないが、おそらく局単位の収支をベースに判断するように作られていると思う。 しかしこれでは「オーラストップでダマ和了可能ならダマ」などの戦略的な打ち方ができない。 そうする場合は手動でプログラム内にルールを記述しなければならず、その正確さはプログラマの雀力に依存する。 Occamはこのような判断を期待値計算の結果、自動で行うようにする事を狙ったAIである。
2−2 方針 麻雀の1局は、次のいずれかの結果で終了する。 ・自分のツモ和了 ・自分の上家からのロン和了 ・自分の対面からのロン和了 ・自分の下家からのロン和了 ・上家のツモ和了 ・上家の自分からのロン和了 ・上家の対面からのロン和了 ・上家の下家からのロン和了 ・対面のツモ和了 ・対面の上家からのロン和了 ・対面の自分からのロン和了 ・対面の下家からのロン和了 ・下家のツモ和了 ・下家の上家からのロン和了 ・下家の対面からのロン和了 ・下家の自分からのロン和了 ・流局(荒牌、四風連打、4人リーチ、四開槓、トリプルロン) Occamは、まずある合法手に対して局収支期待値を求め、その値を最終順位期待値に変換する関数で最終順位を計算する。次に合法手に対して確率を計算し、上記すべての場合の確率×平均順位の総和が最も高い手を選択する。 今回は簡単のため以下の重要と思われる場合のみ考慮する事にした。 ・自分のツモ和了 ・上家の自分からのロン和了 ・対面の自分からのロン和了 ・下家の自分からのロン和了 加えて以下の場合を考慮していない。 ・自分のチートイ和了、国士無双和了 ・カン判断(リーチ後のアンカン除く) さらに、以下の場合を決め打ちしている。 ・9種9牌は常に流す ・見逃しはしない ・時間短縮のため、相手のリーチ無し時かつ孤立牌がある場合は孤立牌を切る。 孤立牌を切る順序は オタ風>役牌>19>28>37>456>ドラ とした。
2−3 局収支期待値を最終順位期待値に変換する関数 2−3−1 MJSIM0 局収支期待値を最終順位期待値に変換する関数は、とつげき東北氏開発のMJSIM0という仕組みを使う。 これは決められた上がり率、放銃率にしたがって「擬似麻雀」を十分回数行い、期待最終順位を計算する仕組みである。 MJSIM0と同等の動きをするクラスを作り、算出した期待得点から期待最終順位を求める関数を作成した。 MJSIM0は自分、相手の各和了率、放銃率をパラメータとして用意する必要があるが、今回は簡単のため固定値とした。 2−3−2 最終順位を評価ポイントに変換 MJSIM0で求めた平均順位は、当然1〜4位の間の値である。 しかし、これをそのまま確率変数として使用すると4位が1位の4倍の価値しかない事になる。 麻雀には一般的にオカ(トップ賞)とウマ(順位点)というルールがあり、1位の価値が2位以下より断トツで高いという特徴がある。 そこで順位を評価値に変換する関数を作成する。 一般的な25000点持ち、ワンスリーと呼ばれるルールでは 1位:オカ +30 ウマ+20   = +50 2位:オカ +10     = +10 3位:オカ -10     = -10 4位:オカ -30     = -30 という順位点がつく。ここで計算に0やマイナスが入るとややこしくなるので全体に40を足す。すると 1位:+90 2位:+50 3位:+30 4位:+10 このような値になる。 プロットし、最小二乗法で近似曲線を求めた。 期待順位をこの近似式に当てはめて、それを評価値とした。 これで局収支期待値を最終順位期待値に変換する仕組みができた。 ここからは既存の麻雀AIと同様に局収支期待値を求める事になる。
2−4 局収支期待値の計算 参考 mjai-manue 2−4−1 あがり確率の計算 モンテカルロシミュレーションにて求める。 まず今の手牌から、残りツモ数分ツモった状態の多牌状態を作る。 ツモには次のルールを設けた。 ・フリテンの価値を低くするため河にある牌を再びツモらない ・今切った牌を再びツモらない そして和了っているか判定し、和了回数/シミュレート回数で和了率を求める。 シミュレート回数は計算時間の都合もあり300回とした。 この方法で試したところ問題となるケースがあった。 ・残り枚数が多すぎる場合 例えば残り17ツモでテンパイしている場合、この方法だと和了率がほぼ100%になる事があった。 ・アタマが無い場合 例えば 「手牌 1m2m 5m6m 3フーロ」という場合などに和了率が極端に高くなる。 これは、ツモる確率を計算し、一人麻雀練習機のように順目ごとの和了確率の総和を厳密に求めていないために起こる問題である。 今回はわからなかったので 簡単のためシャンテン数ごとにツモ枚数を可変としてお茶を濁した。 例えばテンパイ時のツモ枚数は2枚に固定される。 リーチ判断とフーロ判断も同様にして行う。 リーチ判断時は求めた和了率からマイナス5%とした。 フーロ判断時は「鳴かないor何を鳴いて何を切るか」という全ケースについて、残りツモ数をマイナス1した。 先に言うとOccamは正直弱いのだが、この和了率の計算が正確でない事が大きな原因の可能性が高い。 2−4−2 あがり得点の計算 まず手牌の有効牌を求め今の手牌に足し、多牌状態を作る。 そこからランダムに和了形を抜き出しその平均点を取る。 役なしチョンボを防ぐため求める得点はロン和了時の得点とした。 得点を求める際にあがり牌を指定しなければならないが、手牌に無い牌からランダムに選択するようにした。 また、フーロ判断時の無駄鳴き(アンコがあるのにポンする等)防止のため ・既にメンツがあればなかない ・和了形を抜き出して1回でも0点があれば得点を0に固定する というルールを設けた。 2−4−3 放銃率の計算 相手三家について、次式で求める。 放銃率 = テンパイ率 × その牌の放銃率 テンパイ率については、リーチ、4フーロならば当然100%である。 相手がフーロしている時のテンパイ率は「超入門 科学する麻雀」に掲載されている牌譜統計から求められた「順目、フーロ数別テンパイ率」をそのまま採用している。 ダマテンは0%とする。 牌の放銃率については、スジや現物といった情報から 「科学する麻雀」に掲載されている牌譜統計から求められた放銃率をそのまま採用している。 モンテカルロ法(とつげき東北氏開発MJ-1)で求める手順も試したが、いまいち精度が上がらず今回は牌譜統計を採用した。 しかし今後はモンテカルロ法で求めるようにしたい。 2−4−4 放銃点の計算 相手の手牌について、今の状態からランダムに和了系を作りその平均点をとる。 としたかったが、計算時間の関係からmjai-manue氏の統計データ(6265点)の固定値とした。
3 実験 3−1 まうじゃんで対戦 OccamをまうじゃんDLLとして開発し、アカギというAIと対戦させた。 こちらのブログによるとアカギは公開されているDLLの中で断トツで強い事がわかる。 アカギはフーロ率が低い(おそらく実装されていない)のだが和了素点が高く、トップ獲得型の麻雀を打つAIである。 時間短縮のため東南戦でなく東風戦で1600試合対戦させた。 3−1−1 結果
・Occam 平均順位 2.490786位

・アカギ 平均順位 2.506757位 ・順位差 0.015971位 0.1位をR120として計算すると(参考:システマティック麻雀の公式集より)、Occamはレートにして約19程アカギより強い事になる。 -------------------------------------------------------------------------------------------------------- [追記] すいません、検定したところ統計的有意差がついていませんでした。 1600試合では全然試合数が足りてないみたいです。 というかこのOccamは明らかにアカギより弱いです。なぜなら、今改良版Occam(v0.2)を作っているのですが、このOccam(v0.1)より明らかに強いにもかかわらずアカギに勝てていないからです。 -------------------------------------------------------------------------------------------------------- Occamの和了素点が低いため、和了率が優っているにもかかわらず成績にほぼ差がついていない。これは順位を意識した手作りが出来ていない、棒テン気味に打っているという事だと思われる。 ちなみに、なるうらと氏作のしぐま0というAIは、公開されているデータ(アカギとしぐま0の直接対決の結果、リンク先ページ最下段付近)を見る限り しぐま0平均順位:2.464位 アカギ平均順位 :2.532位 順位差 = 0.068位 となり、アカギよりレート82程強いと言える(観戦している印象としてはもっと高い気がする)。 しぐま0はダマあがりを全くと言って良いほどせず、かつ局収支期待値ベースのAIであると思われるが にも関わらずこのような差が付くというのは驚きである。おそらく牌効率技術、鳴き技術が高いレベルで行われているという事だと思う。 ちなみに全体的に作ってからアカギに勝つまで調整するのに1ヶ月かかった。だからなんだ。
3−2 第一東風荘で対戦 3−2−1 結果

所感 ・放銃率が高い。完全にベタ降りすべき場面でも、あがりの可能性を残した打牌をしていた。 ・リーチしすぎ。 ・鳴きが下手。 ・和了素点が低い。素点の計算が悪いのか、そもそもMJSIM0を使う方針が違うのか。 ・ツモ上がり割合が低い。牌効率が悪く、またOccamに「待ち」という概念がないためである。そのため4単騎リーチなども平気でしていた。 ・要するに弱い。 参考:とつげき東北氏成績 3−2−2 悪手検討 ※牌譜はページ最下部にあります。 ※この項目は気になる場面を見つけ次第更新予定です ・全体的に上がりに向かっているが、私のレベル(天鳳四段R1800)から見てもおかしい打牌が多い。 ・フーロ判断も悪い。タコ鳴きをしたり、役牌鳴くべきところでをスルーしたり。 ・リーチ判断も悪い。ダマであがるべきところでダマ前提の手作りをしていない。 ・ドラを大事にしていない。 ・リャンメン形を大事にしていない。 基本的に和了率計算の不正確さから出るミスが多い。 1.
ここから7pを切っているが、評価値を見ると下家の仕掛けにオリているようである。 2.
これも5mよりも4mが仕掛けに安全だからと言って、ピンフを消してまでリーチしている。 評価値が メンピンをあがるメリット>フーロに放銃するデメリット になっていない。 3.
無駄喰い替え(要修正) 4.
単騎リーチ。ロン和了率を考慮にいれていないため? 5.
対子の固定が早すぎるし、リャンメンを消すのは良くない=ロン上がりの考慮がされていない 6.
押すなら1p切りだが7pを切った。平和を認識できていないバグか? 7.
安牌が無いが、正解は8p落としあたりだろうか。5sは明らかにない。 8.
3pを残す理由がない。メンツが足りている場合にこの様な、見切りの早すぎる打牌をする事がある。 9.
鳴き判断が甘い例。クイタンのみをあがる局面でなはないし、後の形が悪すぎる。 10.
ノベタンでなく中ぶくれ単騎待ち。ロン上がり率(待ち)を考慮していないため。 11.
オリてるようだが点数状況的にまだオリルのは早い。ていうかドラのダブ東切っちゃだめ。 12.
両面を消す例 13.
メンツが足りているので5sか3mのトイツほぐしをするべき 14.
9mから切るべき 15.
一盃口消してまで悪形待ちをする理由がない 16.
中スルーしているが、染めを狙うべきでは? おまけ:実験風景

4 考察 残念ながらOccamは人間の平均以下の成績しか出せず、あまり強いAIにはならなかった。 もう少しレートが高いと思っていたが、麻雀においても、人間にとっては当たり前の事を自動でやる事は難しい事だと実感した。 牌譜を見る限り本来やりたかった戦略的な判断が出来ていない場面も多々あり、目的を達成できなかった。今後の課題である。 他に、麻雀は1つのミスで1位から4位に転落するおそれのあるゲームであるため、複雑な場面以外では100%と言っても良い精度で正着を打たなければ人間には勝てないと感じた。 しかし牌譜統計やモンテカルロシミュレーションを用いて期待値を求める方法は、麻雀においても効果的だという事を少しは示せたかもしれない。特にモンテカルロシミュレーションは汎用的かつ簡単かつ精度が高かった。 幸いな事に改善点は山ほどある。思いつくままにTODOを挙げるなら ・高速化(重要) ・各モデルの高精度化(重要、特に和了率の計算) ・未考慮部分の考慮(チートイ、国士無双) ・自動で対戦させるシミュレータ開発(まうじゃんでは遅いため) ・流局収入期待値の考慮 ・ロン和了の考慮(重要) ・リーチ時の上がり率低下分の正確な値。現在5%低下としているが、正直言って適当である。 ・他根拠鳴く固定値にしているパラメータの改善 ・フリテンチョンボ(論外) ・そもそも方針自体が間違っている可能性の検証 ・そもそもOccam以外のプログラムにバグがある可能性の検証 ・しぐま0に勝つ まだまだあるかもしれないが、また時間を見つけて挑戦していきたい。 もしあなたが、実際にオンラインで対戦させ高レートを叩きだしたAIを作ったならば教えてほしい。弟子にしてください。
付録 牌譜(1MB以下のファイルしかアップロードできないため193試合分)
戻る
inserted by FC2 system