Elsaの技術日記(徒然なるままに)

主に自分で作ったアプリとかの報告・日記を記載

MENU

ポケモンステータスからタイプを識別してみる Keras編

先日までkerasで2値や多値分類を行ってきました。
elsammit-beginnerblg.hatenablog.com
elsammit-beginnerblg.hatenablog.com

今回はkerasでポケモンのステータスからタイプを分類してみたいと思います。
このタイプ分類ですが、すでにロジスティック回帰などで実施していますが、
kerasだとどれだけ性能が上がるのか確認したく実施してみました!!
elsammit-beginnerblg.hatenablog.com



■利用データ

利用したポケモンのデータですが、こちらに格納されたデータを用いております。
https://drive.google.com/file/d/0Bx6uOB0FHuuSMXdOclZXTHhhSUE/view

■分類内容

今回は、
・ノーマルタイプ
・はがねタイプ
のどちらのタイプなのか分類してみたいと思います。

■データ加工

すでに前回のブログでまとめておりましたが、念のためこちらで再度まとめておきたいと思います。

先ほどのデータはこちらのようにステータスと名前が列として用意されておりました。
f:id:Elsammit:20210408230232p:plain

こちらのリストからノーマルタイプとはがねタイプを抽出。

poketype2 = "ノーマル"
poketype3 = "はがね"

with codecs.open("/kaggle/input/pokemon-status/pokemon_status.csv", "r", "utf-8", "ignore") as file:
    df = pd.read_table(file, delimiter=",")  

nomal1 = df[df['タイプ1'] == poketype2]
nomal2 = df[df['タイプ2'] == poketype2]
normal = pd.concat([normal1,normal2])

aian1 = df[df['タイプ1'] == poketype3]
aian2 = df[df['タイプ2'] == poketype3]
aian = pd.concat([aian1,aian2])

次にノーマルタイプかはがねタイプかの判定を行うためのフラグをデータの末尾に追加します。

def type_to_num(p_type,typ):
    if p_type == typ:
        return 0
    else:
        return 1

pokemon_m_n = pd.concat([normal, aian], ignore_index=True)
type1 = pokemon_m_n["タイプ1"].apply(type_to_num, typ=poketype3)
type2 = pokemon_m_n["タイプ2"].apply(type_to_num, typ=poketype3)
pokemon_m_n["type_num"] = type1*type2
pokemon_m_n.head()

上記コードを組み合わせて実行してみるとこちらのように選択したいタイプが抽出できかつ末尾に判定用のフラグがセットされております。
f:id:Elsammit:20210408231245p:plain

最後にテストデータとトレーニングデータに分類すればデータ加工・準備は完了です。
全体のコードはこちらになります。

import pandas as pd
from pandas import plotting  
import codecs
import numpy as np

def type_to_num(p_type,typ):
    if p_type == typ:
        return 0
    else:
        return 1
    
poketype2 = "ノーマル"
poketype3 = "はがね"

df = pd.read_csv("pokemon_status.csv")

nomal1 = df[df['タイプ1'] == poketype2]
nomal2 = df[df['タイプ2'] == poketype2]
normal = pd.concat([normal1,normal2])

aian1 = df[df['タイプ1'] == poketype3]
aian2 = df[df['タイプ2'] == poketype3]
aian = pd.concat([aian1,aian2])
    
pokemon_m_n = pd.concat([normal, aian], ignore_index=True)
type1 = pokemon_m_n["タイプ1"].apply(type_to_num, typ=poketype3)
type2 = pokemon_m_n["タイプ2"].apply(type_to_num, typ=poketype3)
pokemon_m_n["type_num"] = type1*type2

X = pokemon_m_n.iloc[:, 7:13].values
y = pokemon_m_n["type_num"].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
pokemon_m_n.head()

■kerasによるポケモンタイプ分類

ではkerasで分類してみます。
今回はノーマルタイプとはがねタイプを分類してみるため、2値分類になります。
そこで、kerasのモデルをこちらのように作成。

#モデルの定義
model = models.Sequential()
model.add(layers.Dense(64, activation="relu", input_shape=(6, )))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(64, activation="relu"))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(1, activation="sigmoid"))

#モデルの構築
model.compile(loss='binary_crossentropy',optimizer='rmsprop',metrics=['accuracy'])

モデルですが、
説明変数は6項目ありますので入力層への入力を6次元に設定。
さらに中間層(隠れ層)を64層用意し、
最後にシグモイド関数により2値分類する
といった構成にしました。

さらにモデルを構築するにあたり、
最適化関数としてrmspropを利用しました。

ではこちらのモデルを用いてポケモンのタイプ分類してみたいと思います。
全体のコードはこちら。

import tensorflow as tf
from sklearn import datasets
from keras.models import Sequential
from keras.layers import Dense, Activation
from matplotlib import pyplot

#モデルの定義
model = models.Sequential()
model.add(layers.Dense(64, activation="relu", input_shape=(6, )))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(64, activation="relu"))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(1, activation="sigmoid"))

#モデルの構築
model.compile(loss='binary_crossentropy',optimizer='rmsprop',metrics=['accuracy'])

#学習の実行
history = model.fit(X_train,y_train,epochs=100)

#エポック毎のaccuracy結果グラフ化
pyplot.plot(history.history['accuracy'])
pyplot.title('model accuracy')
pyplot.ylabel('accuracy')
pyplot.xlabel('epoch')
pyplot.legend(['train', 'test'], loc='upper left')
pyplot.show()
    
#評価の実行
score = model.evaluate(X_test,y_test,batch_size=1)
print(score[0])
print(score[1])

エポック数ですが100を設定しました。
レーニングした結果はこちら。
f:id:Elsammit:20210408232557p:plain

テスト結果ですが、

Loss:0.279
Accuracy:0.908

となりました。
結構高い結果が得られました!!
しかしながら、以前実施したロジスティック回帰の場合には0.943であったので少し悪い結果になってしまいました。。。

■別のタイプで確認してみる
ノーマル、はがねタイプの分類では負けてしまいましたが、、、
ほのお、みずタイプでロジスティック回帰とKerasで比較をおこなってみました。
結果ですが、
【ロジスティック回帰】

testデータに対するscore: 0.738

【Keras】

testデータに対するscore:0.803

といった結果になりタイプによっては性能が高いことが分かりました。

■最後に

タイプによってはKerasの方が性能がよさそうですね。
どんな法則があるのでしょう??
ちょっと後で調べてみたいな!!と思います。