import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
iris = sns.load_dataset("iris")
iris.head()
sns.set()
sns.pairplot(iris, hue="species");
plt.show()
Les deux variables explicatives qui semblent le mieux séparer les espèces sont sepal_with
et petal_length
X = iris.values[:,1:3]
y = iris.values[:,4]
X_train = X[:90]
y_train = y[:90]
X_test = X[90:]
y_test = y[90:]
Les données X
et y
n'étaient pas mélangées: les espèces sont regroupées. En particulier, l'échantillon de test ne contient quasiment que des espèces virginica, alors que l'échantillon d'apprentissage ne contient aucune espèce virginica. Cela fausserait donc et l'apprentissage et le test. Il faut donc au préalable mélanger le jeu de données.
from sklearn.utils import shuffle
X, y = shuffle(X,y)
X_train = X[:90]
y_train = y[:90]
X_test = X[90:]
y_test = y[90:]
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)
print(knn.score(X_train,y_train))
print(knn.score(X_test,y_test))
Le score empirique mesure la proportion de bonnes prédictions, alors que le risque empirique mesure la proportion de mauvaises prédictions (lorsqu la fonction de perte considérée est la perte 0-1). Donc: score = 1 - risque empirique
knn = {}
score_train = []
score_test = []
k_range = range(1,21)
for k in k_range:
knn[k] = KNeighborsClassifier(n_neighbors=k)
knn[k].fit(X_train,y_train)
score_train.append(knn[k].score(X_train,y_train))
score_test.append(knn[k].score(X_test,y_test))
plt.plot(list(k_range),score_train)
plt.plot(list(k_range),score_test)
plt.show()
La valeur $k=5$ semble ici donner le meilleur score de test.
def best_knn_score(X,y):
k_range=range(1,21)
score_test = []
X, y = shuffle(X,y)
X_train = X[:90]
y_train = y[:90]
X_test = X[90:]
y_test = y[90:]
for k in k_range:
knn = KNeighborsClassifier(n_neighbors=k)
knn.fit(X_train,y_train)
score_test.append(knn.score(X_test,y_test))
return max(score_test)
print(best_knn_score(X,y))
print(best_knn_score(X,y))
print(best_knn_score(X,y))
Le résultat est différent à chaque fois. Cela est dû à au mélange aléatoire des données par shuffle(X,y)
.
def best_knn_score_avg(X,y):
scores = []
for i in range(100):
scores.append(best_knn_score(X,y))
return np.mean(scores)
print(best_knn_score_avg(X,y))
X_ = X.copy()
X_[:,0] = X_[:,0]/100
print(best_knn_score_avg(X_,y))
Le score reste similaire
X_ = X.copy()
X_[:,1] = X_[:,1]/100
print(best_knn_score_avg(X_,y))
Le score est cette fois-ci détérioré.
from sklearn import preprocessing
X_scaled = preprocessing.scale(X)
print(best_knn_score_avg(X_scaled,y))
En l'occurence, cela n'améliore pas le score, il est même légèrement détérioré.
X = iris.values[:,0:4]
y = iris.values[:,4]
print(best_knn_score_avg(X,y))
Le score est meilleur.