スランプグラフから設定判別してくれるなんちゃってAI



突然ですが、ジャグラーで↓のスランプグラフの時、設定はいくつだと思いますか?

きっと大多数の方が「設定6」と答えるのではないでしょうか?
では、こちらはどうでしょう?

はい、「設定1」ですよね。
これってたぶん、我々スロッターの頭の中では過去に見てきたたくさんのスランプグラフが脳にインプットされていて、そこから今見たスランプグラフがどの記憶に似ているかで判断していると思います。

今回はこれをコンピュータにやらせてみたい!ということで、スランプグラフから設定判別してくれるなんちゃってAIを作成したいと思います。
(あくまでも素人が思いつきで作ったようなレベルなので、緩い目でご覧ください。)
今回はマイジャグラーⅢを例に、スランプグラフの傾向から設定判別してみます。

はじめに

今回は以下の流れで実験を行います。

1. 判別したいスランプグラフを作成
2. 設定ごとのビッグデータ(スロッターの脳にあるたくさんのスランプグラフの記憶)を作成
3. 判別したいスランプグラフに似た傾向がビッグデータ内にどれくらいあるかを確認
4. 各設定のビッグデータ内で、近いデータがいっぱい見つかった設定が今回の設定!(のはず。)

当然「3. 判別したいスランプグラフに似た傾向がビッグデータ内にどれくらいあるかを確認」が最も大事になってきますが、今回は「相互相関」という手法を使って検証していきます。

どうやってスランプグラフの傾向を評価するか?(相互相関)

「相互相関」とは、ある2つのデータの類似度を評価する手法です。
例によってpythonでは↓の1行で計算してくれるわけですが、せっかくなので中身の計算のイメージだけでもつかんでおきたいと思います。
np.corrcoef(ビッグデータから1日分抜き出したデータ, 1日分のスランプグラフ)[0,1]
「相互相関」の中身の計算は、「内積」とほぼ同じなので、「内積」の計算について説明します。
「内積」は線形代数で勉強したあの「内積」で、以下の計算式で求められます。

↑の式をcosθの式に直すと、↓のようになります。
この式が「相互相関」でやっていることとほぼ同じです。

ちょっと式を見てもわからないので、下図に例を計算してみました。
ベクトルだと考えると理解しにくいですが、スランプグラフだと思うと、傾向が近いものほど値が「1」に近づいていくイメージができると思います。
つまり、青線が設定判別したいスランプグラフ、オレンジ線が脳にインプットされているたくさんのスランプグラフになるわけですね。


1. 判別したいスランプグラフを作成

ここから、Pythonでのコーディングを行っていきます。
以前マイジャグⅢのシミュレータを作成しているので、結果をcsv出力できるように修正します。
まずは、必要なライブラリを追加でインポートします。
下2行の「numpy」と「csv」を追加でインポートしています。
import random
import matplotlib.pyplot as plt
import numpy as np  # 結果のcsv出力用
import csv  # 結果のcsv出力用
次に、結果の出力用のコードを追加します。
スランプグラフの表示用のコードの下に、csv出力用のコードを追加します。
結果が入力されている変数はList型で、このままでは扱えないのでnumpyの配列に変換しています。
これで「data_mjg.csv」のcsvファイルが出力できます。
    # スランプグラフの表示
    plt.title('Setting: %d, Loop = %d' % (設定,loop))
    plt.plot(Result)
    plt.grid(True)
    # plt.show()

    # データのcsv出力
    with open('D:\Test\data_mjg.csv', 'w') as file:
        writer = csv.writer(file, lineterminator='\n')
        writer.writerows(np.array([Result]).T)
最後に設定値を変更しておきます。
今回は設定6で8000回転のデータを作成しました。
if __name__ == "__main__":
    # 設定値の設定
    設定 = i
    # 試行回数の設定
    loop = 8000
    # 途中結果表示の区切り回数
    区切り回数 = 8000

    SlumpGraph_calc(設定, loop, 区切り回数)

2. 設定ごとのビッグデータ(スロッターの脳にあるたくさんのスランプグラフの記憶)を作成

次に設定ごとのビッグデータを作成します。
「1. 判別したいスランプグラフを作成」で作ったファイルを上書きしてしまわないように保存ファイル名を変更しておきます。
ファイル名の末尾に設定値を入れるように変更しました。
    # データのcsv出力
    with open('D:\Test\data_mjg_' + str(設定) + '.csv', 'w') as file:
        writer = csv.writer(file, lineterminator='\n')
        writer.writerows(np.array([Result]).T)
また、各設定のcsvファイルをまとめて出力できるように、シミュレーション設定値をまとめて入れられるように変更しておきましょう。
今回は各設定で100万回分のシミュレーションデータを作成しました。
if __name__ == "__main__":
    for i in range(1,7):
        # 設定値の設定
        設定 = i
        # 試行回数の設定
        loop = 1000000
        # 途中結果表示の区切り回数
        区切り回数 = 1000000

        SlumpGraph_calc(設定, loop, 区切り回数)

3. 判別したいスランプグラフに似た傾向がビッグデータ内にどれくらいあるかを確認

ここから「相互相関」を用いて、スランプグラフから設定判別を行っていきます。
まずは準備したデータを読み込んでいきます。
# coding: UTF-8
import numpy as np

# データベースファイルの読み込み
ResultData = np.loadtxt("D:\Test\data_mjg.csv", delimiter= ",")
ResultDatabase1 = np.loadtxt("D:\Test\data_mjg_1.csv", delimiter= ",")
ResultDatabase2 = np.loadtxt("D:\Test\data_mjg_2.csv", delimiter= ",")
ResultDatabase3 = np.loadtxt("D:\Test\data_mjg_3.csv", delimiter= ",")
ResultDatabase4 = np.loadtxt("D:\Test\data_mjg_4.csv", delimiter= ",")
ResultDatabase5 = np.loadtxt("D:\Test\data_mjg_5.csv", delimiter= ",")
ResultDatabase6 = np.loadtxt("D:\Test\data_mjg_6.csv", delimiter= ",")
次に、設定判別の準備を行います。
「相互相関」は、先に説明した通り「1」に近づくほどスランプグラフの傾向が近いことを意味します。
今回は、「相互相関」の結果が「0.7」より大きい場合に、傾向が似ていると判定することにします。
また、似ている傾向が何回含まれていたかをカウントする変数を準備しておきます。
# 類似と判定する閾値の設定
corr_th = 0.7

# 類似した箇所のカウント用変数
count1 = 0
count2 = 0
count3 = 0
count4 = 0
count5 = 0
count6 = 0
ここで、相互相関を行っていきます。
for文を用いて、ビッグデータを少しずつずらしながら、設定判別したいスランプグラフと比較していくことで、ビッグデータ内にある類似箇所をカウントすることができます。
for文内でやっていることのイメージは下図のような形です。


# ビッグデータを少しづつずらしながら、当日のデータと比較
for i in range(0, len(ResultDatabase1) - len(ResultData), 10):
    if corr_th < np.corrcoef(ResultDatabase1[i : i + len(ResultData)], ResultData[:])[0,1]:
        count1 = count1 + 1
    if corr_th < np.corrcoef(ResultDatabase2[i : i + len(ResultData)], ResultData[:])[0,1]:
        count2 = count2 + 1
    if corr_th < np.corrcoef(ResultDatabase3[i : i + len(ResultData)], ResultData[:])[0,1]:
        count3 = count3 + 1
    if corr_th < np.corrcoef(ResultDatabase4[i : i + len(ResultData)], ResultData[:])[0,1]:
        count4 = count4 + 1
    if corr_th < np.corrcoef(ResultDatabase5[i : i + len(ResultData)], ResultData[:])[0,1]:
        count5 = count5 + 1
    if corr_th < np.corrcoef(ResultDatabase6[i : i + len(ResultData)], ResultData[:])[0,1]:
        count6 = count6 + 1

4. 各設定のビッグデータ内で、近いデータがいっぱい見つかった設定が今回の設定!(のはず。)

得られた結果を確認してみます。
今回は設定ごとに見つかったカウント数の割合で、設定判別結果を出力してみます。
# 結果の出力(カウント数の割合で算出)
print("1:", round(count1 / (count1 + count2 + count3 + count4 + count5 + count6) * 100, 0), "%")
print("2:", round(count2 / (count1 + count2 + count3 + count4 + count5 + count6) * 100, 0), "%")
print("3:", round(count3 / (count1 + count2 + count3 + count4 + count5 + count6) * 100, 0), "%")
print("4:", round(count4 / (count1 + count2 + count3 + count4 + count5 + count6) * 100, 0), "%")
print("5:", round(count5 / (count1 + count2 + count3 + count4 + count5 + count6) * 100, 0), "%")
print("6:", round(count6 / (count1 + count2 + count3 + count4 + count5 + count6) * 100, 0), "%")
結果は以下のようになりました。
今回設定6のデータを用いましたが、意外と良い結果が出てますね。
1: 4.0 %
2: 6.0 %
3: 8.0 %
4: 17.0 %
5: 26.0 %
6: 39.0 %
ちなみに設定判別したスランプグラフはこんな感じです。
割ときれいな右肩上がりのグラフだったのもありますが、右肩上がりこそ設定6の特徴だと考えると、スランプグラフの傾向からでもある程度の設定判別ができそうですね。

今回作成したコード

「相互相関」の計算から結果を出力するまでのコードは、こちらです。
# coding: UTF-8
import numpy as np

# データベースファイルの読み込み
ResultData = np.loadtxt("D:\Test\data_mjg.csv", delimiter= ",")
ResultDatabase1 = np.loadtxt("D:\Test\data_mjg_1.csv", delimiter= ",")
ResultDatabase2 = np.loadtxt("D:\Test\data_mjg_2.csv", delimiter= ",")
ResultDatabase3 = np.loadtxt("D:\Test\data_mjg_3.csv", delimiter= ",")
ResultDatabase4 = np.loadtxt("D:\Test\data_mjg_4.csv", delimiter= ",")
ResultDatabase5 = np.loadtxt("D:\Test\data_mjg_5.csv", delimiter= ",")
ResultDatabase6 = np.loadtxt("D:\Test\data_mjg_6.csv", delimiter= ",")

# 類似と判定する閾値の設定
corr_th = 0.7

# 類似した箇所のカウント用変数
count1 = 0
count2 = 0
count3 = 0
count4 = 0
count5 = 0
count6 = 0

# ビッグデータを少しづつずらしながら、当日のデータと比較
for i in range(0, len(ResultDatabase1) - len(ResultData), 10):
    if corr_th < np.corrcoef(ResultDatabase1[i : i + len(ResultData)], ResultData[:])[0,1]:
        count1 = count1 + 1
    if corr_th < np.corrcoef(ResultDatabase2[i : i + len(ResultData)], ResultData[:])[0,1]:
        count2 = count2 + 1
    if corr_th < np.corrcoef(ResultDatabase3[i : i + len(ResultData)], ResultData[:])[0,1]:
        count3 = count3 + 1
    if corr_th < np.corrcoef(ResultDatabase4[i : i + len(ResultData)], ResultData[:])[0,1]:
        count4 = count4 + 1
    if corr_th < np.corrcoef(ResultDatabase5[i : i + len(ResultData)], ResultData[:])[0,1]:
        count5 = count5 + 1
    if corr_th < np.corrcoef(ResultDatabase6[i : i + len(ResultData)], ResultData[:])[0,1]:
        count6 = count6 + 1

# 結果の出力(カウント数の割合で算出)
print("1:", round(count1 / (count1 + count2 + count3 + count4 + count5 + count6) * 100, 0), "%")
print("2:", round(count2 / (count1 + count2 + count3 + count4 + count5 + count6) * 100, 0), "%")
print("3:", round(count3 / (count1 + count2 + count3 + count4 + count5 + count6) * 100, 0), "%")
print("4:", round(count4 / (count1 + count2 + count3 + count4 + count5 + count6) * 100, 0), "%")
print("5:", round(count5 / (count1 + count2 + count3 + count4 + count5 + count6) * 100, 0), "%")
print("6:", round(count6 / (count1 + count2 + count3 + count4 + count5 + count6) * 100, 0), "%")

ちなみに、設定1で↓のスランプグラフの時の結果はこのような形でした。

1: 31.0 %
2: 27.0 %
3: 21.0 %
4: 11.0 %
5: 8.0 %
6: 2.0 %

また、設定6のちょっとわかりづらいスランプグラフの時はこちら。

1: 21.0 %
2: 15.0 %
3: 19.0 %
4: 14.0 %
5: 24.0 %
6: 6.0 %
さすがに人間でも判断がつかないようなレベルの判別はこのレベルのコードでは困ってしまうようですね。


にほんブログ村 スロットブログ スロット情報へ
にほんブログ村

コメント

このブログの人気の投稿

【WEBアプリ】Sキングハナハナ-30のベル確率予想&ベル確率逆算ツール&設定判別ツール

【WEBアプリ】ハナハナホウオウ天翔のベル確率を差枚数から逆算するツール

【WEBアプリ】ハナハナホウオウ天翔の設定判別ツール