FC2ブログ

*All archives* |  *Admin*

<<07  2018/08  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 31  09>>
麻雀AI開発その90・他家から切られる牌分布とニューラルネットその3(失敗編)
昨日から丸一日経過して、出来上がった重みパラメータから牌譜を基に計算してみた感じがこちら↓。


180817-01.png
配牌時点。
0枚持ち西より1枚持ち北の方が出やすいという謎判定。


180817-02.png
同じ局で5巡目。
やや内側数牌の出る率高くなってる。
相変わらず枚数ほぼ無視の横一線に近い。
3枚見えの東とかどう考えても4.5%も出ないでしょうに。

180817-03.png
別の局でリーチ者がいるケース。
リーチ者の現物がどうこうみたいなのも全然入ってるように見えないです。

完全に失敗作ですね。
ただ単純にニューラルネットとかソフトマックスとかクロスエントロピーとか、かっこいいワードを使いたかっただけの坊やだったのさ…。


敗因の分析をします。
入力変数が盤面の情報をそのままをどかーんと放り込んだだけで、人智を超えたニューラルネットで最適化を勝手にやってもらうことをもくろんだのが、ダメだったのかな、と思ってます。
そういうのよりはある程度従来の知見から、関係ありそうな特徴量を人間の手(わたし)で手動でセッティングしてやる方がよりまともな結果になるのではないかなーと現状では思っています。
関係ありそうな特徴量といえば、当該牌の枚数状況とか、現物かどうかとか、周りの牌の枚数(カベ効果)、他家の攻撃状況などです。
そういうのを直接入力値にした方がうまくいくんじゃないかなーと。

それと多値分類問題でソフトマックスとかクロスエントロピーとか、自分の理解度が低い理論を使ってるのも間違いが発生するもとになってるかもしれません。
すでに自分の中で結果としてうまくいってる部類に入る0-1分類問題に変えた方がいいかもしれないです。
出力層を1個にして切られる率の確率に近いものを出すようにして、合計値を1にするような調整は従来通り手作業でやった方がいいかもです。


というわけで、今後の方針では「より簡単なモデルで切られる率(もどき)を出すニューラルネットを作る」ことです。

ひとまずは重要度が高い特徴量として、
・巡目
・該当牌の牌種類
・該当牌の持ち枚数
・該当牌の見え枚数
・該当牌の種類
・4人の攻撃形態(リーチ・非リーチ門前・役牌仕掛け・タンヤオ仕掛け・その他仕掛け)
・4人の副露数
・切り者以外3人の該当牌の現物筋状況
これだけを入れてやってみます。

もちろん最終的には
・副露者が高いか安いか読み
・ドラ情報
・カベ効果
・序盤外側や5切り
・直近で通った牌かどうか
・残り筋本数
とかも入れたいわけですが、簡単なモデルでまともに動くものが作れなければどうしようもないので。
スポンサーサイト
麻雀AI開発その89・他家から切られる牌分布とニューラルネットその2
2日ほど経過して出てきた重みパラメータ(100回ミニバッジ×100000回のパラメータ更新)を基にcsvファイルから予測切られ率を出してみたところ、
端牌・字牌の切られ率がやや高く、赤牌はかなり切られにくい、程度の結果にしかなっておらず、
枚数とか、他家攻撃への対応みたいなことがほとんどできてない状況でした。

損失関数の推移から覚悟はしていたけど、丸2日たってこれだから学習がほとんど進んでないことがわかりました。
そもそも高々1千万回ニューラルネットをぶん回すだけで、2日も計算時間がかかる時点でちょっときつすぎます。

そこで、昨日から今日にかけて、なんとか計算時間が縮まらないものか、と試行錯誤してました。

一番簡単なのは活性化関数をLeaky Reluから普通のReluに変えたこと。
中間層がマイナスになったノードは微分が0で計算しなくて済むのでおそらく計算時間が半分になるはず。

後は、ループ内で同じ変数を参照する場合の作業量を減らそうと、ループ外に出したりとか1次元配列をジャグ配列に変えて配列の参照を工夫するとか、なるべく演算の数を減らすとか涙ぐましいというかせせこましい努力をしてました。
それによって微分の数値が合わないとかも出てきてコード書くのがストップするハプニングもあったりとか。

ただ計算時間を細かく計測したりもしてみましたが、どうあがいてもDouble型変数の加算代入がたくさん(1回ニューラルネットあたり出力層37個×中間層50個×入力層150~200回)の部分で時間がとられる構図は変わらなかったです。
重みパラメータを使ってる以上、浮動小数点のDouble型で加算をするのは最低必要(だと思ってる)なので、現状どうしようもないと。

今日のバージョンの機械学習だと、100回ミニバッジ×100回重みパラメータ更新の繰り返しにかかる時間は1分20秒ほど。
せいぜい前回の倍くらいまでしか、速度が上がってないです。

果たして今の方式でまともに切られる牌分布を機械学習で求められる日はくるのだろうか、と旧PCの黒いコンソール画面の文字を見つめつつ、もの思ひに耽る今日この頃。
麻雀AI開発その88・他家から切られる牌分布とニューラルネット
前回の最後に、他家から切られる牌分布の算出法が気に食わない、という話をしました。

それで、ここ何日か、ニューラルネットにできないかと思って、作業をしてました。

とりあえず、いつも通り、入力情報と結果(実際に切られた牌番号)を牌譜解析からcsv化するのはできました。
入力情報として取ってきたのは、
・巡目
・親位置
・(切り者から見た)自分位置
・場風
・ドラ
・自分手牌枚数
・自分見えてる枚数
・(4人について)リーチしているか
・(4人について)副露数
・(4人について)現物筋の状況
・(4人について)晒し牌

かなり多くの情報を取り込むことになりました。
1回の切り順に対して他家3人についてそれぞれ1軒のデータとして取り扱うので、件数もかなり多いです。
最初の100試合で、81783件、最初の1万試合で2.5GBのでかいファイルになりました。

それで、次に、csv化したデータを教師データとして、ニューラルネットを組みました。

入力層がなんやかんやでノード数1394になりました。前の染め手打点の時よりあからさまにノード数が多いです。死んでる重みパラメータ(例えば、「黒5牌が4枚見えてる場合」みたいに観測上あり得ない事象)も割と多いのを間引いたりはしてないですが。
出力層は牌の種類で、37個なのは確定です。
中間層のノード数はできれば多く取りたかったですが、学習時間でも1件あたりのニューラルネットの算出時間的にも苦しくなってきたので、泣く泣く50個に絞りました。
重みパラメータの次元数はおおよそこの3つの掛け算で約2,578,900次元です。

中間層の活性化関数はleaky_Relu、出力層の活性化関数はソフトマックス関数で、損失関数は交差エントロピーというのがいいらしいので、それにします。


それで、学習用プログラムを組んで微分が合ってるかどうかを確認して、
いつもの天鳳タイムの前に動作の早い旧PCで学習をスタートさせました。

天鳳から戻ってきてブログ書いてる途中で100回ミニバッジ×10000回のパラメータ更新が終わってました。およそ3時間。
履歴を見る限り学習が進むにつれて損失関数は減ってはきてるけど、減り方が相当にぶいです。
初期値のランダム重みパラメータ時と比較して、2~3%くらいしか損失関数が減ってないです。
これ、ちゃんとできてるのか…、と相当不安に思ってるのが今現在。

とりあえず今回の重みパラメータは成果として残しておいて、旧PCにはさらに10倍学習を続けてもらうことにして、
新PC側で、csvファイルとの突き合わせで、検証をやってみましょうか。
さて、どうなることやら。
麻雀AI開発その87・シミュレーションの改造(枚数を赤ナシベースに)その2
前回(麻雀AI開発その86・シミュレーションの改造(枚数を赤ナシベースに))の続き。

なんとか、放銃率関連のパラメータを赤ナシベースに変えるので、リーチ・副露・ダマのパラメータを無事に取り終わり、無事AI本体に反映させることに成功しました。

結果はこんな感じ↓。

180811-01.png
ちゃんと打黒5sと打赤5sの放銃率が同じくらいになってます。

割と大掛かりに改造したので、しばらくはバグチェックを兼ねていつもの何切る問題に実戦投入してテストしてみることにします。


次は染め手をやろうかと思ったけど、今回の改造も踏まえて他家から切られる牌分布の算出をちょっといじろうかと思ったりしてます。
というのは、今の分布の算出は元になる切られ率に関連する項目ごと(ドラかどうかとか、切り者や他家の状態とか)に係数を掛ける方式でやっているので、
まずその方法が正しいのかどうか大分あやしいのが1点と、
その数値をそのまま使うと、アガリ牌(自分聴牌もしくは他家聴牌に対して)が実際の牌譜よりも出やすい傾向にあって(人間の方が同カテゴリの牌についても読みによってより通りやすい牌を優先して切れる。特に切り者ノーテンの場合)、ある程度恣意的にアガリ牌の切られ率を下げる(自分聴牌に対して)とか、牌の放銃率そのものを下げている(他家聴牌に対して)処理を入れてるのが気に食わないのが1点。

それに代わる手段として、ニューラルネットとか機械学習側の手法を使おうか検討中です。
ニューラルネットで全入力値を押し込ませればどの項目を考慮させるかとか、読みの要素がどうとか、場合分けとかを人力(わたし)の手作業でやらなくても勝手にやってくれるのではないかなーと期待しています。

機械学習をするにあたって問題となるのは、
・うまくいくかどうかわからない。(極端な出力値になると、ある牌の切られる率が限りなく0や1に近づくみたいなことがありうる。手作業よりは恣意的な操作みたいな融通が利かない。)
・難易度はわりと高い。
・作業量がけっこうある。
・計算時間が増えそう。

一番ネックなのは計算時間ですね。
従前ではパラメータどうしの比較的少ない回数の乗算だったのが、複雑なニューラルネットの計算になるのが、他家切り順の毎ターン発生するので明らかに計算時間に負担になりそう。

麻雀AIとしてfloodgateに流すことを考えると計算時間次第では破綻します。
AIとしての運用をあきらめて単純に数値を出すだけのシミュレータとしての運用だけなら多少時間が増えるのは許容はできるが、さすがに何倍とかまで増えるのは許容できそうにないです。

どうなるかはわからないけど、とりあえずやり始めてみようか。

山にいる枚数別、先制リーチVS追いかけリーチの勝敗
AIの改修作業をするやる気がなかなか出ないため、単発の牌譜解析でお茶を濁す今日この頃。

今日のテーマは「2軒リーチ時、山にいる当たり牌の枚数が分かってる時の両者の勝率」です。

リアル麻雀の解説なんかで、「25pは山に3枚、カン3sは山に2枚、3対2ですね。」なんて話はよく聞くような感じがします。
実際に山にいる枚数が少ない方が勝つ確率がどの程度あるのか、というのが気になったので調べてみました。

牌譜解析の条件は次の通り
・2軒目のリーチがかかった瞬間を起点とする。
・他二人はリーチではないがそれ以外の状態(非リーチ門前・副露)は不問とする。
・追いかけリーチの宣言牌で放銃になったケースは除く。
・起点における巡目と、先制リーチ者と追いかけリーチ者の山にある当たり牌の枚数で分類して、その局結果(和了者と放銃者)を調べる。
・筋待ちや字牌待ちは特に分類しない。

↓結果がこちら(データ量が多いのでサムネイル表示)
180730-01.png
180730-02.png

データの内容的にはこれで十分ですが、これだとよくわからんので、9巡目に限定して、先制と追いかけの和了率を表にまとめたのがこちら↓。(ただし、データ数100件未満のところはエラー値扱いにして除外した。)

180730-03.png
180730-04.png

例えば追いかけリーチ巡目が9巡目で、先制が山3、追いかけが山4のケースだと、先制リーチ者の和了率は37.6%、追いかけリーチ者の和了率は52.7%です。
流局分とリーチ者以外の他家和了分を除けば、なんとなく、勝率は7分の3と7分の4に近いように見えなくはない…かも。

山4同士対決だと、先制が43.0%で、追いかけが48.5%。なぜか追いかけの方がアガリ率が高い。
理由はよくわからないです。
追いかけリーチの宣言牌が通った前提でスタートするので、順番的に、先制者ツモ和了番→先制者から追いかけへの放銃番→追いかけ者のツモ和了番→追いかけから先制への放銃番なので、明らかに追いかけ側が有利に働くような要素が見当たらないのだが…。

山4VS山3だと、先制が50.5%、追いかけが40.0%。山3VS山4と比較しても追いかけ側がやはり有利なよう。理由は不明ですが。

右の方で和了率(高さ)、先制者当たり牌枚数(手前軸)、追いかけ者当たり牌枚数(奥行軸)で等高線グラフを描いてみました。
結論、3次元なんでよくわからん。


先制和了率÷追いかけ和了率の比率を取ってみたのが、こちら↓。
180730-05.png
はたしてこれが意味がある数値なのかどうかはよくわからないが。


実際は字牌や筋待ちなどで、両脇からの出上がりできる程度や、3軒目が押してくるかどうか、もかかわってくるとは思いますが、
いちおう今回の数値を押さえておけば、エンタメ的に、「先制山3が追いかけ山4に勝った→37.6%側の事象が起きた→半々よりは少ないけどまぁあり得なくはないか」みたいな楽しみ方ができるかもしれないですね。
プロフィール

nisi5028

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

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

この人とブロともになる

QRコード
QRコード