刻子と順子と国士無双の部品のYNニューラルネットワークの中間層を主成分分析した

# ※この記事は2020年に作成しました
#概要
3つの牌が、それぞれ刻子YNと、順子YNと、国士無双の部品YNの中間層の出力を得て、それを主成分分析して可視化した。
それぞれのニューラルネットワークは入力が102次元とし、中間層は51次元とした。

#結果
##ニューラルネットワークの結果
刻子YNと国士無双の部品YNの精度は100%、順子YNは99.99％となった。

##第一主成分と第二主成分の散布図
![3class_pca.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436155/aa12a6ef-88a8-a6d2-8e81-9f2ee4730afb.png)

##寄与度
![3class_kiyodo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436155/7b40bef5-d571-06e2-2e01-a7687aa672a0.png)

##累積寄与率
![3class_ruiseki.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436155/1019b0dd-0702-2383-b0bd-67ca62bff497.png)


#作成したプログラム
##刻子YN
```python
# coding: UTF-8
import csv
import numpy as np
from keras.utils import to_categorical
from keras.models import Sequential,Model
from keras.layers import Dense,Input
from keras.optimizers import Adam
import random
from keras.callbacks import TensorBoard
import sklearn
from sklearn.preprocessing import StandardScaler
np.set_printoptions(threshold=100000)

num = 150000
x_train = np.zeros((num,3)) # x_trainはランダムな学習データ
for i in range(len(x_train)):
    x_train[i,0] = random.randrange(0,33)
    x_train[i,1] = random.randrange(0,33)
    x_train[i,2] = random.randrange(0,33)
x_train = np.sort(x_train, axis=1)

y_train = np.zeros((num,3)) # y_trainは刻子の学習データ
for i in range(len(y_train)):
    x = random.randrange(0,33)
    y_train[i,0] = x
    y_train[i,1] = x
    y_train[i,2] = x

#x_trainとy_trainを結合し、シャッフルして学習データの完成　データ数はnumの2倍になる
train = np.vstack((x_train,y_train))
np.random.shuffle(train)

#正解ラベルを付ける
lavel = np.zeros((len(train),1))
for i in range(len(train)):
    if train[i,0] == train[i,1] == train[i,2]:
        lavel[i,0] = 1

x_train2 = np.zeros((len(train),102))#trainを3次元から34×2=102次元へ（one-hot表現）
for i in range(len(train)):
    x_train2[i,int(train[i,0])] = 1
    x_train2[i,int(train[i,1]+34)] = 1
    x_train2[i,int(train[i,2]+68)] = 1


#trainは学習データ
#lavelは正解ラベル

lavel = to_categorical(lavel,2)

model = Sequential()

input_data = Input(shape=(102,))#入力層
hidden_layer = Dense(51, activation='relu')(input_data)#中間層
output_layer = Dense(2, activation='softmax')(hidden_layer)#出力層
Hidden_output = Model(input = input_data , output = hidden_layer) #中間出力用
model = Model(input = input_data , output = output_layer)#入力から出力

#最適化アルゴリズムAdam、損失関数
model.compile(
    optimizer=Adam(lr=0.01),
    loss='categorical_crossentropy',
    metrics=['accuracy'],
)
#http://localhost:6006/
#tensorboard --logdir=./logs
tsb = TensorBoard(log_dir='./logs')
history_adam=model.fit(
    x_train2,
    lavel,
    batch_size=256,
    epochs=10,
    verbose=1,
    shuffle = True,
    validation_split=0.3,
    callbacks=[tsb]
)
#model.save('shuntsYN.h5')

HDo = Hidden_output.predict(x_train2)
ss = sklearn.preprocessing.StandardScaler()
HDo_ss = ss.fit_transform(HDo)
np.savetxt('C:/Users/p-user/Desktop/csvdata/kotsu_pca.csv', HDo_ss)
```

##順子YN
```python
# coding: UTF-8
import csv
import numpy as np
from keras.utils import to_categorical
from keras.models import Sequential,Model
from keras.layers import Dense,Input
from keras.optimizers import Adam
import random
from keras.callbacks import TensorBoard
import sklearn
from sklearn.preprocessing import StandardScaler
np.set_printoptions(threshold=100000)

num = 150000
x_train = np.zeros((num,3)) # x_trainはランダムな学習データ
for i in range(len(x_train)):
    x_train[i,0] = random.randrange(0,33)
    x_train[i,1] = random.randrange(0,33)
    x_train[i,2] = random.randrange(0,33)
x_train = np.sort(x_train, axis=1)

y_train = np.zeros((num,3)) # y_trainは順子の学習データ
for i in range(len(y_train)):
    x = random.randrange(0,24)
    while x==7 or x==8 or x==16 or x==17:
        x = random.randrange(0,24)
    #if x!=7 and x!=8 and x!=16 and x!=17 and x!=25 and x!=26 and x<=27:
    y_train[i,0] = x
    y_train[i,1] = x + 1
    y_train[i,2] = x + 2

#x_trainとy_trainを結合し、シャッフルして学習データの完成　データ数はnumの2倍になる
train = np.vstack((x_train,y_train))
np.random.shuffle(train)

#正解ラベルを付ける
lavel = np.zeros((len(train),1))
for i in range(len(train)):
    if train[i,0]!=7 and train[i,0]!=8 and train[i,0]!=16 and train[i,0]!=17 and train[i,0]<=24\
        and train[i,0]==(train[i,1]-1)==(train[i,2]-2):
        lavel[i,0] = 1

x_train2 = np.zeros((len(train),102))#trainを3次元から34×2=102次元へ（one-hot表現）
for i in range(len(train)):
    x_train2[i,int(train[i,0])] = 1
    x_train2[i,int(train[i,1]+34)] = 1
    x_train2[i,int(train[i,2]+68)] = 1


#trainは学習データ
#lavelは正解ラベル

lavel = to_categorical(lavel,2)

model = Sequential()

input_data = Input(shape=(102,))#入力層
hidden_layer = Dense(51, activation='relu')(input_data)#中間層
output_layer = Dense(2, activation='softmax')(hidden_layer)#出力層
Hidden_output = Model(input = input_data , output = hidden_layer) #中間出力用
model = Model(input = input_data , output = output_layer)#入力から出力

#最適化アルゴリズムAdam、損失関数
model.compile(
    optimizer=Adam(lr=0.01),
    loss='categorical_crossentropy',
    metrics=['accuracy'],
)
#http://localhost:6006/
#tensorboard --logdir=./logs
tsb = TensorBoard(log_dir='./logs')
history_adam=model.fit(
    x_train2,
    lavel,
    batch_size=256,
    epochs=10,
    verbose=1,
    shuffle = True,
    validation_split=0.3,
    callbacks=[tsb]
)
#model.save('shuntsYN.h5')

HDo = Hidden_output.predict(x_train2)
ss = sklearn.preprocessing.StandardScaler()
HDo_ss = ss.fit_transform(HDo)
np.savetxt('C:/Users/p-user/Desktop/csvdata/shunts_pca.csv', HDo_ss)
```

##国士無双の部品YN
```python
# coding: UTF-8
import csv
import numpy as np
from keras.utils import to_categorical
from keras.models import Sequential,Model
from keras.layers import Dense,Input
from keras.optimizers import Adam
import random
from keras.callbacks import TensorBoard
import sklearn
from sklearn.preprocessing import StandardScaler
np.set_printoptions(threshold=100000)

num = 150000
x_train = np.zeros((num,3)) # x_trainはランダムな学習データ
for i in range(num):
    x_train[i,0] = random.randrange(0,33)
    x_train[i,1] = random.randrange(0,33)
    x_train[i,2] = random.randrange(0,33)
x_train = np.sort(x_train, axis=1)

y_train = np.zeros((num,3))# y_trainは国士の部品になる学習データ
for i in range(num):
    for j in range(3):
        x = random.randrange(0,33)
        while 1<=x<=7 or 10<=x<=16 or 19<=x<=25:
            x = random.randrange(0,33)
        y_train[i,j] = x

#x_trainとy_trainを結合し、シャッフルして学習データの完成　データ数はnumの2倍になる
train = np.vstack((x_train,y_train))
np.random.shuffle(train)

#正解ラベルを付ける
lavel = np.zeros((len(train),1))
for i in range(len(train)):
    cnt = 0
    for j in range(3):
        if train[i,j]==0 or train[i,j]==8 or train[i,j]==9 or train[i,j]==17 or\
            train[i,j]==18 or train[i,j]>=26:
            cnt += 1
    if cnt==3:
        lavel[i,0]=1

x_train2 = np.zeros((len(train),102))#trainを3次元から34×2=102次元へ（one-hot表現）
for i in range(len(train)):
    x_train2[i,int(train[i,0])] = 1
    x_train2[i,int(train[i,1]+34)] = 1
    x_train2[i,int(train[i,2]+68)] = 1


#trainは学習データ
#lavelは正解ラベル

lavel = to_categorical(lavel,2)

model = Sequential()

input_data = Input(shape=(102,))#入力層
hidden_layer = Dense(51, activation='relu')(input_data)#中間層
output_layer = Dense(2, activation='softmax')(hidden_layer)#出力層
Hidden_output = Model(input = input_data , output = hidden_layer) #中間出力用
model = Model(input = input_data , output = output_layer)#入力から出力

#最適化アルゴリズムAdam、損失関数
model.compile(
    optimizer=Adam(lr=0.01),
    loss='categorical_crossentropy',
    metrics=['accuracy'],
)
#http://localhost:6006/
#tensorboard --logdir=./logs
tsb = TensorBoard(log_dir='./logs')
history_adam=model.fit(
    x_train2,
    lavel,
    batch_size=256,
    epochs=10,
    verbose=1,
    shuffle = True,
    validation_split=0.3,
    callbacks=[tsb]
)
#model.save('shuntsYN.h5')

HDo = Hidden_output.predict(x_train2)
ss = sklearn.preprocessing.StandardScaler()
HDo_ss = ss.fit_transform(HDo)
np.savetxt('C:/Users/p-user/Desktop/csvdata/kokushi_pca.csv', HDo_ss)
```

##主成分分析
```python
# coding: UTF-8
import numpy as np
import matplotlib.pyplot as plt
import sklearn #機械学習のライブラリ
from sklearn.decomposition import PCA #主成分分析器
from pandas import plotting 
import matplotlib.ticker as ticker
import pandas as pd
from sklearn.preprocessing import StandardScaler


data = 5000

kotsu = np.loadtxt("C:/Users/p-user/Desktop/csvdata/kotsu_pca.csv")
kotsu = np.delete(kotsu,slice(data,None),0)
shunts = np.loadtxt("C:/Users/p-user/Desktop/csvdata/shunts_pca.csv")
shunts = np.delete(shunts,slice(data,None),0)
kokushi = np.loadtxt("C:/Users/p-user/Desktop/csvdata/kokushi_pca.csv")
kokushi = np.delete(kokushi,slice(data,None),0)

df1  = np.vstack((kotsu,shunts))
df  = np.vstack((df1,kokushi))
#print(df.shape)


pca = PCA()
feature = pca.fit(df)
# データを主成分空間に写像
feature = pca.transform(df)
#主成分得点
pd.DataFrame(feature, columns=["PC{}".format(x + 1) for x in range(51)]).head()


#累積寄与率をプロット
plt.gca().get_xaxis().set_major_locator(ticker.MaxNLocator(integer=True))
plt.plot([0] + list( np.cumsum(pca.explained_variance_ratio_)), "-o")
plt.xlabel("Number of principal components")
plt.ylabel("Cumulative contribution rate")
plt.grid()
plt.show()



"""# 第一主成分と第二主成分における観測変数の寄与度をプロットする
plt.figure(figsize=(6, 6))
for x, y, name in zip(pca.components_[0], pca.components_[1], range(100)):
    plt.text(x, y, name)
    #print(x,y,name)

plt.scatter(pca.components_[0], pca.components_[1], alpha=0.8)
plt.grid()
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.show()
"""

"""
#第一主成分と第二主成分の散布図
plt.figure(figsize=(6, 6))
plt.scatter(feature[:4999, 0], feature[:4999, 1], alpha=0.5, c='red', label='Kotsu')
plt.scatter(feature[5000:9999, 0], feature[5000:9999, 1], alpha=0.5, c='blue', label='Shuntsu')
plt.scatter(feature[10000:14999, 0], feature[10000:14999, 1], alpha=0.5, c='green', label='Kokushi')
plt.grid(True)
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.legend(loc='upper left')
plt.show()
"""
```