FC2ブログ

*All archives* |  *Admin*

<<09  2018/10  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  11>>
はじめてのpython&Tensorflowその4・手牌枚数で畳み込みニューラルネット
前回で、Denseを直列つなぎしただけのちゃちなニューラルネットを組みましたが、
今回はそこから卒業してアルファ碁みたいに畳み込み計算をやってみようと思います。

大量のエラーメッセージの波をかき分けながら、なんとかモデルのコンパイルが通りました。
型変換するだけとか、ベクトルのサイズ変更するだけでもえらく大変でした。kerasたん、ツンデレすぎる…。
ググって調べる能力だけでなんとかやってきてます。

今回組んだニューラルネットの構造はこんな感じ↓。(TensorBoradのグラフ図)
181014-02.png

入力は前回と同じで、37種牌の枚数を要素にもつ37次ベクトル。
まずは入力のベクトルをマンズ、ピンズ、ソーズ、字牌の4つに分割しています。

その4区分に対して、下のほうのlambda_〇みたいな層がいっぱいあるのは畳み込み計算ができる形に整形をするなどの下ごしらえ工程です。

マンズ、ピンズ、ソーズについては数牌フィルター(サイズ5×6、重みパラメータは共有)32枚を通す2次元畳み込み計算をしています。(conv2d_1層)

字牌については数牌とは別個のフィルター(サイズ1×6)32枚を通す2次元畳み込み計算をしています。(conv_2d_2)

で、出力がshape9×32が3つと7×32が1個出てきたのを統合してるのが、その上のconcatenateの層。
そこからは前回と同じ感じで全結合3回を直列させてるのを計算してます。

なんかすんごいぐっちゃぐっちゃにかき回してるだけの汚いニューラルネットですね。

それで上記のようなニューラルネットで学習させたのがこんな感じ↓。(1万試合分の手牌で、10epoch)
181014-03.png
前回の正解率44%から、今回は57%くらいへと評価値がだいぶ向上してます。
汚くても結果が出ればええねん、みたいな。

テストデータ(手牌+正解ラベル)による検証がこちら↓。(サイズがでかすぎるとエクセルでの取り回しが効きにくいので、10000試合だけ抜き取った。)
181014-01.png
2位的中率まで含めれば82%まで予測的中率が上がってます。だいぶいい感じです。
畳み込み計算によって当該牌の周囲の形を見ることができるようになったのが表れてるのかなーと思います。


〇現在困ってること
model.saveをしようとするとエラーが出る。
model.save_weghitsは通る。
model.to_jsonは通らないので、重みのセーブはできるけど、ニューラルネットの構造がセーブできない状況。(現在は訓練用と同じコードを予測用プログラムでもコピペすることで応急的に対応してる。)
おそらく、原因は、
kakou_manzu = Lambda(tf.cast,arguments={'dtype':tf.int32})(kakou_manzu)
の行(テンソルのdtypeをfloatからintに変えたい)で、kerasの関数でなくTensorflowの関数を使ってるため。
kerasの関数で型変換ができればたぶんmodel.saveも通るので、構造のセーブができると思うのだけど、何かいい方法はないだろうか?


次は、入力情報を増やす(畳み込み計算の入力チャンネル数を増やす)ことをやろうかと思っています。

入れようとしている情報として、
・巡目
・ドラ
・赤5牌
・役牌
・当該牌を切った時の面子手シャンテン数
・当該牌を切った時の対子数(七対子がらみ)
・当該牌を切った時のヤオ九牌種類数(国士がらみ)

また牌譜解析からcsvを取って、それをPythonで読み取ってうまいことNNの設計をして、…みたいなイメージ。
スポンサーサイト
はじめてのpython&Tensorflowその3・他家攻撃なし、手牌枚数のみニューラルネット
前回で、Pythonの機械学習で自力での応用ができるようになった(多分)ので、
いよいよ麻雀におけるデータで試してみたいと思います。

まず最初は前回でも書いた通り、
他家攻撃なしかつ手牌の枚数情報のみを入力値にして、
てきとうなニューラルネットにぶちこんでみます。
本当に手牌の枚数情報のみなので、巡目もドラも役牌種類も全然考慮してません。

入力データは最初の1000試合分、約13万種類の手牌を訓練用に最初の6分の5の11万種類を充て、残りの6分の1の2万種類をテスト用(評価用)としました。
出力値は37種類の牌の切られる確率の予測値です。

ニューラルネットの構造
・入力層…37種類の牌の手持ち枚数
・隠れ層1…全結合でノード数64、活性化関数Relu
・隠れ層2…全結合でノード数64、活性化関数Relu
・出力層…全結合でノード数37、活性化関数ソフトマックス
・損失関数…クロスエントロピー

TensorBoardとやらでニューラルネットの構造を可視化というものをやってみたらこんな感じ↓。
181011-02.png
とりあえず今の私には理解が難しいことだけわかった。

正解率(おそらく予測切られ率で最も大きい牌番号が実際の正解ラベルと同じである確率と思われる。)と損失関数の推移もTensorBoradによるとこういう感じらしい↓。
181011-03.png
多分左側のvalがないほうが訓練用データの正解率(acc)と損失関数(loss)で、右側のvalがついてるほうがテスト用データの正解率と損失関数だと思われます。

学習が進むにつれ正解率は上昇し、損失関数は減少しているようなことがわかります。
10epoch回した結果、テストデータの正解率で44%くらいということです。
37種類の牌もしくは手牌にある牌のどれかを切れる中で、5回に2回は実際に切られた牌と同一の予測をできるのは、初回で適当に組んだだけで、役牌とかドラとかも考慮してないにしてはまずまずの結果じゃないかなーと思います。

結果をエクセルでまとめるとこんな感じ↓
181011-01.png
テスト用データについて、予測率が1番高い牌番号と2番目に高い牌番号を取ってきて、1位的中率と1位or2位の的中率を出してみました。
(牌番号1~10がマンズ、11~20がピンズ、21~30がソーズ、31~37が字牌)

特徴として、
予測1位や2位の牌はことごとく字牌や端寄りになってる感じです。
全員リーチも副露もしてないので、データが序巡に偏ってるためかなーと。
真ん中牌が切られるケースは外れデータみたいな扱いをされてるのかもしれないです。
まぁ、手持ちにない牌が予測1位や2位になるケースはほぼなさそうで安心。


次はニューラルネットの構造をもうちょっとましにして実用的にしようかと思います。
具体的には枚数と重みパラメータのテンソル積の全結合にするんじゃなくて、アルファ碁みたいに畳み込み計算を導入してパラメータの個数を減らして計算時間にかかる負荷を減らそうかと。

まだKerasについて十分理解していないので、全結合と単純な畳み込み計算以外の方法を知りませんが、調べたらどこかに載ってるかなぁ。
はじめてのpython&Tensorflowその2・keras導入
Tensorflowよりもkerasというのを使うとわかりやすいらしいという情報をいただきまして、
調べてみていろいろいじくってみたところ、
Tensorflow…ほぼ無理→keras…なんとかなりそう、
くらいに理解度が改善しました。

今日書いたコードはこちら↓。
180810-02.txt

やったのは、
・mnistのkeras版サンプルコードをコピペして理解する。
・2次元散布図の2値分類問題について、先のサンプルコードを応用しながら自分でプログラムを書いた。
・計算された重みパラメータを使ってテストデータで予測値を出してcsvに吐き出す。あとはエクセルでてきとうにグラフ化。
です。

割と勉強は進んで、簡単なニューラルネットなら自力で応用できるようになりました。

1個目は、
[-1,1]×[-1,1]の2次元の一様乱数を200個発生させて(前者がx、後者をyとする)、y>x^2なら正解ラベル1を、y<=x^2なら正解ラベル0をつけたものを訓練データ&テストデータとしてニューラルネットの計算をやりました。
ニューラルネットは真の境界線y=x^2は知りませんが、与えられた(x,y)の組に対して0か1のどちらかで予測します。

200個の点のうち、100個ずつ訓練用とテスト用に分けて、前半100個の訓練データで散布図を描いたものがこちら↓です。
181010-03.png

ニューラルネットの構造は
入力層:x,yの2個
隠れ層1:全結合でノード数10(活性化関数Relu)
隠れ層2:全結合でノード数10(活性化関数Relu)
出力層:0か1で2個(活性化関数ソフトマックス)

多層ニューラルネットの微分とか誤差逆伝搬を計算しなくてもよい喜びはひとしおです。

出力されたのは拡張子hdf5というファイル。この中にモデルの情報が全部詰まってるらしいです。

これを再度pythonで読み込みなおして、テストデータ100件から予測値(0か1)を出して散布図にしたのがこちら↓。
181010-04.png
100件中予測値と正解ラベルが違うのは4件(オレンジ色の点)。正解率96%でした。

y=x^2だと簡単すぎたかなーと思って、もうちょっと変態な関数でやってみようかなーと思いました。
こんどはy=2(x-1)x(x+1)と三次関数にしてみました。
さっきはデータがすかすかだったので、データ数を5倍の500件+500件に増やしてみました。

ニューラルネットの構造はさっきと同じとします。

↓訓練データ散布図
181010-05.png
↓テストデータによる予測の散布図
181010-06.png
予測が外れているのは500件中6件。正解率98.8%。
データ数が増えたためか、より正解率は増えてくれました。


とりあえずこれで自分でPythonを使って機械学習を応用できる目途がたちました。
麻雀のケースへの応用を考えることができるフェーズに入れそうです。

まずは最初なんでできるだけ簡単にするため、
入力情報を「自分の手牌構成」だけにしようと思っています。

そのために訓練データの取り方として、
全員副露もリーチもしていない状況、という条件下で、(赤ナシ換算の)手牌情報34種のマスに枚数だけの情報+正解ラベルは(赤ナシ換算の)実際に切られた牌、を牌譜解析から収集、csv化して、
そこからはpythonとkerasでのお仕事でモデルを組んで重みパラメータを出す、という流れを想定しています。

単純な全結合とか畳み込み計算とかではできなさそうなので、その辺のモデルの組み方は腕の見せ所になりそうですが、
ほぼ無理なレベルから、なんとかなりそうレベルまで持って行けたのは非常にでかいです。

とりあえず今日はこんなところで。
はじめてのpython&Tensorflowその1・mnistの畳み込みニューラルネット
より高度な機械学習をするため、というか手計算で微分とか誤差逆伝搬とかするのがしんどくなってきたので、新しくPythonとTensorflowを勉強してます。

環境構築はわりと手間取りましたが、なんとかできました。
pipがアップグレードできないとかでTensorflowをインストールできずに詰まるのは勘弁してほしかった。

Pythonの基本的文法はまぁVB.netと同様オブジェクト指向なので、なんとかなりそう。
変数の宣言とかで明示的に型を明記しないところが違うので、若干戸惑うところではありそう。

次に機械学習に必要なTensorflowを勉強している途中です。

なんですけど、すごく難しくて、わかるor応用できる気がまるでしないのが現状です。
テンソル?なにそれおいしいの?ベクトルのすごいバージョンみたいなものか?、という程度の認識しか持ってないので、非常に厳しい。

Tensorflowの入門サイト(https://deepinsider.jp/tutor/introtensorflow/buildcnn)を見て、サンプルコード(mnistのCNN計算)をコピペしてプログラムを動かしてみたのはいいけれど、わからないところが多すぎます。

↓は上記サイトのリスト6のコードで、自分がわからんところをコメントアウト(#?~?の間)で列挙して書き加えたものです。
180808-02.txt

半分以上わからん。
いちおう、出力はちゃんとされてるみたい。↓
181008-01.png

やっぱり無料のサイトを見て回るだけではきついのか…。ちゃんとした入門書を買わないといけないのかなー。
Python自体全然コードが慣れてないので、図書館の返却期限の2週間後にはPythonの入門書を返さなきゃいけないので、日程的な焦りもある。

サルでもわかるとまでは言わない、理系一般人にわかるTensorflow入門のサイトか本をだれか教えてくれたら非常にうれしいです。


エディタはVisual Studioがそのまま使えてるので、いいですけど、Tensorflowの関数打ち込んだときの関数の説明書きが全部英語なのもけっこうつらい。
パッと見でどういう関数なのかがつかめない。
日本語で勉強できるTensorflowのサイトor本がいいんですけど、高望みしすぎでしょうか。
麻雀AI開発その97・次の予定
今日は特に成果物があるわけではないですが、麻雀AIの話です。

この前のPCデータ吹っ飛び事件を受けて、
全く同じことをやり直すというモチベーションが著しく下がっている今日この頃。
染め手対応とかできてないことへの対応はしたいところなのですが、そういう気分ではないです。

そこで、どうせなら別アプローチで麻雀AI開発をしたいなーと思うようになりました。
従前のモンテカルロシミュレーションをベースにしてちまちま牌譜解析でパラメータ取りとか部分的なニューラルネットで部品作りだけするのが邪魔くさいと。

参考にしたいと思ってるのが、「アルファ碁」の事例です。
(人から薦めてもらった「最強AIアルファ碁解体新書」を読みながら。)

まずアルファ碁でやってるのは教師付き学習のニューラルネット(SLポリシーネットワークと書かれている)で、各候補手が打たれる確率を算出しているのをやっているようです。
具体的には13層の畳み込みニューラルネット(CNN)のようです。石の配置等を画像分析のように2次元の情報ととらえて多層の畳み込み計算をすると。

では、麻雀の場合はというと、自分の手の形については1次元(もしくは枚数も含めれば2次元データとも見れる)の情報としてとらえて畳み込み計算はできなくはなさそう。
アルファ碁のSLポリシーネットワークでは入力層の情報を48チャンネルとして持っているようなので、麻雀についても手の形以外の情報、例えば捨て牌とか牌種類とかを同じように複数チャンネルで処理していくみたいな構想です。

アルファ碁ではSLポリシーネットワークの後、それをベースとして、強化学習でRLポリシーネットワークというものを作って、より強いAIにしていくという方法をとっているようです。
今の私の手持ちのAIだとちゃんとしたニューラルネットになってなくて、パラメータをちょこちょこ変えつつの強化学習がかなり困難なので、強化学習でよりAIを進化させることができる可能性がある、という点で将来性があっていいかなーと思っています。


と、ここまでは気前よく願望を含みの将来像を書いてきましたが、実際に私の実力的に可能かどうかは相当あやしいです。
なんかありきたりな発想なので、ほかの人も通った道なのかもしれませんし。

とりあえずこういう文章だけ書いてみて決意表明だけはして、思い描いている構想を前に進める努力はするけども、「やっぱりできませんでしたー」になる可能性も相当高いです。


ところで、今まで私が使っているプログラミング言語はVB.netなのですが、Pythonという言語だと、なんか機械学習関連のフレームワーク(?)とやらが充実していていいらしいという話をちょこちょこ目にします。
多層のニューラルネットになるといちいち微分を自分で計算してうんぬんとかが非常に困難なことも予想されるので、そのへんが自動でやってくれるものがあるのなら非常に魅力的ではあります。

なんで、私にとって新しい言語であるPythonの習得から入るという序の口から入らないといけないので、道のりは険しいですが、一から麻雀AIを組むなら既存プログラムとの噛み合わせの問題もほぼないと思われるので、勉強するコストを払うには見合うかなーと思っています。

まぁ、PCデータ吹っ飛び事件をきっかけに踏ん切りがついたと思えれば、ちょっとでも前向きな方向でいいのかなーとか。
プロフィール

nisi5028

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

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

この人とブロともになる

QRコード
QRコード