-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathPyTorchMNISTFonctionEntrainer.py
More file actions
125 lines (106 loc) · 5.04 KB
/
PyTorchMNISTFonctionEntrainer.py
File metadata and controls
125 lines (106 loc) · 5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# -*- coding: utf-8 -*-
"""
Exemple simple de MNIST avec PyTorch
Exemple avec nn.Sequential et F.cross_entropy
Production de métriques avec graphes
Fonction entrainer
"""
import torch
torch.manual_seed(0) # Pour résultats reproductibles
# Fonction J d'entropie croisée
import torch.nn.functional as F
fonction_cout = F.cross_entropy
def taux_bonnes_predictions(lot_Y_predictions, lot_Y):
predictions_categorie = torch.argmax(lot_Y_predictions, dim=1)
return (predictions_categorie == lot_Y).float().mean()
from torch import nn
# Définition de l'architecture du RNA
modele = nn.Sequential(
nn.Linear(784, 30),
nn.ReLU(),
nn.Linear(30, 10)
)
from torch import optim
optimiseur = optim.SGD(modele.parameters(), lr=0.05)
# Chargement des données de MNIST
import pickle, gzip
fichier_donnees = gzip.open(r"mnist.pkl.gz", 'rb')
((donnees_ent_X, donnees_ent_Y),(donnees_valid_X, donnees_valid_Y),(donnees_test_X,donnees_test_Y)) = pickle.load(fichier_donnees, encoding="latin-1")
fichier_donnees.close()
# Conversion des données en type toch.Tensor
import torch
donnees_ent_X, donnees_ent_Y, donnees_valid_X,donnees_valid_Y = map(torch.tensor, (donnees_ent_X, donnees_ent_Y, donnees_valid_X,donnees_valid_Y))
# Création des objets DataLoader pour itérer par lot
from torch.utils.data import TensorDataset
from torch.utils.data import DataLoader
ds_ent = TensorDataset(donnees_ent_X, donnees_ent_Y)
dl_ent = DataLoader(ds_ent, batch_size=100, shuffle=True)
ds_valid = TensorDataset(donnees_valid_X,donnees_valid_Y)
dl_valid = DataLoader(ds_valid, batch_size=100)
def entrainer(modele, dl_ent, dl_valid, optimiseur, nb_epochs=10):
# Listes pour les métriques par epoch
liste_cout_moyen_ent = []
liste_taux_moyen_ent = []
liste_cout_moyen_valid = []
liste_taux_moyen_valid = []
# Boucle d'apprentissage
for epoch in range(nb_epochs):
cout_total_ent = 0 # pour cumuler les couts par mini-lot
taux_bonnes_predictions_ent = 0 # pour cumuler les taux par mini-lot
modele.train() # Pour certains types de couches (nn.BatchNorm2d, nn.Dropout, ...)
# Boucle d'apprentissage par mini-lot pour une epoch
for lot_X, lot_Y in dl_ent:
optimiseur.zero_grad() # Remettre les dérivées à zéro
lot_Y_predictions = modele(lot_X) # Appel de la méthode forward
cout = fonction_cout(lot_Y_predictions, lot_Y)
cout.backward() # Calcul des gradiants par rétropropagation
with torch.no_grad():
cout_total_ent +=cout
taux_bonnes_predictions_ent += taux_bonnes_predictions(lot_Y_predictions, lot_Y)
optimiseur.step() # Mise à jour des paramètres
# Calculer les moyennes par mini-lot
with torch.no_grad():
cout_moyen_ent = cout_total_ent/len(dl_ent)
taux_moyen_ent = taux_bonnes_predictions_ent/len(dl_ent)
modele.eval() # Pour certains types de couches (nn.BatchNorm2d, nn.Dropout, ...)
with torch.no_grad():
cout_valid = sum(fonction_cout(modele(lot_valid_X), lot_valid_Y) for lot_valid_X, lot_valid_Y in dl_valid)
taux_bons_valid = sum(taux_bonnes_predictions(modele(lot_valid_X), lot_valid_Y) for lot_valid_X, lot_valid_Y in dl_valid)
cout_moyen_valid = cout_valid/len(dl_valid)
taux_moyen_valid = taux_bons_valid/len(dl_valid)
print(f'-------- > epoch {epoch+1}: coût moyen entraînement = {cout_moyen_ent}')
print(f'-------- > epoch {epoch+1}: taux moyen entraînement = {taux_moyen_ent}')
print(f'-------- > epoch {epoch+1}: coût moyen validation = {cout_moyen_valid}')
print(f'-------- > epoch {epoch+1}: taux moyen validation = {taux_moyen_valid}')
liste_cout_moyen_ent.append(cout_moyen_ent)
liste_taux_moyen_ent.append(taux_moyen_ent)
liste_cout_moyen_valid.append(cout_moyen_valid)
liste_taux_moyen_valid.append(taux_moyen_valid)
# Affichage du graphique d'évolution des métriques par epoch
import numpy as np
import matplotlib.pyplot as plt
plt.subplot(1, 2, 1)
plt.plot(np.arange(0,nb_epochs),liste_cout_moyen_ent,label='Erreur entraînement')
plt.plot(np.arange(0,nb_epochs),liste_cout_moyen_valid,label='Erreur validation')
plt.title("Evolution du coût")
plt.xlabel('epoch')
plt.ylabel('moyenne par observation')
plt.legend(loc='upper center')
# plt.show()
plt.subplot(1, 2, 2)
plt.plot(np.arange(0,nb_epochs),liste_taux_moyen_ent,label='Taux bonnes réponses entraînement')
plt.plot(np.arange(0,nb_epochs),liste_taux_moyen_valid,label='Taux bonnes réponses validation')
plt.title("Evolution du taux")
plt.xlabel('epoch')
plt.ylabel('moyenne par observation')
plt.legend(loc='upper center')
# plt.show()
entrainer(modele, dl_ent, dl_valid, optimiseur, nb_epochs=10)
CHEMIN = './MNISTSimple10.pth'
torch.save(modele.state_dict(), CHEMIN)
modele = nn.Sequential(
nn.Linear(784, 30),
nn.ReLU(),
nn.Linear(30, 10)
)
modele.load_state_dict(torch.load(CHEMIN))