FC2ブログ

*All archives* |  *Admin*

<<05  2020/06  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  07>>
はじめてのpython&Tensorflowその11・切り番時の他家反応追加
今回の課題は、切り番に対する他家の反応部分をニューラルネットを組むのをしました。

最初はツモ番も切り番への対応も訓練データも別にして、完全に独立したニューラルネットにすればいけるだろうと踏んでましたが、今後強化学習をkeras-rlでするにあたってはmodel.fitさせるのに単一のニューラルネットのほうが都合がよさそうな感じに見受けられました。(この見立てがあってるかどうかは不明。)

なんで、訓練データは両方ごちゃまぜにして、ジェネレータで入力データの整形をするところで、ツモ番か切り番かで場合分けして、参照する重みパラメータを変える感じで作ってみました。パラメータの数が単純計算で2倍くらい増えました。

なんやかんやあって、Tensorboradが壊れて使えない(アクセスが拒否された、とかいう不穏なメッセージが流れた)ので、グラフ図と損失関数正解率グラフは今回はなしで。
入力が125チャンネル(0番~55番までがツモ番に充当、56番~124番を切り番に充当)で、出力値は切られた牌番号(前までと同じ、スルー時と大明槓時は牌番号0とする。)と行動種類番号(通常打牌、リーチ、暗槓or加カン、スルー、ポン、大明槓、下チー、中チー、上チーで0番~8番までを割り当て)の2種類にしました。

実際の手牌との突合せがこんな感じ↓。(自分手牌文字列で「出〇」などと書いてる行は切り番、ない行がツモ番です。)
181104-01.png
実際切られた牌番号と予測牌番号(1位と2位)、実際行動と予測行動1位を見比べて、ぱっと見まずまずの当て具合のように見えなくはない。

ただ、ツモ番と切り番がごちゃまぜになっていてわかりにくいので、なんかいろいろエクセルのcountifとかで分析したのがこちら↓です。
181104-02.png
上のほうが牌番号についての分析です。
ツモ番についてはだいたい前と同じ感じ。
切り番で、実際予測ともに鳴きだった場合(どちらかがスルーだと牌番号0とかになって比較がやりにくいので、除外。)は1位的中が4割弱、2位まででも正解率66%とけっこう数値が落ちます。

下のほうが行動番号に関する分析です。
左が実際の行動、上がニューラルネットで予測した行動、クロスしたマス目がcountifでカウントされた回数です。
対角線上の実際行動と予測行動が合致しているマス目の数字が大きいほどうまく予測できてることになります。

とりあえずツモ番については置いておくとして、切り番(スルー~上チーまで)を見ることにします。
基本的に切り番のデータの多くはスルーに偏っています。
そのためか、ニューラルネットの予測側もスルーに関してはまずまず予測が成功してる感じは見受けられます。
実際行動がスルーだったときに正しくスルーと予測しているデータの割合は97%とだいぶいい感じです。

一方、実際行動が鳴きだった場合については正しく鳴きと予測している割合が2割~6割とあまり芳しくないです。
つまり、鳴きかスルーかが微妙なケースについてはかなりの割合でデータの多くを占めるスルー側に引っ張られてるのかなーという印象です。

損失関数については牌番号も行動番号もクロスエントロピーの単純加算にしてるだけなので、その辺は工夫の余地があるのかもしれないです。
とりあえずは今回の教師ありニューラルネットは強化学習のための踏み台として使いたいだけなので(まぁこれ自体にも価値はあるとは思いますが)、まぁ今のところはてきとうでいいや。必要があれば再学習もすればいいし。

実際行動が鳴きだったケースでフィルターをかけたもの↓。
181104-03.png
こう見ると実際鳴きだったケースをけっこうスルーと答えていて取りこぼしが目立つような気がします。

次の課題はkeras-rlを使った強化学習の練習か、VB.netで作った強化学習に必要な関数のPythonへの移植のどっちかですね。
どちらからやってもいいのですが、まぁ、途中で強化学習むりーってなってとん挫した場合を考えるのがいやなんで、先にkeras-rlの練習からやりましょうか。

とりあえずkeras-rlとgymというのをpipで入れるところまではできました。pipのアップグレードができなくてかなり躓きましたが、pipアンインストール(なんか関連するライブラリも一緒に消滅)からの再インストール→なんかぐちゃぐちゃになっちゃったので、Anaconda自体もアンインストールからの再インストールという荒療治でなんとか解決しました。Tensorboradさんがお亡くなりになったのはこのへんが原因と思われる。

で、keras-rlとかDDPGに関して情報収集をやってる最中です。
独自仕様でgym環境を作るサンプルコードが書いてるページ(ただし、Q学習)と、DDPGのサンプルコードが書いてるページ(ただし、gym環境は既存のもの)を見つけたので、その辺をうまく組み合わせてkeras-rlの練習をやってみようかと思います。
まずは簡単な設定で独自のgym環境作ってDDPGが成功しないことには、麻雀なんていう高尚なゲームはとてもじゃないけど作れませんので。
はじめてのpython&Tensorflowその10・自分ツモ番の選択ほぼ完成
前回(はじめてのpython&Tensorflowその9・他家リーチ)から、
他家副露者なしの条件を外して、自分ツモ番での選択についてすべて判断可能にしました。

入力チャンネルの追加項目はだいたい前回書いた通りです。
他家一色手模様に関する指標として、(染め色がマンズの場合、)「最初にマンズが切られるまでに切られたピンズ・ソーズの枚数」という項目を加えました。
また、「ある牌が最後に通ってからの手出し回数」に加え、「ある牌と同一筋が最後に通ってからの手出し回数」も入力チャンネルに加えました。

入力チャンネル数は全部で56個になりました。
考慮すべき項目がだいぶ増えたので、フィルター枚数をさらに倍化の128枚にして、
バッチサイズ100×ステップ数1000×epoch数100と10倍の学習量にしました。

読み取るべきcsvの列数も増えて、重みパラメータの数も増えて、epoch数も10倍にしたので、
学習時間は丸1日~2日まで増えました。

まぁ、自分ツモ番に関しては今回ので完成形になるので、この程度の時間で済んでくれるなら安いもんだろうと。
ただ、後で入れ忘れた項目とかcsvからの変換のコードにバグがあったりすると悲惨です。
実際、他家リーチ一発状態を入れ忘れて1回やり直しになって1日強の間待ちぼうけでした。

学習結果はこんな感じ↓。
181030-01.png
損失関数も徐々に減っていって、最終的に正解率は66%overまで来ました。
他家リーチとか副露みたいな対応もまずまずの確度で当てられると。
学習が終わるまでじっと待った甲斐がありました。


実際の手牌との突合せがこちら↓。
181030-02.png
上位2牌の予測が成功してるのは86%まであるので、全体としてはだいぶ実際の牌譜と整合させることができてるかなーと思います。

次の課題は他家から鳴ける牌が出た時の反応についてです。
他家に対する警戒に関する項目はツモ番のときをそのまま流用できます。
自分手牌に関する項目についても、だいたい似たような感じで作れると思います。
シャンテン数や手役関連はスルー時と鳴き時で分ける必要があるとかはちょっとツモ番時とは異なってきそうですが。
難しそうなのは鳴き方が複数ある場合とか、喰い替え禁止あたりをどう表現するかですが、自分の中ではプランはある程度あるので、思い描いたどおりに入力チャンネルの設計ができるかどうかだけです。
まぁ、そこまではなんとかなるでしょう。最悪、場合分けしまくってチャンネル数特盛設計にすればいいです。

そうして、SLポリシーネットワークまでできたら、アルファ碁みたいにReinforceアルゴリズムで強化学習で強くするパートまで見えてきます。

今のところ抱えてる大きな課題は二つ。

・Pythonやkerasで強化学習ってどうすればいいんだ?なんかkeras-rlというもので強化学習ができるらしいという情報まではつかんだのですが、Q学習のサンプルコードは割と見つかったのですが、方策勾配法やReinforceアルゴリズムでは情報が少なくて調べるのが難航してます。actor-criticとかDDPGならkeras-rlの関数でできるらしいけど、普通の方策勾配法のやり方がわからない。
actorが既知(今やってるSLポリシーネットワーク)でcriticが未知みたいな状況なので。
がんばって英語のサイトを探し回るしかないのだろうか。
強化学習については全然素人なので、細かい理論的なところまで頭が回らないです。いちおう、前に薦めてもらった「これからの強化学習」は入手済みで読んだけど、ちょっと難しすぎて何言ってるかわからないです。

・強化学習をするにあたって、ゲームの流れやSLポリシーネットワークなりRLポリシーネットワークなりに突っ込む用のデータ作成のために、今までVB.NETで書いてきた各種関数をPythonで書き直さないといけないことがほぼ確定事項な感じ。最低でもシャンテン計算と、アガリ時メンツ切り分けと、アガリ役判定は必須です。とりあえずものすごくがんばってPythonへの移行を考えなきゃいけないことだけはわかった。

強化学習ができれば、PCのスペックが許す限り、無尽蔵に牌譜を生み出せるので、「アルファ碁解体新書」に書いてる方法で、バリューネットワーク(評価値の算出)まで行ける公算が高いのですが、道はまだ険しいですなぁ。
はじめてのpython&Tensorflowその9・他家リーチ
前回(はじめてのpython&Tensorflowその8・自分副露)から、

他家リーチ者ありのケースを訓練データに追加、入力チャンネルに他家リーチかどうかと、各牌の現物筋変数状況を追加。

今回もチャンネル数が増えただけで、モデルの構造に大きな変化はないのでTensorBoradのグラフ図は省略。

損失関数と正解率のグラフ↓。
181026-01.png
途中で折れ曲がってるのは、最初の10epoch回して学習を打ち切ったのですが、グラフの曲線的に学習を進めればもうちょっと改善できそう?と思って、さらに10epoch追加で学習させたためです。

他家リーチへの対応とかいう普通の手作りと別要素が入ってくるにもかかわらず、正解率65%超えまで進んでくれていい感じ。
さらに学習を進めれば、まだまだ損失関数の改善が見込めそうですが、とりあえず試作段階なので、このへんで終えておきます。

手牌との突合せが↓。(最初の100件)
181026-02.png
全体のバランス的にはリーチ者なしのサンプル数の割合のほうが高いので、前回とそんなに変わらないように見える。

対面リーチがある場合でフィルターをかけたものの最初の数十件↓。
181026-03.png
対面リーチの件数は10000件中386件。予測1位的中率は58%、予測2位まで的中だと75%になってます。

対リーチだと手が広いことのほうが多い(現物や安全そうな牌が3種以上あるとか、危険牌を切って押し返しもあるとか)ので、全体よりは正解率は落ちますけど、それでも6割弱は正解を当てられてるというのは、自分としてはなかなかいいんじゃないか、と思いましたが、どうですかね?

次の課題は他家副露です。これで訓練データの制限は全部外れる(自分リーチの場合以外)ので、自分ツモ番についてのポリシーニューラルネットの決定版になりそうです。
ただ、他家副露まで含めると考えるべき要素が多くなるので、うまいこと入力データを作れるといいですが。
考えてる追加項目とすると、
・他家が副露しているかどうか、もしくは門前状態であるかどうか。
・他家副露数
・他家副露種類
・他家副露牌
・他家副露の見えてる役・ドラの枚数
・捨て牌が一色模様かどうか
・同巡フリテンと同巡筋牌
・ある牌が最後に通ってからの手出し回数
・同色5が切られてるかどうか、もしくは切られた巡目
・同色内側牌が切られてるかどうか、もしくは切られた巡目
・親番が誰か
・他家3人の役牌情報
・4人の点数
・残り局数
・積み棒、供託リーチ棒

うん、たくさんあるね。

一番難しそうなのは「捨て牌が一色模様かどうか」をどう定義してニューラルネットに組み込むかですね。

csvの容量的にもけっこう大変なことになってきてます。
現時点でエクセルで「AAR」列まで1件あたりのデータが増えてきてます。列番3桁は初めて見る。
はじめてのpython&Tensorflowその8・自分副露
前回(はじめてのpython&Tensorflowその7・リーチと暗槓)からの追加項目として、
自分が副露手の場合を訓練データに追加しました。(他家については従前どおり3人非リーチ門前)

入力項目の追加は、
・チートイシャンテン数
・国士シャンテン数
・副露数
・副露種類(役牌・タンヤオ・その他)
・副露牌
・副露牌も入れた手牌枚数
です。

入力チャンネルが増えただけで、モデルの構造はほぼ変化がないので、TensorBoradのグラフは省略。

損失関数と正解率のグラフ↓。
181024-01.png
たぶんそんなに変わりはない。

手牌との突合せ↓。(最初の100件)
181024-02.png

副露している手牌についてフィルターをかけたもの↓。
181024-03.png
門前手と比較してもそこまで変な結果にはなってなさそう。

リーチされた手牌についてフィルターをかけたもの↓。
181024-04.png
前の時より予測リーチ率上がった?


ここまで、他家攻撃なしについて、65%弱程度の正解率で打牌決定ができたことになったと思います。
次はいよいよ他家攻撃ありの場合に移ろうかと思います。
やっと四人麻雀ができるぜー。
まずは対リーチでちゃんと判断ができるかどうかですね。

追加項目として考えてるのは、
・他家3人について、リーチをしているか。
・他家3人について、各牌の現物筋無筋状況。
とりあえずはこれだけで、ちゃんと対リーチ対応をやってくれることを祈ろう。
はじめてのpython&Tensorflowその7・リーチと暗槓
前回(はじめてのpython&Tensorflowその6・手役情報と複数回畳み込み計算)からの追加項目として、
自分のツモ番における選択肢として、牌を切る以外に、リーチ宣言と暗槓があるので、今回はその部分を入れました。

ニューラルネットの構造としては、出力値として、従前の牌番号だけから、リーチ宣言したかどうかと、暗槓したかどうかの出力値を2つ足した感じになります。
分岐は最後のDense計算層(従前だとdense_3層)からにしています。

損失関数は各出力ともクロスエントロピーで、3つの損失関数の単純加算した値を最小化させる最適化です。特に工夫もなくふつうです。

入力チャンネルの追加は、
・打牌可能か
・リーチ可能か
・暗槓可能か
の3つです。

構造はこんな感じ↓。
181022-01.png

損失関数と正解率はこんな感じ↓。
バッチサイズ100、1epochあたり1000ステップで、10epoch分回した。
181022-02.png

損失関数のカーブ的にまだ改善の見込みはありそうだけど、まぁ計算時間の都合で今回はこのへんにしておく。

リーチのほうはまだましですが、暗槓については全体のデータ数から見てだいぶレアケース(テスト用データ10000件中暗槓は6件のみ)な分、損失関数の値が小さすぎてほぼ機能してない疑惑。

手牌との突合せ↓(最初の100件)
181022-03.png
まぁこれは従前と似たようなものか。

実際にリーチ宣言されたデータについての予測値↓。
181022-04.png
さっきのよりは予測リーチ率は高めに出てくれてるけど、予測リーチ率5割以上を正解とみなす場合、けっこう5割に届いてないケースが多いです。

特に七対子聴牌のケースについては予測リーチ率が低くてちょっと適応できてない感があります。
後、赤5を切って聴牌のケースもうまく予測できずに弱点になってるっぽい。
このへんは学習量を増やせばなんとかなるものなのかなー。

実際に暗槓されたデータについての予測値↓。
181022-05.png

暗槓がまともに機能してない疑惑的中。
暗槓可能情報やリーチ可能情報を入力層のチャンネルの中に埋め込むんじゃなくて、別口でもうちょっと上のDense層とかに直接突っ込んだほうがいいのだろうか?


次の課題
・七対子国士情報追加
・リーチ暗槓可能情報の入れる場所
・自分副露手の打牌選択
プロフィール

nisi5028

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

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

この人とブロともになる

QRコード
QRコード