【K近傍法】scikit-learnでアヤメの多クラス分類(iris-dataset)
3種類のアヤメについて、それぞれ50サンプルのデータがあります。 それぞれ、Iris setosa、Iris virginica、Iris versicolorという名前で、全部で150のデータ。
4つの特徴量が計測されていて、これが説明変数。
- 萼片(sepal)の長さ(cm)
- 萼片(sepal)の幅(cm)
- 花びら(petal)の長さ(cm)
- 花びら(petal)の幅(cm)
アヤメの分類は3つのクラス
- Iris-setosa (n=50)
- Iris-versicolor (n=50)
- Iris-virginica (n=50)
特徴量から、それぞれの分類を予測していきます。
データ準備
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 from sklearn import linear_model from sklearn.datasets import load_iris # データの読み込み iris = load_iris() # 説明変数をXに X = iris.data #目的変数をYに Y = iris.target iris_data = DataFrame(X,columns=['Sepal Length','Sepal Width','Petal Length','Petal Width']) iris_target = DataFrame(Y,columns=['Species']) def flower(num): ''' 数字を受け取って、対応する名前を返す''' if num == 0: return 'Setosa' elif num == 1: return 'Veriscolour' else: return 'Virginica' iris_target['Species'] = iris_target['Species'].apply(flower) # 1つのテーブルにまとめる iris = pd.concat([iris_data,iris_target],axis=1) iris.head()
特徴量を可視化
#pairPlot で可視化 sns.pairplot(iris,hue='Species',size=2)
plt.figure(figsize=(12,4)) sns.countplot('Petal Length',data=iris,hue='Species')
plt.figure(figsize=(12,4)) sns.countplot('Petal Width',data=iris,hue='Species')
ロジスティック回帰で予測
ここではロジスティック回帰による分類を簡単に実装してみる。
from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split logreg = LogisticRegression() # テストが全体の40% X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.4,random_state=3) # データを使って学習 logreg.fit(X_train, Y_train) LogisticRegression() # 精度計算 from sklearn import metrics # テストデータを予測 Y_pred = logreg.predict(X_test) # 精度を計算 print(metrics.accuracy_score(Y_test,Y_pred)) 0.9666666666666667
0.9666666666666667 とかなり精度が高い。
次に、K近傍法で予測してみる
K近傍法で予測
K近傍法は英語で、k-nearest neighbor
学習のプロセスは、単純に学習データを保持するだけ。
与えられたサンプルのk個の隣接する学習データのクラスを使い、このサンプルのクラスを予測します。
★が新しいサンプル
これを中心に、 K=3ではAが1つ、Bが2つなので、分類されるクラスは、Bです。 K=6ではAが4つ、Bが2つなので、Aと判別される。
Kの選び方によっては、同数になってしまうことがあるので注意が必要な手法
# K近傍法 from sklearn.neighbors import KNeighborsClassifier # k=3 knn = KNeighborsClassifier(n_neighbors = 3) # 学習 knn.fit(X_train,Y_train) # テストデータを予測 Y_pred = knn.predict(X_test) # 精度 check print(metrics.accuracy_score(Y_test,Y_pred))
→ 0.95
# k=1にしてみる knn = KNeighborsClassifier(n_neighbors = 1) knn.fit(X_train,Y_train) Y_pred = knn.predict(X_test) print(metrics.accuracy_score(Y_test,Y_pred)) 0.9666666666666667
もっとも近いサンプルに合わせて分類すると精度が上がった
kの数値による予測精度の推移を見てみる
# 1~90まで繰り返す k_range = range(1, 90) accuracy = [] for k in k_range: knn = KNeighborsClassifier(n_neighbors=k) knn.fit(X_train, Y_train) Y_pred = knn.predict(X_test) accuracy.append(metrics.accuracy_score(Y_test, Y_pred)) # plot plt.plot(k_range, accuracy) plt.xlabel('K for kNN') plt.ylabel('Testing Accuracy')
kは増やしすぎても精度が下がる
こんな感じで、もっとも精度の高いところを選択するのが良さそう