choix du meilleur K

This commit is contained in:
François Pelletier 2019-03-17 13:18:07 -04:00
parent 4f8da781bf
commit d9fa94a2d6
2 changed files with 64 additions and 25 deletions

View file

@ -32,9 +32,42 @@ class Knn: #nom de la class à changer
c'est à vous d'utiliser vos propres notations
"""
self.k=5
def set_best_k(self, train, train_labels, nb_split, k_potentiel):
## Création des échantillons de validation croisée
shuffle_indices = np.random.permutation([i for i in range(train.shape[0])])
validation_index = np.array_split(shuffle_indices, nb_split)
train_index = []
for i in range(nb_split):
train_index.append(list(set(shuffle_indices)-set(validation_index[i])))
## Itération sur les valeurs de K et sur les échantillons de validation croisée
accuracy_cv = np.empty((len(k_potentiel),nb_split))
for k_index in range(len(k_potentiel)):
for i in range(nb_split):
self.k=k_potentiel[k_index]
self.train(train[train_index[i]], train_labels[train_index[i]], verbose=False)
cm,accuracy,precision,recall = self.test(train[validation_index[i]], train_labels[validation_index[i]], verbose=False)
accuracy_cv[k_index][i] = accuracy
## Calcul de la moyenne
mean_accuracy = accuracy_cv.mean(axis=1)
## Extraction du meilleur K
best_k = k_potentiel[int(min(np.argwhere(mean_accuracy==max(mean_accuracy))))]
## Assignation
self.k=best_k
## Retourner la valeur
return best_k
def train(self, train, train_labels): #vous pouvez rajouter d'autres attribus au besoin
def train(self, train, train_labels, verbose=True): #vous pouvez rajouter d'autres attribus au besoin
"""
c'est la méthode qui va entrainer votre modèle,
train est une matrice de type Numpy et de taille nxm, avec
@ -63,7 +96,7 @@ class Knn: #nom de la class à changer
"""
# on fait seulement utiliser les données du jeu d'entrainement comme paramètre d'un modèle Knn
self.train=train
self.train_set=train
self.train_labels=train_labels
n,m = train.shape
@ -78,9 +111,9 @@ class Knn: #nom de la class à changer
i_range = [i for i in range(n)]
i_range.pop(x)
nn[x,:,0]=i_range[0:self.k]
nn[x,:,1]=np.apply_along_axis(minkowski_distance,1,self.train[i_range[0:self.k]],train[x],self.minkowski_p)
nn[x,:,1]=np.apply_along_axis(minkowski_distance,1,self.train_set[i_range[0:self.k]],train[x],self.minkowski_p)
for i in i_range[self.k:n]:
dist = minkowski_distance(self.train[i],train[x],self.minkowski_p)
dist = minkowski_distance(self.train_set[i],train[x],self.minkowski_p)
nn_dist=nn[x,:,1]
distdiff = nn_dist-dist
max_distdiff=max(distdiff)
@ -95,12 +128,13 @@ class Knn: #nom de la class à changer
# on construit la matrice de confusion
cm = self.confusion_matrix(train_labels,nn_mode_label)
accuracy, precision, recall = self.prediction_metrics(cm,train_labels,nn_mode_label)
self.print_prediction_metrics(cm,accuracy,precision,recall)
if (verbose):
self.print_prediction_metrics(cm,accuracy,precision,recall)
return cm,accuracy,precision,recall
def predict(self, exemple, label):
def predict(self, exemple, label, verbose=True):
"""
Prédire la classe d'un exemple donné en entrée
exemple est de taille 1xm
@ -109,12 +143,12 @@ class Knn: #nom de la class à changer
alors l'exemple est bien classifié, si non c'est une missclassification
"""
n,m = self.train.shape
n,m = self.train_set.shape
nn=np.empty((self.k,2))
nn[:,0]=[i for i in range(self.k)]
nn[:,1]=np.apply_along_axis(minkowski_distance,1,self.train[0:self.k],exemple,self.minkowski_p)
nn[:,1]=np.apply_along_axis(minkowski_distance,1,self.train_set[0:self.k],exemple,self.minkowski_p)
for i in range(self.k,n):
dist = minkowski_distance(self.train[i],exemple,self.minkowski_p)
dist = minkowski_distance(self.train_set[i],exemple,self.minkowski_p)
nn_dist=nn[:,1]
distdiff = nn_dist-dist
max_distdiff=max(distdiff)
@ -125,11 +159,12 @@ class Knn: #nom de la class à changer
nn_labels = self.train_labels[nn[:,0].astype(np.int)]
nn_mode_label = mode(nn_labels)
print("Observé:"+str(label)+" Prédit:"+str(nn_mode_label))
if (verbose):
print("Observé:"+str(label)+" Prédit:"+str(nn_mode_label))
return nn_mode_label
def test(self, test, test_labels):
def test(self, test, test_labels, verbose=True):
"""
c'est la méthode qui va tester votre modèle sur les données de test
l'argument test est une matrice de type Numpy et de taille nxm, avec
@ -152,14 +187,14 @@ class Knn: #nom de la class à changer
"""
n,m = test.shape
n_ex,m_ex = self.train.shape
n_ex,m_ex = self.train_set.shape
nn=np.empty((n,self.k,2))
# Boucle sur chaque ligne du jeu de test
for x in range(n):
nn[x,:,0]=[i for i in range(self.k)]
nn[x,:,1]=np.apply_along_axis(minkowski_distance,1,self.train[0:self.k],test[x],self.minkowski_p)
nn[x,:,1]=np.apply_along_axis(minkowski_distance,1,self.train_set[0:self.k],test[x],self.minkowski_p)
for i in range(self.k,n_ex):
dist = minkowski_distance(self.train[i],test[x],self.minkowski_p)
dist = minkowski_distance(self.train_set[i],test[x],self.minkowski_p)
nn_dist=nn[x,:,1]
distdiff = nn_dist-dist
max_distdiff=max(distdiff)
@ -172,7 +207,8 @@ class Knn: #nom de la class à changer
# on construit la matrice de confusion
cm = self.confusion_matrix(test_labels,nn_mode_label)
accuracy, precision, recall = self.prediction_metrics(cm,test_labels,nn_mode_label)
self.print_prediction_metrics(cm,accuracy,precision,recall)
if (verbose):
self.print_prediction_metrics(cm,accuracy,precision,recall)
return cm,accuracy,precision,recall

View file

@ -19,20 +19,23 @@ En gros, vous allez :
"""
# Initializer vos paramètres
myKnn = Knn.Knn()
# Initializer/instanciez vos classifieurs avec leurs paramètres
# Charger/lire les datasets
train, train_labels, test, test_labels = ld.load_iris_dataset(0.7)
# Initializer vos paramètres
## Choix du meilleur K
findbest_Knn = Knn.Knn()
meilleur_k = findbest_Knn.set_best_k(train, train_labels, nb_split=5, k_potentiel=range(1,16))
print("Le meilleur K est:"+str(meilleur_k)+"\n\n")
# Initializer/instanciez vos classifieurs avec leurs paramètres
myKnn = Knn.Knn()
myKnn.k=meilleur_k
# Entrainez votre classifieur
myKnn.train(train, train_labels)