
ゆうき( @BASEBALLY15 )です^^
機械学習で「テストデータを20(30)%,学習データを80(70)%に分ける」 って言うけど,なぜ,こんな分け方をするの・・・?
その悩みを解決するために,今回は,テストデータが何%の時に精度が最も良いのか,ということについて検証します^^
よろしくお願いします・・・
(Jupiter notebookを使用)

検証する際に使ったアルゴリズム
以下の4つのアルゴリズムを使い,それぞれのテストデータの精度を検証しました.
- LinearSVC(サポートベクタークラシファー)
- LogisticRegression(ロジスティック回帰)
- RandomForestClassifier(ランダムフォレスト)
- KNeighborsClassifier(k近傍法)
それでは,検証結果を見ていきましょう^^
テストデータを何%にするのがベストなのか?
ライブラリ
import numpy as np
import pandas as pd
from pandas import Series, DataFrame
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style("whitegrid")
%matplotlib inline
そして,以下のコードを記述し,今回の検証で使うアルゴリズムをインポートしたいと思います.
あと,データを分割するライブラリと精度を求めるためのライブラリも追加しておきます.
#LinearSVCを使うためのライブラリ
from sklearn.svm import LinearSVC
#ランダムフォレスターを使うためのライブラリ
from sklearn.ensemble import RandomForestClassifier
#ロジスティック回帰を使うためのライブラリ
from sklearn.linear_model import LogisticRegression
#k近傍法を使うためのライブラリを用意
from sklearn.neighbors import KNeighborsClassifier
#学習用とテスト用に分けるためのライブラリ
from sklearn.model_selection import train_test_split
#精度を求めるためのライブラリ
from sklearn.metrics import accuracy_score
コード
今回の検証では,seabornのアイリスのデータを使いたいと思います.

まずは,データを読み込みたいと思います.
#seabornのirisのデータを読み込む
iris = sns.load_dataset("iris")
#実行
iris
すると,以下のデータフレームが表示されます.
sepal_length | sepal_width | petal_length | petal_width | species | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | setosa |
1 | 4.9 | 3.0 | 1.4 | 0.2 | setosa |
2 | 4.7 | 3.2 | 1.3 | 0.2 | setosa |
3 | 4.6 | 3.1 | 1.5 | 0.2 | setosa |
4 | 5.0 | 3.6 | 1.4 | 0.2 | setosa |
… | … | … | … | … | … |
145 | 6.7 | 3.0 | 5.2 | 2.3 | virginica |
146 | 6.3 | 2.5 | 5.0 | 1.9 | virginica |
147 | 6.5 | 3.0 | 5.2 | 2.0 | virginica |
148 | 6.2 | 3.4 | 5.4 | 2.3 | virginica |
149 | 5.9 | 3.0 | 5.1 | 1.8 | virginica |
次に,予測に使うデータX(説明変数)と予測したいデータY(目的変数)に分けます.
#予測に使うデータX(説明変数)
X = iris.drop("species", axis=1)
#予測したいデータY(目的変数)
Y = iris["species"]
dropを使うことで,”species”以外のデータを使うことが出来ます.
また,“species”, axis=1は,” species “の列方向を指定しています.
テストデータ20%から80%までの精度を検証
次に,テストデータの精度を20%から80%の間で検証したいので, for文を使います.
そのために,繰り返す範囲を指定します.
#繰り返し範囲を指定(20%から80%を1%ずつ繰り返す)
all_range = range(20,81,1)
#精度を表示させるためにリストを用意
###LinearSVC###
linear_accuracy = []
###ロジスティック回帰###
log_accuracy = []
###ランダムフォレスター###
random_accuracy = []
###k近傍法###
kn_accuracy = []
そして,4つのアルゴリズムごとに機械学習を行っていきます.
for i in all_range:
#学習用とテスト用に分ける
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=i/100)
###LinearSVC###
#学習
linearmodel = LinearSVC()
linearmodel.fit(X_train, Y_train)
#予測
Y_pred1 = linearmodel.predict(X_test)
linear_accuracy.append(accuracy_score(Y_pred1, Y_test))
###ロジスティック回帰###
#学習
logmodel = LogisticRegression()
logmodel.fit(X_train, Y_train)
#予測
Y_pred2 = logmodel.predict(X_test)
log_accuracy.append(accuracy_score(Y_pred2, Y_test))
###ランダムフォレスター###
#学習
ranmodel = RandomForestClassifier()
ranmodel.fit(X_train, Y_train)
#予測
Y_pred3 = ranmodel.predict(X_test)
random_accuracy.append(accuracy_score(Y_pred3, Y_test))
###k近傍法###
#学習
knmodel = KNeighborsClassifier(n_neighbors=1)
knmodel.fit(X_train, Y_train)
#予測
Y_pred4 = knmodel.predict(X_test)
kn_accuracy.append(accuracy_score(Y_pred4, Y_test))
データフレーム化して,それぞれのアルゴリズムの精度を見てみましょう^^
#データフレーム化
df = pd.DataFrame([linear_accuracy, log_accuracy, random_accuracy, kn_accuracy],
index=["LinearSVC", "LogisticRegression", "RandomForestClassifier", "KNeighborsClassifier"],
columns=[i for i in all_range])
#行と列を入れ替えて表示(Tと記述すると,入れ替えることが出来る)
df.T
すると,以下のように,それぞれの精度が表示されます.
LinearSVC | LogisticRegression | RandomForestClassifier | KNeighborsClassifier | |
---|---|---|---|---|
20 | 0.966667 | 0.933333 | 0.933333 | 0.966667 |
21 | 0.937500 | 0.968750 | 0.968750 | 0.968750 |
22 | 0.969697 | 1.000000 | 0.969697 | 0.969697 |
23 | 0.942857 | 1.000000 | 0.971429 | 0.942857 |
24 | 0.972222 | 1.000000 | 0.972222 | 0.972222 |
… | … | … | … | … |
76 | 0.885965 | 0.947368 | 0.947368 | 0.956140 |
77 | 0.896552 | 0.913793 | 0.913793 | 0.887931 |
78 | 0.863248 | 0.940171 | 0.931624 | 0.948718 |
79 | 0.966387 | 0.941176 | 0.924370 | 0.949580 |
80 | 0.891667 | 0.933333 | 0.950000 | 0.925000 |
このままでは,どのアルゴリズムと何%のアルゴリズムがベストなのかが分からないので,
精度が98%以上のデータのみを表示させます.
#精度が98%以上のデータのみを表示
all_max = df.T[df.T>=0.98].dropna(how="all", axis=0)
#実行
all_max
すると,このように精度が98%以上のデータだけが表示されます.(NaNは精度が98%よりも低い値です.)
LinearSVC | LogisticRegression | RandomForestClassifier | KNeighborsClassifier | |
---|---|---|---|---|
22 | NaN | 1.000000 | NaN | NaN |
23 | NaN | 1.000000 | NaN | NaN |
24 | NaN | 1.000000 | NaN | NaN |
26 | NaN | 1.000000 | 1.000000 | 1.000000 |
28 | 1.000000 | 1.000000 | 1.000000 | 1.000000 |
29 | NaN | 1.000000 | NaN | NaN |
34 | NaN | 1.000000 | NaN | NaN |
36 | 0.981481 | 0.981481 | NaN | NaN |
37 | 1.000000 | 0.982143 | 0.982143 | NaN |
40 | NaN | 0.983333 | NaN | 0.983333 |
42 | 1.000000 | NaN | NaN | NaN |
47 | 0.985915 | 1.000000 | 1.000000 | 1.000000 |
50 | NaN | NaN | 0.986667 | NaN |
51 | 0.987013 | 0.987013 | NaN | NaN |
53 | NaN | 0.987500 | NaN | NaN |
56 | NaN | 0.988235 | NaN | NaN |
73 | NaN | 0.981818 | NaN | NaN |
これを見ると,テストデータが28%の時,どのアルゴリズムでも精度が100%になっています!
(※実行するたびに精度は変わります.)
最後に,今回の検証結果を可視化したいと思います.
#subplot()の間隔の調整
plt.subplots_adjust(wspace=0.4, hspace=0.6)
###LinearSVCをプロット###
plt.subplot(2,2,1)
plt.plot(all_range, linear_accuracy, color="red")
plt.title("LinearSVC")
plt.ylabel("accuracy")
plt.xlabel("range")
#軸の範囲を指定
plt.xlim(20,80)
plt.ylim(0.85,1.0)
###ロジスティック回帰をプロット###
plt.subplot(2,2,2)
plt.plot(all_range, log_accuracy, color="blue")
plt.title("LogisticRegression")
plt.ylabel("accuracy")
plt.xlabel("range")
plt.xlim(20,80)
plt.ylim(0.85,1.0)
###ランダムフォレスターをプロット###
plt.subplot(2,2,3)
plt.plot(all_range,random_accuracy, color="green")
plt.title("RandomForestClassifier")
plt.ylabel("accuracy")
plt.xlabel("range")
plt.xlim(20,80)
plt.ylim(0.85,1.0)
###k近傍法をプロット###
plt.subplot(2,2,4)
plt.plot(all_range, kn_accuracy, color="purple")
plt.title("KNeighborsClassifier")
plt.ylabel("accuracy")
plt.xlabel("range")
plt.xlim(20,80)
plt.ylim(0.85,1.0)
すると,このように,それぞれのアルゴリズムの精度が表示されます.

この結果を見ると,テストデータが30%周辺で,精度が良いことが分かります.
使うデータによって,テストデータを何%にするのかを考えないといけないですね^^
終わりに
今回は,テストデータが何%の時に最も精度が良いのかということについて検証してみました.
今後も,Pythonを勉強していて疑問に感じたことは,どんどん解決していこうと思います^^
それでは・・・