Skip to content
Snippets Groups Projects
Commit 6238306c authored by Cosserat Esteban's avatar Cosserat Esteban
Browse files

Update Rapport.ipynb

parent 3e4b82dc
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags:
# Classification d'Images
[Énoncé du TD]("https://gitlab.ec-lyon.fr/edelland/mod_4_6-td1").
## Introduction
Ce TD a pour objectif d'appliquer les méthodes de classification abordées en cours. Nous allons travailler sur la base de données [CIFAR-10]("https://www.cs.toronto.edu/~kriz/cifar.html"). Dans un premier temps, nous mettrons en œuvre la classification par les k-plus proches voisins en utilisant la distance euclidienne. Ensuite, nous explorerons la classification à l'aide de réseaux de neurones. Pour chaque méthode, nous évaluerons le taux de réussite.
Afin que ce document puisse rester interactif, les fonctions longues à exécuter ont été désactivées et les résultats sont fournis manuellement.
## Importation des Données
Nous importons les bibliothèques nécessaires pour charger et traiter les fichiers.
%% Cell type:code id: tags:
``` python
import numpy as np
import pickle
import os
import matplotlib.pyplot as plt
```
%% Cell type:markdown id: tags:
Nous extrayons ces données et développons des fonctions qui nous permettront de créer des listes d'images d'entraînement et de test à partir de ces données. De plus, nous récupérons les listes de libellés de classe associées à chaque image, ce qui nous permettra d'attribuer un libellé à une image de test et de la comparer ensuite au libellé réel de l'image.
%% Cell type:code id: tags:
``` python
def read_cifar_batch(batch_path):
with open(batch_path, 'rb') as file:
batch_data = pickle.load(file, encoding='bytes')
data = np.array(batch_data[b'data'], dtype=np.float32)
labels = np.array(batch_data[b'labels'], dtype=np.int64)
return data, labels
```
%% Cell type:code id: tags:
``` python
def read_cifar(path_folder):
data = np.empty((0, 3072), dtype=np.float32)
labels = np.empty((0), dtype=np.int64)
for filename in os.listdir(path_folder):
if filename.startswith("data_batch") or filename == "test_batch":
batch_path = os.path.join(path_folder, filename)
d, l = read_cifar_batch(batch_path)
data = np.concatenate((data, d), axis=0)
labels = np.concatenate((labels, l), axis=None)
return(data,labels)
```
%% Cell type:code id: tags:
``` python
def split_dataset(data, labels, split_factor):
num_samples = len(data)
shuffled_indices = np.random.permutation(num_samples)
split_index = int(num_samples * split_factor)
data_train = data[shuffled_indices[:split_index],:]
labels_train = labels[shuffled_indices[:split_index]]
data_test = data[shuffled_indices[split_index:],:]
labels_test = labels[shuffled_indices[split_index:]]
return data_train, labels_train, data_test, labels_test
```
%% Cell type:markdown id: tags:
Afin de vérifier le bon fonctionnement de ces fonctions, nous les appliquons à une liste de 10 images. Nous vérifions que les images d'entraînement et de test sont correctement sélectionnées de manière aléatoire à partir de la base de données.
%% Cell type:code id: tags:
``` python
if __name__ == "__main__":
#read_cifar_batch("data/cifar-10-batches-py/data_batch_1")
d, l = read_cifar("data/cifar-10-batches-py")
print(l[0:10])
d_1, l_1, d_1, l_2 = split_dataset(d[:10,:], l[:10], 0.9)
print(l_1,l_2)
d_1, l_1, d_2, l_2 = split_dataset(d[:10,:], l[:10], 0.9)
print(l_1,l_2)
```
%% Output
[6 9 9 4 1 1 2 7 8 3]
[4 3 7 8 6 9 1 2 1] [9]
[8 9 3 7 6 9 1 4 1] [2]
%% Cell type:markdown id: tags:
Afin de vérifier l'association correcte entre les images et les libellés, l'algorithme suivant affiche les libellés et les images correspondantes, tout en indiquant si chaque image sera utilisée pour l'entraînement du modèle ou pour les tests.
%% Cell type:code id: tags:
``` python
def affichage(d_train, l_train, d_test, l_test):
long, large = 5,2
with open("data/cifar-10-batches-py/batches.meta", 'rb') as file:
batch_data = pickle.load(file, encoding='bytes')
liste_names= np.array(batch_data[b'label_names'])
fig, axes = plt.subplots(large, long, figsize=(12, 5))
fig.subplots_adjust(hspace=0.5)
for i in range(len(l_train)):
im = np.array(np.reshape(d_train[i, 0:3072], (32, 32, 3), order='F'), dtype=np.int64)
im = np.transpose(im, (1, 0, 2))
name=liste_names[l_train[i]]
axes[i // long, i % long].imshow(im)
axes[i // long, i % long].set_title(f"Train : {name.decode('utf-8')}")
axes[i // long, i % long].axis('off')
for i in range(len(l_test)):
im = np.array(np.reshape(d_test[i, 0:3072], (32, 32, 3), order='F'), dtype=np.int64)
im = np.transpose(im, (1, 0, 2))
j = i + len(l_train)
name=liste_names[l_test[i]]
axes[j // long, j % long].imshow(im)
axes[j // long, j % long].set_title(f"Test : {name.decode('utf-8')}")
axes[j // long, j % long].axis('off')
plt.show()
if __name__ == "__main__":
d, l = read_cifar("data/cifar-10-batches-py")
d_1, l_1, d_2, l_2 = split_dataset(d[:10,:], l[:10], 0.5)
affichage(d_1, l_1, d_2, l_2)
```
%% Output
%% Cell type:markdown id: tags:
## Classification par les k Plus Proches Voisins
Dans cette section, nous allons développer un algorithme de classification en utilisant la méthode des k plus proches voisins, choisis en fonction d'une distance euclidienne.
Pour ce faire, nous commençons par écrire la fonction de calcul de distance. Cette fonction prend en entrée les images d'entraînement et de test, et pour chaque image de test, elle calcule sa distance par rapport à chaque image d'entraînement. En plaçant les résultats dans une matrice, nous obtenons une image de test associée à chaque ligne et une image d'entraînement associée à chaque colonne.
Pour une base de données composée de N images d'entraînement et M images de test, la matrice de distances en sortie est la suivante :
| | Image entrainement 1 | ... | Image entrainement n | ... | Image entrainement N |
|------------------|----------------------|-----|----------------------|-----|----------------------|
| Image test 1 | dist(im_e1,im_t1) | ... | dist(im_en,im_t1) | ... | dist(im_eN,im_t1) |
| ... | ... | ... | ... | ... | ... |
| Image test m | dist(im_e1,im_tm) | ... | dist(im_en,im_tm) | ... | dist(im_eN,im_tm) |
| ... | ... | ... | ... | ... | ... |
| Image test M | dist(im_e1,im_tM) | ... | dist(im_en,im_tM) | ... | dist(im_eN,im_tM) |
%% Cell type:code id: tags:
``` python
def distance_matrix(data_train, data_test):
dist_mat=[]
for image_test in data_test:
dist_mat.append([])
for image_train in data_train:
dist_mat[-1].append(np.sum(np.square(image_train-image_test)))
return(np.array(dist_mat))
```
%% Cell type:markdown id: tags:
Avec cette matrice de distances, nous allons rechercher pour chaque ligne (image de test) les k plus petites valeurs de distance et récupérer les libellés des images d'entraînement associés à ces valeurs. Enfin, nous comptons les libellés les plus fréquents dans cette liste pour associer un libellé à l'image de test.
La fonction `knn_predict` prend donc en entrée la matrice de distances, la liste des libellés des images d'entraînement et le nombre k de plus proches voisins considéré, et renvoie en sortie le libellé associé.
%% Cell type:code id: tags:
``` python
def knn_predict(dist, labels_train, k):
resultat=[]
for image_test in dist:
k_max = np.argpartition(image_test, k)[:k]
val, count = np.unique(labels_train[k_max], return_counts=True)
indexe = np.argmax(count)
resultat.append(val[indexe])
return (resultat)
```
%% Cell type:markdown id: tags:
Une dernière fonction va appeler les deux dernières fonctions et comparer les résultats du modèle avec les vrais libellés des images de test. En sortie, nous obtiendrons le taux de réussite du modèle, c'est-à-dire le rapport entre le nombre de classes correctement attribuées et le nombre total de classes testées.
%% Cell type:code id: tags:
``` python
def evaluate_knn(data_train, labels_train, data_test, labels_test, k):
dist_matrice = distance_matrix(data_train, data_test)
res = knn_predict(dist_matrice, labels_train, k)
return(np.sum(labels_test == res) / len(labels_test))
```
%% Cell type:markdown id: tags:
Pour visualiser ce modèle, nous traçons les taux de réussite en fonction du nombre de k voisins choisis.
%% Cell type:code id: tags:
``` python
if __name__ == "__main__":
x = range(1, 20)
d, l = read_cifar_batch("data/cifar-10-batches-py/data_batch_1")
d_train, l_train, d_test, l_test = split_dataset(d, l, 0.9)
dist_matrice = distance_matrix(d_train, d_test)
y = []
for knn in x:
stat = 0
res = knn_predict(dist_matrice, l_train, knn)
y.append(np.sum(l_test == res) / len(l_test))
plt.plot(x, y, label='Précision')
plt.xlabel('nombre de plus proche voisins concidérés')
plt.ylabel('taux de bonne calification')
plt.xticks(range(1, 20))
plt.yticks(np.arange(0, 1.1, 0.1))
plt.legend()
plt.show()
```
%% Output
%% Cell type:markdown id: tags:
Pour évaluer l'efficacité de cette méthode, j'ai effectué 10 itérations, chaque fois sur un nouvel ensemble de test et d'entraînement. J'ai tracé les 10 courbes sur le même graphe, ce qui a donné le résultat ci-dessous.
%% Cell type:code id: tags:
``` python
%%script false
if __name__ == "__main__":
nbr_knn = 20
nbr_val = 10
x = range(1, nbr_knn)
d, l = read_cifar_batch("data/cifar-10-batches-py/data_batch_1")
for essai in range(nbr_val):
d_train, l_train, d_test, l_test = split_dataset(d, l, 0.9)
dist_matrice = distance_matrix(d_train, d_test)
y = []
for knn in x:
stat = 0
res = knn_predict(dist_matrice, l_train, knn)
y.append(np.sum(l_test == res) / len(l_test))
plt.plot(x, y, label=f'Précision knn mesure {essai}')
plt.xlabel('nombre de plus proche voisins concidérés')
plt.ylabel('taux de bonne calification')
plt.xticks(range(1, nbr_knn))
plt.yticks(np.arange(0, 1.1, 0.1))
plt.legend()
plt.show()
```
%% Output
Couldn't find program: 'false'
%% Cell type:code id: tags:
``` python
from IPython.display import display, Image
display(Image(filename="result/knn_1_20_valid_10test.png"))
```
%% Output
%% Cell type:markdown id: tags:
On remarque une chute à k=2, cette chute est due à l'introduction d'un nouveau label parmi les choix possibles. L'algorithme développé ne traite pas la situation où dans ses k plus proches voisins, deux labels apparaissent le même nombre de fois, et il choisit naturellement le plus petit des deux.
Pour réduire les erreurs lorsque deux labels apparaissent le même nombre de fois parmi les k plus proches voisins, l'algorithme ci-dessous choisira celui des deux dont la somme des distances est la plus petite.
%% Cell type:code id: tags:
``` python
def knn_predict2(dist, labels_train, k):
resultat=[]
for im in dist:
dico={}
kmax=np.argpartition(im, k)[:k]
for indexe in kmax:
if labels_train[indexe] in dico:
dico[labels_train[indexe]][0]+=1
dico[labels_train[indexe]][1]+=im[indexe]
else:
dico[labels_train[indexe]]=[1,im[indexe]]
dico = sorted(dico.items(), key=lambda item: item[1][0], reverse=True)
max_value = dico[0][1][0]
dico = [item for item in dico if item[1][0] == max_value]
if len(dico) > 1:
dico = sorted(dico, key=lambda item: item[1][1])
resultat.append(dico[0][0])
return(resultat)
```
%% Cell type:markdown id: tags:
Pour comparer les deux méthodes, j'ai tracé les résultats des deux méthodes sur le même graphique en utilisant les mêmes ensembles d'entraînement et de test.
%% Cell type:code id: tags:
``` python
if __name__ == "__main__":
nbr_knn = 20
x = range(1, nbr_knn)
#d, l = read_cifar_batch("data/cifar-10-batches-py/data_batch_1")
#d_train, l_train, d_test, l_test = split_dataset(d, l, 0.9)
#dist_matrice = distance_matrix(d_train, d_test)
y1 = []
y2 = []
for knn in x:
stat = 0
res = knn_predict(dist_matrice, l_train, knn)
res2 = knn_predict2(dist_matrice, l_train, knn)
y1.append(np.sum(l_test == res) / len(l_test))
y2.append(np.sum(l_test == res2) / len(l_test))
plt.plot(x, y1, label=f'Précision knn')
plt.plot(x, y2, label='Précision knn2')
plt.xlabel('nombre de plus proche voisins concidérés')
plt.ylabel('taux de bonne calification')
plt.xticks(range(1, nbr_knn))
plt.yticks(np.arange(0, 1.1, 0.1))
plt.legend()
plt.show()
```
%% Output
%% Cell type:markdown id: tags:
On remarque que la nouvelle méthode améliore sensiblement la précédente et ne présente pas de chute à k=2.
### Résultat
Finalement, on constate que la méthode des k plus proches voisins a une efficacité d'environ 30% sur la base de données CIFAR-10, quel que soit le nombre de plus proches voisins choisis. Cela représente une amélioration par rapport à un choix aléatoire qui aurait un taux d'environ 10% compte tenu des 10 classes, mais reste relativement faible.
## Réseaux de Neurones Artificiels
Dans cette partie nous allons développé un réseau de neuronne pour la classification de la base de donnée CIFAR-10. Pour cela nous prenons la fonction d'activation $\sigma$ et les matrices de poids et de biais respectant les relations suivantes:
Dans cette partie, nous allons développer un réseau de neurones pour la classification de la base de donnée CIFAR-10. Pour cela nous prenons la fonction d'activation $\sigma$ et les matrices de poids et de biais respectant les relations suivantes:
$$Z^{L+1}=W^{L+1}A^{L}+B^{L+1}$$
$$A^{L+1}=\sigma(Z^{L+1})$$
La fonction de perte donné C est la fonction de coup MSE :
La fonction de perte, donnée C, est la fonction de coût MSE :
$$C = \frac{1}{N_{out}}\sum_{i=1}^{N_{out}} (\hat{y_i} - y_i)^2$$
### 1
Pour entraîner notre modèle nous devons effectuer la descente de gradiant, qui consiste à trouver la relation qui permet d'avoir l'impacte des matrices de poid et de biais sur la fonction de perte.
Pour entraîner notre modèle nous devons effectuer la descente de gradient, qui consiste à trouver la relation qui permet d'avoir l'impact des matrices de poids et de biais sur la fonction de perte.
$$\sigma(x)=\frac{1}{1+e^{-x}} $$
$$\Rightarrow \sigma'(x)=\frac{-e^{-x}}{-(1+e^{-x})^2} $$
$$\Rightarrow \sigma'(x)=\frac{1}{1+e^{-x}}(\frac{1+e^{-x}-1}{1+e^{-x}}) $$
$$\Rightarrow \sigma'(x)=\sigma(\frac{1+e^{-x}}{1+e^{-x}}-\frac{1}{1+e^{-x}}) $$
$$\Rightarrow \sigma'(x)=\sigma(1-\sigma)$$
### 2
$$\frac{\partial C}{\partial A^{(2)}} ? $$
$$\Rightarrow \frac{\partial C}{\partial a_i^{(2)}}=\frac{1}{N_{out}}\sum_{i=1}^{N_{out}} (a_i^{(2)} - y_i)^2 $$
$$\Rightarrow \frac{\partial C}{\partial a_i^{(2)}}=\frac{2}{N_{out}} (a_i^{(2)} - y_i) $$
$$\Rightarrow \frac{\partial C}{\partial A^{(2)}}=\frac{2}{N_{out}} (A^{(2)} - Y)$$
### 3
$$\frac{\partial C}{\partial Z^{(2)}}=\frac{\partial C}{\partial A^{(2)}}\frac{\partial A^{(2)}}{\partial Z^{(2)}} $$
$$A^{(2)}=\sigma (Z^{(2)}) $$
$$\frac{\partial A^{(2)}}{\partial Z^{(2)}}=A^{(2)}(1-A^{(2)}) $$
$$\Rightarrow \frac{\partial C}{\partial Z^{(2)}}=\frac{\partial C}{\partial A^{(2)}}[A^{(2)}(1-A^{(2)})]$$
### 4
$$\frac{\partial C}{\partial W^{(2)}}=\frac{\partial C}{\partial Z^{(2)}}\frac{\partial Z^{(2)}}{\partial W^{(2)}} $$
$$Z^{(2)}=W^{(2)}A^{(1)}+B^{(2)} $$
$$\frac{\partial Z^{(2)}}{\partial W^{(2)}}=A^{(1)} $$
$$\Rightarrow \frac{\partial C}{\partial W^{(2)}}=\frac{\partial C}{\partial Z^{(2)}}A^{(1)}$$
### 5
$$\frac{\partial C}{\partial B^{(2)}}=\frac{\partial C}{\partial Z^{(2)}}\frac{\partial Z^{(2)}}{\partial B^{(2)}} $$
$$Z^{(2)}=W^{(2)}A^{(1)}+B^{(2)} $$
$$\frac{\partial Z^{(2)}}{\partial B^{(2)}}=1 $$
$$\Rightarrow \frac{\partial C}{\partial B^{(2)}}=\frac{\partial C}{\partial Z^{(2)}}$$
### 6
$$\frac{\partial C}{\partial A^{(1)}}=\frac{\partial C}{\partial Z^{(2)}}\frac{\partial Z^{(2)}}{\partial A^{(1)}} $$
$$Z^{(2)}=W^{(2)}A^{(1)}+B^{(2)} $$
$$\frac{\partial Z^{(2)}}{\partial A^{(1)}}=W^{(2)} $$
$$\Rightarrow \frac{\partial C}{\partial A^{(1)}}=\frac{\partial C}{\partial Z^{(2)}}W^{(2)}$$
### 7
$$\frac{\partial C}{\partial Z^{(1)}}=\frac{\partial C}{\partial A^{(1)}}\frac{\partial A^{(1)}}{\partial Z^{(1)}} $$
$$A^{(1)}=\sigma (Z^{(1)}) $$
$$\frac{\partial A^{(1)}}{\partial Z^{(1)}}=A^{(1)}(1-A^{(1)}) $$
$$\Rightarrow \frac{\partial C}{\partial Z^{(1)}}=\frac{\partial C}{\partial A^{(1)}}[A^{(1)}(1-A^{(1)})]$$
### 8
$$\frac{\partial C}{\partial W^{(1)}}=\frac{\partial C}{\partial Z^{(1)}}\frac{\partial Z^{(1)}}{\partial W^{(1)}} $$
$$Z^{(1)}=W^{(1)}A^{(0)}+B^{(1)} $$
$$\frac{\partial Z^{(1)}}{\partial W^{(1)}}=A^{(0)} $$
$$\Rightarrow \frac{\partial C}{\partial W^{(1)}}=\frac{\partial C}{\partial Z^{(1)}}A^{(0)}$$
### 9
$$\frac{\partial C}{\partial B^{(1)}}=\frac{\partial C}{\partial Z^{(1)}}\frac{\partial Z^{(1)}}{\partial B^{(1)}} $$
$$Z^{(1)}=W^{(1)}A^{(0)}+B^{(1)} $$
$$\frac{\partial Z^{(1)}}{\partial B^{(1)}}=1 $$
$$\Rightarrow \frac{\partial C}{\partial B^{(1)}}=\frac{\partial C}{\partial Z^{(1)}}$$
%% Cell type:markdown id: tags:
### 10
La fonction de perte MSE n'est pas adapté à la classification, pour la suite nous prendrons donc la fonction loss cross-entropy qui prend la matrice target $Y$ et la matrice de prbabilité de prédiction $\hat{Y}$
La fonction de perte MSE n'est pas adaptée à la classification, pour la suite nous prendrons donc la fonction loss cross-entropy qui prend la matrice target $Y$ et la matrice de probabilité de prédiction $\hat{Y}$
$$loss=\frac{1}{N_{out}}\sum_{i=1}^{N_{out}}-(y_i*log(\hat{y_i}))$$
Pour calculer cette fonction de perte il faut avoir $\hat{y}$ qui est une prédiction sous forme de probabilité, donc que la somme des probabilité soit 1 et que chaque probabilité soit comprise dans $[0,1]$. Pour cela on remplace la signoïde $A^{(2)}=\sigma(Z^{(2)})$ par la fonction softmax qui donne $\hat{Y}=A^{(2)}=softmax(Z^{(2)})$.
Pour calculer cette fonction de perte il faut avoir $\hat{y}$ qui est une prédiction sous forme de probabilité, donc que la somme des probabilités soit 1 et que chaque probabilité soit comprise dans $[0,1]$. Pour cela on remplace la signoïde $A^{(2)}=\sigma(Z^{(2)})$ par la fonction softmax qui donne $\hat{Y}=A^{(2)}=softmax(Z^{(2)})$.
$$softmax(x_i)=\frac{e^{x_i}}{\sum_{j=1}^{n}e^{x_j}}$$
%% Cell type:code id: tags:
``` python
def learning_methode(k,dk,learning_rate):
k2=k-learning_rate*dk
return(k2)
def learn_once_mse(w1,b1,w2,b2,data,targets,learning_rate):
a0 = data # the data are the input of the first layer
z1 = np.matmul(a0, w1) + b1 # input of the hidden layer
a1 = 1 / (1 + np.exp(-z1)) # output of the hidden layer (sigmoid activation function)
z2 = np.matmul(a1, w2) + b2 # input of the output layer
a2 = 1 / (1 + np.exp(-z2)) # output of the output layer (sigmoid activation function)
predictions = a2 # the predicted values are the outputs of the output layer
# Compute loss (MSE)
loss = np.mean(np.square(predictions - targets))
dc_da2=(2/data.shape[0])*(predictions-targets)
dc_dz2=dc_da2*(a2*(1-a2))
dc_dw2=np.dot(np.transpose(a1), dc_dz2)
dc_db2=np.dot(np.ones((1,dc_dz2.shape[0])),dc_dz2)
dc_da1=np.dot(dc_dz2,np.transpose(w2))
dc_dz1=dc_da1*(a1*(1-a1))
dc_dw1=np.dot(np.transpose(a0), dc_dz1)
dc_db1=np.dot(np.ones((1,dc_dz1.shape[0])),dc_dz1)
w1=learning_methode(w1,dc_dw1,learning_rate)
b1=learning_methode(b1,dc_db1,learning_rate)
w2=learning_methode(w2,dc_dw2,learning_rate)
b2=learning_methode(b2,dc_db2,learning_rate)
# Compute loss (MSE)
return(w1,b1,w2,b2,loss)
```
%% Cell type:markdown id: tags:
### 11
La fonction one_hot va passer le vecteur label en matrice de 1 et de 0 qui servira de target à la matrice de prediction de probabilité rendu par softmax.
La fonction one_hot va passer le vecteur label en matrice de 1 et de 0 qui servira de target à la matrice de prédiction de probabilité rendue par softmax.
%% Cell type:code id: tags:
``` python
def one_hot(label):
nbr_classe=9
mat=np.zeros((len(label),nbr_classe))
for label_indexe,label_im, in enumerate(label):
mat[label_indexe,label_im-1]=1
return(mat)
```
%% Cell type:markdown id: tags:
### 12
%% Cell type:code id: tags:
``` python
def softmax(y):
y=np.exp(y)
v=np.sum(y, axis=1, keepdims=True)
return(y / v)
def learn_once_cross_entropy(w1,b1,w2,b2,data,labels_train,learning_rate):
targets = one_hot(labels_train)
a0 = data
z1 = np.dot(a0, w1) + b1
a1 = 1 / (1 + np.exp(-z1))
z2 = np.dot(a1, w2) + b2
softa2=softmax(z2)
predictions=softa2
loss=np.mean(np.sum(-targets*np.log(predictions),axis=1))
dc_dz2=(predictions-targets)/data.shape[0]
dc_dw2=np.dot(np.transpose(a1), dc_dz2)
dc_db2=np.sum(dc_dz2, axis=0, keepdims=True)
dc_da1=np.dot(dc_dz2,np.transpose(w2))
dc_dz1=dc_da1*(1-a1)*a1
dc_dw1=np.dot(np.transpose(a0), dc_dz1)
dc_db1=np.sum(dc_dz1, axis=0, keepdims=True)
w1=learning_methode(w1,dc_dw1,learning_rate)
b1=learning_methode(b1,dc_db1,learning_rate)
w2=learning_methode(w2,dc_dw2,learning_rate)
b2=learning_methode(b2,dc_db2,learning_rate)
return(w1,b1,w2,b2,loss)
```
%% Cell type:markdown id: tags:
### 13
La fonction accuracy va mesurer le taux de réussite du model, elle sera utile pour mesurer l'efficacité du modèle sur une base de test et pour suivre l'évolution du modèle en fonction des epoques d'entraînement (et donc vérifier que le modèle s'améliore)
La fonction accuracy va mesurer le taux de réussite du modèle, elle sera utile pour mesurer l'efficacité du modèle sur une base de test et pour suivre l'évolution du modèle en fonction des époques d'entraînement (et donc vérifier que le modèle s'améliore)
%% Cell type:code id: tags:
``` python
def accuracy(w1,b1,w2,b2,data,labels):
a0 = data
z1 = np.dot(a0, w1) + b1
a1 = 1 / (1 + np.exp(-z1))
z2 = np.dot(a1, w2) + b2
softa2=softmax(z2)
predictions = softa2
prediction_2 = np.empty(predictions.shape[0], dtype=int)
for i, ligne in enumerate(predictions):
prediction_2[i] = np.argmax(ligne)+1
indices_egalite = np.where(prediction_2 == labels)[0]
nombre_indices = len(indices_egalite)
return(nombre_indices/len(labels))
def train_mlp_cross_entropy(w1,b1,w2,b2,d_train,labels_train,learning_rate,num_epoch):
train_accuracies,loss_evo=[],[]
for k in range(num_epoch):
w1,b1,w2,b2,loss=learn_once_cross_entropy(w1,b1,w2,b2,d_train,labels_train,learning_rate)
t=accuracy(w1,b1,w2,b2,d_train,labels_train)
train_accuracies.append(t)
loss_evo.append(loss)
return (w1,b1,w2,b2,train_accuracies,loss_evo)
```
%% Cell type:markdown id: tags:
### 14
%% Cell type:code id: tags:
``` python
def test_mlp(w1,b1,w2,b2,d_test,labels_test):
test_accuracy=accuracy(w1,b1,w2,b2,d_test,labels_test)
return(test_accuracy)
```
%% Cell type:markdown id: tags:
### 15
%% Cell type:code id: tags:
``` python
def run_mlp_training(data_train, labels_train, data_test, labels_test,d_h,learning_rate,num_epoch):
d_in = data_train.shape[1] # input dimension
d_out = max(labels_train) # output dimension (number of neurons of the output layer)
w1 = np.random.randn(d_in, d_h) # first layer weights
b1 = np.zeros((1, d_h)) # first layer biaises
w2 = np.random.randn(d_h, d_out) # second layer weights
b2 = np.zeros((1, d_out)) # second layer biaises
w1,b1,w2,b2,accuratie_train,loss=train_mlp_cross_entropy(w1,b1,w2,b2,data_train, labels_train,learning_rate,num_epoch)
test_accuracy=test_mlp(w1,b1,w2,b2,data_test, labels_test)
return(accuratie_train,loss,test_accuracy)
```
%% Cell type:markdown id: tags:
### 16
%% Cell type:code id: tags:
``` python
if __name__ == "__main__":
d, l = read_cifar_batch("data/cifar-10-batches-py/data_batch_1")
num_epoch=1000
dh=64
learning_rate=0.1
d_train, l_train, d_test, l_test = split_dataset(d, l, 0.9)
train_accuracy,loss,test_accuracy=run_mlp_training(d_train, l_train, d_test, l_test,dh,learning_rate,num_epoch)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
ax1.plot(range(num_epoch),loss,label="cross-entropy")
ax1.set_xlabel('epoque')
ax1.set_ylabel('loss')
ax1.set_title('evolution de la fonction loss par epoque')
ax1.legend()
ax2.plot(range(num_epoch),train_accuracy,label="cross-entropy")
ax2.set_xlabel('epoque')
ax2.set_ylabel('accuracy')
ax2.set_title('evolution de la accuracy')
ax2.legend()
plt.tight_layout()
plt.show()
```
%% Output
C:\Users\Utilisateur\AppData\Local\Temp\ipykernel_26032\2793120310.py:10: RuntimeWarning: overflow encountered in exp
a1 = 1 / (1 + np.exp(-z1))
C:\Users\Utilisateur\AppData\Local\Temp\ipykernel_26032\1996586622.py:4: RuntimeWarning: overflow encountered in exp
a1 = 1 / (1 + np.exp(-z1))
%% Cell type:markdown id: tags:
On remarque que la fonction de perte de perte tend vers 2. Cette limite peut être un minimum local, en effet le modèle part d'une matrice généré aléatoirement et tend vers le minimum local le plus proche, ainsi avec d'autres matrices de poid et de biais initiale nous pourions potentiellement arrivé à un meilleur modèle. De plus il est possible le le learning raite soit trop grand et que 2 ne soit pas réellement le minimum mais la limite vers laquel notre nodèle tend car il tourne autour du minimum avec un pas trop grand pour l'atteindre.
On remarque que la fonction de perte de perte tend vers 2. Cette limite peut être un minimum local, en effet le modèle part d'une matrice générée aléatoirement et tend vers le minimum local le plus proche, ainsi avec d'autres matrices de poids et de biais initial nous pourrions potentiellement arriver à un meilleur modèle. De plus il est possible que le learning rate soit trop grand et que 2 ne soit pas réellement le minimum mais la limite vers laquelle notre modèle tend car il tourne autour du minimum avec un pas trop grand pour l'atteindre.
## Conclusion
On a vue dans ce BE deux méthodes de classification : la méthode par k-plus proches voisins et par réseau de neurone. Chacun de ces modèle pourrait être améliorer pour augmanter leurs taux de réussite.
On a vu dans ce BE deux méthodes de classification : la méthode par k-plus proches voisins et par réseau de neurones. Chacun de ces modèles pourrait être amélioré pour augmenter leurs taux de réussite.
- k plus proches voisins : on peut choisir une autre métrique de distance qui serait plus efficace ou ajouter une étapes de prétraitement pour avoir des meilleurs positionnement des images en fonction de leurs classes.
- k plus proches voisins : on peut choisir une autre métrique de distance qui serait plus efficace ou ajouter une étape de prétraitement pour avoir de meilleurs positionnements des images en fonction de leurs classes.
- réseau de neuronne : on peut augmenter le nombre de couches, en effet avec 1 seule couche caché chaque poid vas impacter plusieurs classes et devra être très affiné pour permettre une classification efficace. De plus les hyperparamètre comme learning rate et les matrice initialisé pourrait être également optimisé.
- réseau de neurones : on peut augmenter le nombre de couches, en effet avec 1 seule couche cachée chaque poids va impacter plusieurs classes et devra être très affiné pour permettre une classification efficace. De plus les hyperparamètres comme learning rate et les matrices initialisées pourraient être également optimisés.
On comparant ces modèles on remarque cependant que les k plus proches voisins ne s'améliore qu'en ajoutant de nouvelles instances à la base de donnée d'entraînement, la où le réseau de neuronne s'améliore en s'entraînant avec une même base de donnée. Ainsi le réseau de neuronne présente un potentiel d'être in fine meilleur que les k-plus proches voisins.
On comparant ces modèles, on remarque cependant que les k plus proches voisins ne s'améliorent qu'en ajoutant de nouvelles instances à la base de donnée d'entraînement, là où le réseau de neurones s'améliore en s'entraînant avec une même base de donnée. Ainsi le réseau de neurones présente un potentiel d'être in fine meilleur que les k-plus proches voisins.
Pour cela il faudra quand même apporté beaucoup de changement au modèle, que se soit avec les hyperparamètres comme expliqué plus haut, ou par l'utilisation de filtres comme matrice de poid, l'utilisation de convolution et l'augmentation du nombre de couches cachés. Car actuellement le modèle par réseau de neuronne atteint tout juste 18% de réussite pour 1000 époques d'entraînement un learning rate à 0,1 et une couche caché de dimension 64 contre 30% pour le modèle par k plus proches voisins.
Pour cela il faudra quand même apporter beaucoup de changements au modèle, que se soit avec les hyperparamètres comme expliqué plus haut, ou par l'utilisation de filtres comme une matrice de poids, l'utilisation de convolution et l'augmentation du nombre de couches cachées. Car actuellement le modèle par réseau de neurones atteint tout juste 18% de réussite pour 1000 époques d'entraînement, un learning rate à 0,1 et une couche cachée de dimension 64 contre 30% pour le modèle par k plus proches voisins.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment