*All archives* |  *Admin*

<<08  2017/09  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30  10>>
麻雀AI開発その32・数学的なお話(実データから押し引き基準を決める関数を策定)
前回、各打牌候補ごとの再帰局収支と危険度指数をAIに計算させて、(時間の面を度外視すれば)CSVファイルに出力する環境が整いました。

では、具体的にAIで求めた諸数値をどのように押し引き判断に使っていくか(どのような計算方法を取るか)、というところを考えてみたいと思います。
以下は、数学的な小難しい話になるので、そういうのが難しい方は読み飛ばしていただいて構いません。

まずはAIで計算される標本データ、および実際に計算で使う要素を変数として定義しておきます。
x_jをある打牌候補(j番目の牌)を切った時の再帰局収支、y_jをある打牌候補(j番目の牌)を切った時の危険度指数、iが実際に打たれた打牌候補番号とします。
x,y,iの関係は次のようになります。
170710-05.png
標本データについてはxとyの組14組(以下これをwと定義する。)に対して番号iが対応しています。
また、実際にAIを使用するときには入力値としてwを計算し、それに対して何らかの関数を用いて、出力値iを計算する必要があります。

1打につき、この対応が1組(w,i)が1つあり、それが全体の標本データとして多数個(n個)あります。(例えばn=1万とか100万とか)
170710-06.png

ここで「打牌選好力」という概念を導入します。
打牌候補番号j(j=1~14)に対して、打牌選好力z_j(0以上の値)をある関数で定義(計算)し、
入力値wに対して(z_1~z_14までが計算される)、実際に切られる打牌候補番号がiになる確率P(i)を以下のように定義します。
170710-12.png
このとき、P(i)は全て0以上の値で、P(1)~P(14)までの和は1になるので、Pは確率分布の定義になっています。
(勘の鋭い方ならわかると思いますが、このアイデアは「科学する麻雀」の「トップ獲得力」の概念をそのまま利用しています。)

続いて、「打牌選好力z_jをある関数で定義(計算)」についてです。この関数(入力値がx、yの組で出力値がz)をf(x,y)とします。
一番簡単な定義ならx、yについて線形となる次のような定義です。
170710-11.png
a,b,cはx,yに依存しない一定の係数(ただし、他家最大攻撃者と自分シャンテン数によって数値を変える)です。

ただ、この定義だと打牌選好力がどのような範囲のxとyに対しても線形の関係になっているということになりますが、
これだとyが0(完全安牌)ならxがたとえマイナスが大きくても、その中間(xがそこそこで、yはそこそこのプラスの値)になるような打牌候補よりもベタ降りとしてその完全安牌が切られる可能性は(中間の打牌候補に比べて)極めて高くなる、
また、その逆にxが極めて大きい(攻めるとすると価値の高い打牌)なら多少危険度が高い(yが大きな値)でも中間的な打牌候補よりも全ツでその牌が切られる確率は格段に上がる、ということが予想されます。
つまり、xかyどちらかに大きく偏ってる打牌候補(もちろんxもyも両方ともいいことに越したことはないですが)の方が選ばれる確率P(i)とか打牌選好力z_iとかが大きく跳ね上がると予想されますが、線形の仮定ではその部分をうまく反映できない可能性があります。

また、線形にすると、打牌選好力は必ず0以上の値である、ということが担保されないことも問題です。

打牌選好力を計算する関数fの定義を2次曲線とするならば次のような定義になります。
170710-07.png
以下ではfが線形であるという前提で話を進めようと思います。(2次曲線でも問題の本質はそんなに変わらない。)

入力値wから打牌選好力z、ひいては確率分布Pを求めるにはn個ある標本データから係数a,b,cを定める必要があります。
ここでは最尤推定法という方法を使おうと思います。(というか、それ以外の方法が思いつかない。)
これは以下で定義される尤度(各標本データが発生する確率の積)が最大になるような係数a,b,cの組み合わせを答えとするものです。
(簡単な例なら、多数のくじの中から10本引いたら3本当たりだったならば、実際のくじの当たり率が10分の1とか10分の5のときよりも10分の3と考えるほうが妥当である、的なやつです。不正確だったらごめんなさい。)
170710-08.png

ただ、このまま確率の積を計算するとnがかなり多いとPが極めて小さくて計算しづらいのと、積だと扱いづらいというので、
最尤推定の鉄板ネタで、logを取ったものが最大となるという問題に置き換えます。
170710-09.png
それでこんな感じに変形される、と。logなので、積が和になってばらせる、と。

この値が最大となるa,b,cを(代数的に)求めるには、a,b,cの3変数関数と考えた時にa,b,cそれぞれで偏微分してそれが0になるという式の連立方程式を解けばいいということになります。
170710-10.png
logは消えて分数になったけれど、これを代数的に解くのはかなり無理そうです。

2次曲線で係数が6個になるということも考えると、ここはやはりExcelのソルバー先生の出番になるでしょうか。
これでうまいこといければいいですが。
(なんか、計算量が多くてソルバーの手に負えないという可能性もなきにしもあらずだが。)


ここまでで、数学的な話は終わり。

昨日、一晩AIに計算させてみたところ、途中でエラーを吐いて計算が止まってしまいました。(多数試合、計算させてエラーチェックをするためにこの計算をやってる意味もある。)
今日の朝にバグを直したのと、計算の節約(ベタ降り局収支はカット。また、向聴が今より上がる打牌かつ、ベタ降り打牌より総放銃率が3%以上高くて、かつ実際に切られた牌でない、の3条件が当てはまるときは再帰計算を行わない。)を施して、再度100試合計算させたら、約5時間で終わりました。
昨日の1試合5分とかよりは多少マシにはなったけれど、それでもまだ長いなぁ。

100試合のサンプルサイズは14000弱。そこから他家攻撃に関する分類が7種類と、自分シャンテン数が0(及び役なし上がり形の-1)と1と2の3種類(3シャンテン以上は再帰計算ができないor時間がかかりすぎるので、対象外とする。)。
21種類の分類があるから平均で各5~600程度のサンプル数か。
10000試合ならサンプル数が5~6万に増えて、計算にかかる時間が5時間×100倍で500時間、20日プラスα。これならギリ耐えられそう。
うん、とりあえず1万試合目標でやってみましょうか。

1万試合分計算できたら、出てきたcsvファイルを各分類(他家最大攻撃とシャンテン数)でそれぞれに振り分けして、
Excelソルバーでうまいこと計算すると。
そして、1万試合計算の20日の間に検討ソフトの外形を作る、というこんな方針でしょうかね。
スポンサーサイト

コメントの投稿

Secret
(非公開コメント受付中)

コメント

プロフィール

nisi5028

Author:nisi5028
FC2ブログへようこそ!

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
FC2カウンター
フリーエリア
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード