forked from sergeLabo/semaphore_cupy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsemaphore_ia.py
208 lines (155 loc) · 7 KB
/
semaphore_ia.py
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import numpy as np
from time import time
def sigmoid(x):
"""La fonction sigmoïde est une courbe en S:
https://fr.wikipedia.org/wiki/Sigmo%C3%AFde_(math%C3%A9matiques)
"""
return 1 / (1 + np.exp(-x))
def sigmoid_prime(z):
"""La dérivée de la fonction sigmoid,
soit sigmoid' comme f' !
"""
return z * (1 - z)
def relu(x):
"""Rectifie les négatifs à 0:
-1 > 0
1 > 1
Rectified Linear Unit:
In the context of artificial neural networks, the rectifier is an
activation function defined as the positive part of its argument.
https://bit.ly/2HyT4ZO sur Wikipedia en.
"""
return np.maximum(0, x)
def relu_prime(z):
"""Fonction: 1 pour tous les réels positifs ou nuls et 0 pour les réels négatifs.
La fonction de Heaviside (également fonction échelon unité, fonction
marche d'escalier) est la fonction indicatrice de R.
Une fonction fonction indicatrice, est une fonction définie sur un
ensemble E qui explicite l’appartenance ou non à un sous-ensemble F de E
de tout élément de E.
"""
return np.asarray(z > 0, dtype=np.float32)
class SemaphoreIA:
"""Réseau de neuronnes Perceptron multicouches."""
def __init__(self, train, learningrate):
"""train = Nombre de shot pour l'apprentissage
learningrate = coeff important
"""
print("Calcul avec numpy ... numpy ... numpy ... numpy ... ")
self.train = train
self.learningrate = learningrate
# Réseau de neurones: colonne 1600 en entrée, 2 nodes de 100, sortie de 27 caractères
self.layers = [1600, 100, 100, 27]
# Fonction d'activation: imite l'activation d'un neuronne
self.activations = [relu, relu, sigmoid]
self.weight_list = None
fichier = np.load('./semaphore.npz')
self.x_train = fichier['x_train']
self.y_train = fichier['y_train']
self.x_test = fichier['x_test']
self.y_test = fichier['y_test']
a = "Training: Shot {} Lettre {}; Testing: Shot {} Lettre {}"
print(a.format( len(self.x_train), len(self.y_train),
len(self.x_test), len(self.y_test)))
def training(self):
"""Apprentissage avec 60 000 images
Poids enregistré dans weights.npy
"""
print("Training...")
# Matrice diagonale de 1
diagonale = np.eye(27, 27)
# globals() Return a dictionary representing the current global symbol table.
self.activations_prime = [globals()[fonction.__name__ + '_prime'] for fonction in self.activations]
node_dict = {}
# Liste des poids
# Initialisation des poids des nodes, pour ne pas à être à 0
# Construit 3 matrices (100x1600, 100x100, 27x100)
# /np.sqrt() résultat expérimental de l'initialisation de Xavier Glorot et He
weight_list = [np.random.randn(self.layers[k+1], self.layers[k]) / \
np.sqrt(self.layers[k]) for k in range(len(self.layers)-1)]
# vecteur_ligne = image en ligne à la 1ère itération
# nombre_lettre = nombre correspondant à la lettre de l'image
# i pour itération, vecteur_colonne = x_train de i, nombre_lettre = y_train de i
for i, (vecteur_ligne, nombre_lettre) in enumerate(zip(self.x_train, self.y_train)):
# la ligne devient colonne
vecteur_colonne = np.array(vecteur_ligne, ndmin=2).T
# Forward propagation
node_dict[0] = vecteur_colonne
for k in range(len(self.layers)-1):
# weight_list[k] (100x1600, 100x100 27x100) vecteur_colonne (1600,)
# z de format 100 x 1
z = np.dot(weight_list[k], vecteur_colonne)
# self.activations = non linéaire sinon sortie fonction linéaire de l'entrée
# imite le seuil d'activation électrique du neuronne
vecteur_colonne = self.activations[k](z)
node_dict[k+1] = vecteur_colonne
# Retro propagation, delta_a = écart entre la sortie réelle et attendue
delta_a = vecteur_colonne - diagonale[:,[nombre_lettre]]
# Parcours des nodes en sens inverse pour corriger proportionnellemnt
# les poids en fonction de l'erreur par rapport à la valeur souhaitée
# Descente du Gradient stochastique
for k in range(len(self.layers)-2, -1, -1):
delta_z = delta_a * self.activations_prime[k](node_dict[k+1])
delta_w = np.dot(delta_z, node_dict[k].T)
delta_a = np.dot(weight_list[k].T, delta_z)
# Pour converger vers le minimum d'erreur
weight_list[k] -= self.learningrate * delta_w
self.weight_list = weight_list
# Dans un fichier
np.save('./weights.npy', weight_list)
print("type(weight_list :)", type(weight_list),
"\nlen(weight_list) =", len(weight_list),
"\n 0", len(weight_list[0]),
"\n 1", len(weight_list[1]),
"\n 2", len(weight_list[2]))
# Dans un fichier
np.save('./weights.npy', weight_list)
print('weights.npy enregistré')
def testing(self):
"""Teste avec les images de testing, retourne le ratio de bon résultats"""
print("Testing...")
weight_list = np.load('weights.npy', allow_pickle=True)
# Nombre de bonnes reconnaissance
success = 0
for vecteur_ligne, nombre_lettre in zip(self.x_test, self.y_test):
# image en ligne au 1er passage pour les failed
img = vecteur_ligne.copy()
for k in range(len(self.layers)-1):
vecteur_ligne = self.activations[k](np.dot(weight_list[k],
vecteur_ligne))
reconnu = np.argmax(vecteur_ligne)
if reconnu == nombre_lettre:
success += 1
if len(self.x_test) != 0:
resp = 100.0 * success / len(self.x_test)
else:
resp = 0
return resp
def main():
train = 60000
learningrate = 0.023
sia = SemaphoreIA(train, learningrate)
sia.training()
resp = sia.testing()
print("Learningrate: {} Résultat {}".format(learningrate, round(resp, 1)))
if __name__ == "__main__":
t = time()
main()
print("Calcul en:", round((time() - t), 1), "s")
"""
AMD FX(tm)-8320 Eight-Core Processor
Calcul avec numpy ... numpy ... numpy ... numpy ...
Training: Shot 60000 Lettre 60000; Testing: Shot 10000 Lettre 10000
Training...
type(weight_list :) <class 'list'>
len(weight_list) = 3
0 100
1 100
2 27
weights.npy enregistré
Testing...
Learningrate: 0.023 Résultat 87.4
Calcul en: 139.8 s
"""