ポケモン機械学習　N番煎じ

#はじめに

機械学習をしてみたいと思って、選ばれたのが『ポケモン』でした。
ポケモンは種族値がポケモンごとに決まっているので、データの宝石箱だと考えました。

しかし、今回はGoogleで『ポケモン　機械学習』で検索してトップに出てきた人のものを参考にした<b>完全下位互換</b>記事なので、真似したい方は是非元記事をご参照ください。
[ポケモンで学ぶ機械学習](https://qiita.com/Alesion30/items/08a1bd69c93ee120df6b)

#環境

OS:Win10 home
IDE:VScode
言語:python 3.7.3 64bit

#やったこと

[7世代までのポケモンのデータベース](http://rikapoke.hatenablog.jp/entry/pokemon_datasheet_gne7)を元に、『ひこう』、『エスパー』のポケモンを抽出して、ロジスティック回帰で二値分類させてみました。
ちなみに、ポケモンにおける各タイプの数は以下（7世代まで）

|タイプ|匹数|
|:---:|:---:|
|ノーマル|116匹|
|かくとう|63匹|
|どく|69匹|
|じめん|75匹|
|ひこう|113匹|
|むし|89匹|
|いわ|67匹|
|ゴースト|55匹|
|はがね|58匹|
|ほのお|72匹|
|みず|141匹|
|でんき|60匹|
|くさ|103匹|
|こおり|43匹|
|エスパー|100匹|
|ドラゴン|59匹|
|あく|59匹|
|フェアリー|54匹|

みずが最多で、こおりが最小でしたね。フリーズドライで倍返しですね。

Codeは以下です。

```python:lr_pokemon.py

import pandas as pd
import codecs
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt


# read data by pandas
with codecs.open("data/pokemon_status.csv", "r", "Shift-JIS", "ignore") as file:
    df = pd.read_table(file, delimiter=",")

# print(df.head(15))

p_type = ["ノーマル","かくとう","どく","じめん","ひこう","むし","いわ","ゴースト","はがね","ほのお","みず","でんき","くさ","こおり","エスパー","ドラゴン","あく","フェアリー"]
print(len(p_type))

# make functions
def count_type(p_type):
    list1 = df[df['タイプ１'] == p_type]
    list2 = df[df['タイプ２'] == p_type]
    lists = pd.concat([list1, list2])
    print(p_type + "のポケモン: %d匹" % len(lists))

def type_to_num(p_type):
    if p_type == "ひこう":
        return 1
    else:
        return 0

# count number of type in pokemons
for i in p_type:
    count_type(i)

# make sky_df
sky1 = df[df['タイプ１'] == "ひこう"]
sky2 = df[df['タイプ２'] == "ひこう"]
sky = pd.concat([sky1, sky2])

# make psycho_df
psycho1 = df[df['タイプ１'] == "エスパー"]
psycho2 = df[df['タイプ２'] == "エスパー"]
psycho = pd.concat([psycho1, psycho2])

df_s_p = pd.concat([sky, psycho], ignore_index=True)

type1 = df_s_p['タイプ１'].apply(type_to_num)
type2 = df_s_p['タイプ２'].apply(type_to_num)
df_s_p['type_num'] = type1 + type2

print(df_s_p)

X = df_s_p.iloc[:,7:13].values
y = df_s_p['type_num'].values

X_train,X_test,y_train,y_test = train_test_split(X, y, test_size = 0.3, random_state = 0)

lr = LogisticRegression(C = 1.0)
lr.fit(X_train, y_train)
# show scores
print("train_score: %.3f" % lr.score(X_train, y_train))
print("test_score: %.3f" % lr.score(X_test, y_test))

i = 0
error1 = 0
success1 = 0
error2 = 0
success2 = 0
print("[ひこうタイプと判断したポケモン一覧]")
print("----------------------------------------")
print("")
while i < len(df_s_p):
    y_pred = lr.predict(X[i].reshape(1, -1))
    if y_pred == 1:
        print(df_s_p.loc[i, ["ポケモン名"]])
        if df_s_p.loc[i, ["type_num"]].values == 1:
            success1 += 1
            print("ひこうタイプですよね")
            print("")
        else:
            error1 += 1
            print("ひこうタイプやと思ってしまいました")
            print("")
    else:
        print(df_s_p.loc[i, ["ポケモン名"]])
        if df_s_p.loc[i, ["type_num"]].values == 0:
            error2 += 1
            print("エスパータイプですよね")
            print("")
        else:
            success2 += 1
            print("エスパータイプやと思ってしましました")
            print("")
    i += 1
print("----------------------------------------")
print("正しくひこうタイプと判断したポケモンの数: %d匹" % success1)
print("正しくエスパータイプと判断したポケモンの数: %d匹" % success2)
print("誤ってひこうタイプと判断したポケモンの数: %d匹" % error1)
print("誤ってエスパータイプと判断したポケモンの数: %d匹" % error2)
print("")




```

#結果

結果は正答率75%でした。低いですね。機械学習では使えない数値でした。

私はもっと良い数字がでると思ったんですけどね。なぜなら『ひこう』なら物理アタッカー、『エスパー』なら特殊アタッカーと大まかに分けられるかなと思ったからです。現実はそんなに単純ではありませんね。
とはいえ、実際に誤検知されたポケモンを見ると私でも誤検知してしまうなーという理由が得られました。
例えば、ひこうなのにエスパーと間違えられた子として『サンダー』、『フリーザー』がいたのですが、とくこうが高いのでそりゃそうよな。俺でも初見なら間違えるわ、となりました。
逆に、エスパーなのにひこうと間違えられた子として『ケーシィ』、『ラルトス』がいたのですが、これは低種族値なので仕方ないかなと思いました。低種族値帯では数値に差がつきにくいので。
進化系の『フーディン』や『サーナイト』、『エルレイド』はばっこしエスパーに割り振られていたので安心です。

<br>
<br>
<br>
ん？？
<br>
<br>
<br>
![erureido.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208060/08320895-7b06-30f7-e6c0-c5a2080413b6.jpeg)

エルレイドはんっ！
あんたはひこうタイプに間違われても良かったんちゃいまっか！！！

#おわりに
やはり種族値だけでポケモンを判断するのは間違っている　完