※この記事は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%前後だった。
#作成したプログラム
# 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データだけに使える