LoginSignup
0
0

13個の手牌を286通りにして3つのニューラルネットワークにかけてその結果から聴牌かどうかを判断するニューラルネットワーク

Last updated at Posted at 2023-06-05

※この記事は2020年に作成しました

#概要
まず、手牌は大きさが34の配列に牌の種類の該当するところにその牌の個数が入っている。それを牌の番号ごとにして13個の手牌の形にしている。
そして、itertools.combinationsを使ってそれぞれを13個の手牌から3つを取り出す286通りに並べている。
それを順子YN、刻子YN、国士YNの3つを通してそれぞれの結果を出す。その結果をnp.hstackで1つにまとめて学習データの完成としている。
学習データは4942個の聴牌データと4942個のノーテンデータを使用している。
それぞれのYNの結果を通して1つにまとめるまでは、聴牌とノーテンのデータを別々に処理している。
単純計算で、YNのモデルで判断する回数は、「データ数×286通り×3つのYN」なので、848万472回である。
3つのYNの結果からハードコーディングで聴牌判定をすることは不可能なので、最初の半分を聴牌、残りの半分をノーテンとして3つのYNの結果を出して学習データとし、それに正解ラベルを付けてシャッフルしてから、正解ラベルを作成して、学習データから正解ラベルを消している。

 _{13}C_3=286

#結果
5エポック目から50エポック目まではテストデータに対する正解率はずっと95%前後だった。
aaaaaaaaaaaaaaaaaaaaaaaa.png

#作成したプログラム

# coding: UTF-8
import numpy as np
import itertools
import time
from keras.models import load_model
from keras.utils import to_categorical
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
np.set_printoptions(threshold=10000000,linewidth=200)
t1 = time.time() 

#x_test = np.loadtxt("C:/Users/p-user/Desktop/csvdata/old/tehai_xtest.csv",delimiter=",")
#y_test = np.loadtxt("C:/Users/p-user/Desktop/csvdata/old/tehai_ytest.csv",delimiter=",")

data = 4942
x_train = np.zeros((data,34), dtype='float32')# x_trainは聴牌の手牌
with open('C:/sqlite/tenpai.csv', 'r') as fr:
    for i,row in enumerate(fr.readlines(),start=0):
        if i <data:
            x_train[i] += np.array(list(map(np.float,row[:34])))

y_train = np.zeros((data,34), dtype='float32')# y_trainはノーテンの手牌
with open('C:/sqlite/noten.csv', 'r') as fr:
    for i,row in enumerate(fr.readlines(),start=0):
        if i <data:
            y_train[i] += np.array(list(map(np.float,row[:34])))


tehai = np.zeros((data,13))#x_trainを13個の手牌tehaiへ
for i in range(data):
    cnt = 0
    for j in range(34):
        if x_train[i,j] >= 1:
            tehai[i,cnt] = j
            cnt += 1
            x_train[i,j] -=1
        if x_train[i,j] >= 1:
            tehai[i,cnt] = j
            cnt += 1
            x_train[i,j] -=1
        if x_train[i,j] >= 1:
            tehai[i,cnt] = j
            cnt += 1
            x_train[i,j] -=1
        if x_train[i,j] >= 1:
            tehai[i,cnt] = j
            cnt += 1
            x_train[i,j] -=1

tehaiN = np.zeros((data,13))#y_trainを13個の手牌tehaiNへ
for i in range(data):
    cnt = 0
    for j in range(34):
        if y_train[i,j] >= 1:
            tehaiN[i,cnt] = j
            cnt += 1
            y_train[i,j] -=1
        if y_train[i,j] >= 1:
            tehaiN[i,cnt] = j
            cnt += 1
            y_train[i,j] -=1
        if y_train[i,j] >= 1:
            tehaiN[i,cnt] = j
            cnt += 1
            y_train[i,j] -=1
        if y_train[i,j] >= 1:
            tehaiN[i,cnt] = j
            cnt += 1
            y_train[i,j] -=1

label=[0,1]
tehaiC = np.zeros((data,286,3))
for i in range(data):#tehaiを286通りへ
    tehaiC[i,] = list(itertools.combinations(tehai[i,], 3))
    #print(tehaiC[i,])

tehaiCN = np.zeros((data,286,3))
for i in range(data):#tehaiNを286通りへ
    tehaiCN[i,] = list(itertools.combinations(tehaiN[i,], 3))
    #print(tehaiC[i,])

modelShunts = load_model('shuntsYN.h5')   
ShuntsYN = np.zeros((data*2,286))#順子YNの結果を入れる
for i in range(data):#tehaiCを順子YNにかける
    for j in range(286):
        x_train = np.zeros((1,3))
        x_train[0,] = tehaiC[i,j]
        x_train = x_train/33.
        pred = modelShunts.predict(x_train, batch_size=1, verbose=1)
        pred_label = label[np.argmax(pred[0])]
        ShuntsYN[i,j] = np.argmax(pred[0])
for i in range(data):#tehaiCNを順子YNにかける
    for j in range(286):
        x_train = np.zeros((1,3))
        x_train[0,] = tehaiCN[i,j]
        x_train = x_train/33.
        pred = modelShunts.predict(x_train, batch_size=1, verbose=1)
        pred_label = label[np.argmax(pred[0])]
        ShuntsYN[i+data,j] = np.argmax(pred[0])

modelkotsu = load_model('kotsuYN.h5')
kotsuYN = np.zeros((data*2,286))#刻子YNの結果を入れる
for i in range(data):#tehaiCを刻子YNにかける
    for j in range(286):
        x_train = np.zeros((1,3))
        x_train[0,] = tehaiC[i,j]
        x_train = x_train/33.
        pred = modelkotsu.predict(x_train, batch_size=1, verbose=1)
        pred_label = label[np.argmax(pred[0])]
        kotsuYN[i,j] = np.argmax(pred[0])
for i in range(data):#tehaiCNを刻子YNにかける
    for j in range(286):
        x_train = np.zeros((1,3))
        x_train[0,] = tehaiCN[i,j]
        x_train = x_train/33.
        pred = modelkotsu.predict(x_train, batch_size=1, verbose=1)
        pred_label = label[np.argmax(pred[0])]
        kotsuYN[i+data,j] = np.argmax(pred[0])

modelkokushi = load_model('kokushiYN.h5')
kokushiYN = np.zeros((data*2,286))#国士YNの結果を入れる
for i in range(data):#tehaiCを国士YNにかける
    for j in range(286):
        x_train = np.zeros((1,3))
        x_train[0,] = tehaiC[i,j]
        x_train = x_train/33.
        pred = modelkokushi.predict(x_train, batch_size=1, verbose=1)
        pred_label = label[np.argmax(pred[0])]
        kokushiYN[i,j] = np.argmax(pred[0])
for i in range(data):
    for j in range(286):#tehaiCNを国士YNにかける
        x_train = np.zeros((1,3))
        x_train[0,] = tehaiCN[i,j]
        x_train = x_train/33.
        pred = modelkokushi.predict(x_train, batch_size=1, verbose=1)
        pred_label = label[np.argmax(pred[0])]
        kokushiYN[i+data,j] = np.argmax(pred[0])

YN3 = np.zeros((data*2,858))
for i in range(data*2):
    ShunKotYN = np.hstack((ShuntsYN[i,],kotsuYN[i,]))
    SKKYN = np.hstack((ShunKotYN,kokushiYN[i,]))
    YN3[i,] = SKKYN
#print(YN3[0,])
#print(YN3.shape)

train = np.zeros((data*2,859))
for i in range(data):
    x = np.append(YN3[i,],1)
    train[i,] = x

for i in range(data):
    x = np.append(YN3[i+data,],0)
    train[i+data,] = x

np.random.shuffle(train)
lavel = np.zeros((data*2,1))

for i in range(data*2):
    if train[i,858] == 1:
        lavel[i,0] = 1
    else:
        lavel[i,0] = 0

train=np.delete(train,858,1)
lavel = to_categorical(lavel,2)
#trainが学習データ
#lavelが正解ラベル

model = Sequential()

#中間層、入力層、活性化関数ReLU関数
model.add(Dense(units=429,input_shape=(858,),activation='relu'))
#出力層2、活性化関数ソフトマックス関数
model.add(Dense(units=2,activation='softmax'))

#最適化アルゴリズムAdam、損失関数クロスエントロピー
model.compile(
    optimizer=Adam(lr=0.005),
    loss='categorical_crossentropy',
    metrics=['accuracy'],
)

history_adam=model.fit(
    train,
    lavel,
    batch_size=100,
    epochs=50,
    verbose=1,
    shuffle = True,
    validation_split=0.2
)
model.save('tenpaiYN.h5')

t2 = time.time()
elapsed_time = t2-t1
print(f"経過時間:{elapsed_time}")

mode.fitのshuffleはHDF5データだけに使える

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0