Outils pour utilisateurs

Outils du site


l_intelligence_du_semaphore

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Prochaine révision
Révision précédente
l_intelligence_du_semaphore [2019/01/26 13:17]
serge créée
l_intelligence_du_semaphore [2020/02/04 17:43] (Version actuelle)
serge ↷ Liens modifiés en raison d'un déplacement.
Ligne 1: Ligne 1:
 ====== L'​intelligence du sémaphore ====== ====== L'​intelligence du sémaphore ======
 +<WRAP center round box 80% centeralign>​
 +**{{tagpage>​semaphore|Sémaphores}}** ​ ....  **{{tagpage>​bge|Blender Game Engine}}** ....  **{{tagpage>​ia|Intelligence Artificielle}}**
 +</​WRAP>​
 +<WRAP center round box 60% centeralign>​
 +C'est quoi un sémaphore ?
 +{{ youtube>​F3sY6_fOx2I?​medium }}
 +{{ chappe.jpeg?​400 }}
 +</​WRAP>​
  
 +<WRAP center round box 60% centeralign>​
 +**Calcul de [[Le sémaphore avec TensorFlow|Le sémaphore avec TensorFlow]] sur GPU au lieu du CPU avec TensorFlow**
 +</​WRAP>​
 +=====Les sources sur GitHub=====
 +  * **[[https://​github.com/​sergeLabo/​semaphore|semaphore chez github.com]]**
 +=====Les images utilisées pour l'​apprentissage=====
 +====Images sorties de Blender====
 +<WRAP group>
 +<WRAP third column>
 +{{media_03:​shot_0_a.png?​200|}}
 +</​WRAP>​
 +<WRAP third column>
 +{{media_03:​shot_1_b.png?​200|}}
 +</​WRAP>​
 +<WRAP third column>
 +{{media_03:​shot_2_c.png?​200|}}
 +</​WRAP>​
 +</​WRAP>​
 +====Images adaptées pour l'​apprentissage====
 +L'​optimisation a montré que la meilleure solution est avec ce type d'​image.
 +<WRAP group>
 +<WRAP third column>
 +{{media_01:​shot_0_a.png?​200|}}
 +</​WRAP>​
 +<WRAP third column>
 +{{media_01:​shot_1_.png?​200|}}
 +</​WRAP>​
 +<WRAP third column>
 +{{media_01:​shot_2_b.png?​200|}}
 +</​WRAP>​
 +</​WRAP>​
  
 +
 +===== Des maths ! ====
 +====Relu Rectifier neural networks====
 +{{ relu.jpg?​400 |}}
 +  * **[[https://​en.wikipedia.org/​wiki/​Rectifier_(neural_networks)|Rectifier (neural networks)]]** ​ sur Wikipedia en
 +<code python>
 +def relu(x):
 +    """​Rectified Linear Unit:
 +    ​
 +    In the context of artificial neural networks, the rectifier is an
 +    activation function defined as the positive part of its argument.
 +    ​
 +    Rectifie les négatifs à 0:
 +    -1 > 0
 +     1 > 1
 +     """​
 +    return np.maximum(0,​ x)
 +</​code>​
 +====Relu_prime====
 +  * **[[https://​fr.wikipedia.org/​wiki/​Fonction_de_Heaviside|Fonction de Heaviside]]** sur Wikipedia fr
 +  * **[[https://​fr.wikipedia.org/​wiki/​Fonction_caract%C3%A9ristique_(th%C3%A9orie_des_ensembles)|Fonction caractéristique (théorie des ensembles)]]** ​ sur Wikipedia fr
 +<code python>
 +def relu_prime(z):​
 +    """​La fonction de Heaviside (également fonction échelon unité, fonction marche d'​escalier) est la fonction indicatrice de R.
 +    ​
 +Une 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. 
 +C'est donc la fonction H (discontinue en 0) prenant la valeur 1 pour tous les réels positifs et la valeur 0 pour les réels strictement négatifs.
 +    """​
 +    return np.asarray(z > 0, dtype=np.float32)
 +</​code>​
 +====Sigmoïd====
 +{{ sigmoid.png?​400 |}}
 +  * **[[https://​fr.wikipedia.org/​wiki/​Sigmo%C3%AFde_(math%C3%A9matiques)|Sigmoïde]]** ​ sur Wikipedia fr
 +Elle représente la fonction de répartition de la loi logistique. Elle est souvent utilisée dans les réseaux de neurones parce qu'​elle est dérivable, ce qui est une contrainte pour l'​algorithme de [[https://​fr.wikipedia.org/​wiki/​R%C3%A9tropropagation_du_gradient|rétropropagation]] de [[https://​fr.wikipedia.org/​wiki/​Perceptron_multicouche#​Perceptron_multicouche_%C3%A0_r%C3%A9tropropagation|Werbos]]. La forme de la dérivée de sa fonction inverse est extrêmement simple et facile à calculer, ce qui améliore les performances des algorithmes. ​
 +<code python>
 +def sigmoid(x):
 +    """​La fonction sigmoïde est une courbe en S."""​
 +    return 1 / (1 + np.exp(-x))
 +</​code>​
 +
 +====Sigmoïd prime====
 +<code python>
 +def sigmoid_prime(z):​
 +    """​La dérivée de la fonction sigmoid."""​
 +    return z * (1 - z)
 +</​code>​
 +
 +====Algorithme du gradient stochastique====
 +  * **[[https://​fr.wikipedia.org/​wiki/​Algorithme_du_gradient_stochastique|Algorithme du gradient stochastique]]**
 +L'​algorithme du gradient stochastique est une méthode de descente de gradient (itérative) utilisée pour la minimisation d'une fonction objectif qui est écrite comme une somme de fonctions différentiables. ​
 +
 +====Diagonale de 1====
 +{{ media_01:​matrice_3x3_1.png?​200 |}}
 +
 +  numpy.eye(N,​ M=None, k=0, dtype=<​class '​float'>,​ order='​C'​)
 +  ​
 +  Return a 2-D array with ones on the diagonal and zeros elsewhere.
 +Matrice ou la sortie est idéale: le 1 correspond à entée[i] = sortie[i], et entée[j],​sortie[k] =0 si j différent de k
 +
 +====Initialisation de X. Glorot et He====
 +X = Xavier = prénom
 +  * **[[http://​deepdish.io/​2015/​02/​24/​network-initialization/​|Initialization of deep networks]]**
 +
 +===== Réseau de neurones Perceptron multicouches ​ =====
 +  * **[[https://​fr.wikipedia.org/​wiki/​Perceptron_multicouche|Perceptron multicouche]]**
 +Un réseau de neurones Perceptron multicouches est un type de réseau dont l'​information circule dans un unique sens, de la couche d'​entrée vers la couche de sortie. Ont dit qu'il est un réseau "à propagation directe"​ (feedforward).
 +
 +
 +===== Réseau de neurones Convolutif =====
 +  * **[[https://​fr.wikipedia.org/​wiki/​R%C3%A9seau_neuronal_convolutif|Réseau neuronal convolutif]]**
 +Un réseau de neurones Convolutif est un type de réseau de neurones artificiels dans lequel le motif de connexion entre les neurones est inspiré par le cortex visuel des animaux. Actuellement,​ il est très utilisé pour l'​analyse des images, des vidéos et du langage naturel.
 +
 +Ce type de réseau est développé avec [[yolo_avec_mes_propres_images|Yolo Darknet Préparation de mes propres images]] puis [[yolo_sans_carte_graphique|Yolo Darknet sans carte graphique]] et enfin [[yolo_darknet_sur_un_portable_optimus|Yolo Darknet sur un portable Optimus]].
 +
 +=====Réseau de neurones Perceptron multicouches en python=====
 +**Du code expliqué avec beaucoup d'​amour**
 +Enfin, là c'est de l'​intelligence qu'on cherche, pas de l'​amour.
 +
 +====Notre réseau====
 + **Une colonne de 1600 en entrée, 2 nodes de 100, une sortie de 27 caractères.**
 +
 +{{ media_01:​perceptron.svg.png?​1000 |}}
 +
 +La totalité du projet est à **[[https://​github.com/​sergeLabo/​semaphore|Semaphore]]** sur Github, et  **[[jeu_du_semaphore_dans_le_blender_game_engine|Jeu du sémaphore dans le Blender Game Engine]]** pour la création des images.
 +
 +====Installation====
 +Installation de pip3:
 +  sudo apt install pip3
 +Installation de numpy et opencv
 +  sudo pip3 install opencv numpy
 +Il faut installer mon [[pymultilame|module python perso]] disponible sur Github
 +  sudo pip3 install -e git+https://​github.com/​sergeLabo/​pymultilame.git#​egg=pymultilame
 +  ​
 +====Le script====
 +<file python ia.py>
 +#​!/​usr/​bin/​env python3
 +# -*- coding: UTF-8 -*-
 +
 +import shutil
 +import numpy as np
 +import cv2
 +from pymultilame import MyTools
 +
 +def sigmoid(x): return 1 / (1 + np.exp(-x))
 +def sigmoid_prime(z):​ return z * (1 - z)
 +def relu(x): return np.maximum(0,​ x)
 +def relu_prime(z):​ return np.asarray(z > 0, dtype=np.float32)
 +
 +class SemaphoreIA:​
 +    def __init__(self,​ root, learningrate,​ failed=0):
 +        self.root = root
 +        self.learningrate = learningrate
 +        self.failed = failed
 +        self.tools = MyTools()
 +
 +        # Dossier des ratés
 +        if self.failed:​
 +            # Suppression du dossier failed et recréation pour le vider
 +            try:
 +                shutil.rmtree(self.root + '​failed'​)
 +            except:
 +                print('​Pas de dossier failed'​)
 +            self.tools.create_directory(self.root + '​failed'​)
 +
 +        # 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]
 +
 +        fichier = np.load(self.root + '​semaphore.npz'​)
 +        self.x_train,​ self.y_train = fichier['​x_train'​],​ fichier['​y_train'​]
 +        self.x_train = 1 - self.x_train
 +        self.x_test,​ self.y_test = self.x_train[50000:,:​],​ self.y_train[50000:​]
 +        self.x_train,​ self.y_train = self.x_train[:​50000,:​],​ self.y_train[:​50000]
 +
 +        # Affichage des images pour distraire
 +        cv2.namedWindow('​img'​)
 +
 +    def training(self):​
 +        """​Apprentissage avec 50 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 d'un gars qui s'​appelle Xavier Glorot et d'un autre qui s'​appelle 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)):​
 +
 +            # Affichage pour distraire les mangalore
 +            if i % 10000 == 0:
 +                print(i, nombre_lettre)
 +                img = vecteur_ligne.reshape(40,​40) * 255
 +                img = cv2.resize(img,​ (600, 600), interpolation=cv2.INTER_AREA)
 +                cv2.imshow("​img",​ img)
 +                cv2.waitKey(1)
 +
 +            # 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 neurone
 +                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 proportionnellement
 +            # 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
 +
 +        # Dans un fichier
 +        np.save(self.root + '​weights.npy',​ weight_list)
 +        print('​weights.npy enregistré'​)
 +        cv2.destroyAllWindows()
 +
 +    def testing(self):​
 +        """​Teste avec 10 000 images, retourne le ratio de bon résultats"""​
 +        print("​Testing..."​)
 +
 +        weight_list = np.load(self.root + '​weights.npy'​)
 +
 +        # Nombre de bonnes reconnaissance
 +        success = 0
 +
 +        # Dict avec le nombre d'​erreurs par lettre
 +        failed_dict = {}
 +
 +        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
 +            else:
 +                if self.failed:​
 +                    self.write_failed(img,​ nombre_lettre,​ reconnu, success)
 +                if nombre_lettre in failed_dict:​
 +                    failed_dict[nombre_lettre] += 1
 +                else:
 +                    if self.failed:​
 +                        self.tools.create_directory(self.root + '​failed'​ + '/​bad_'​ + str(nombre_lettre))
 +                        failed_dict[nombre_lettre] = 1
 +
 +        if self.failed:​
 +            sorted_by_value = sorted(failed_dict.items(),​ key=lambda kv: kv[1], reverse=True)
 +            print(sorted_by_value)
 +
 +        resp = 100.0 * success / len(self.x_test)
 +        return resp
 +
 +    def write_failed(self,​ img, nombre_lettre,​ reconnu, S):
 +        """​Les images avec erreur de reconnaisance sont copiées dans
 +        /​semaphore/​failed/​bad_11/​11_6_9067.png
 +        11 est la lettre k, donc dans le dossier il ny a que la lettre k
 +        et le 2ème nombre est la lettre reconnue fausse
 +        """​
 +        name = str(nombre_lettre) + '​_'​ + str(reconnu) + '​_' ​ + str(S) + '​.png'​
 +        fichier = self.root + '​failed'​ + '/​bad_'​ + str(nombre_lettre) + '/'​ + name
 +        img = img.reshape(40,​40) * 255
 +        cv2.imwrite(fichier,​ img)
 +
 +
 +if __name__ == "​__main__":​
 +    print(MyTools().get_absolute_path(__file__))
 +    root = MyTools().get_absolute_path(__file__)[:​-28]
 +    print("​Current directory:",​ root)
 +
 +    for i in range(5):
 +        learningrate = 0.022
 +        failed = 0
 +        sia = SemaphoreIA(root,​ learningrate,​ failed)
 +        sia.training()
 +        resp = sia.testing()
 +        print("​Learningrate:​ {} Résultat {}"​.format(learningrate,​ round(resp, 1)))
 +</​file> ​   ​
 +
 +
 +===== Etape suivante: YOLO Darknet=====
 +**[[computer_vision_and_pattern_recognition_segmentation_d_image|Computer Vision and Pattern Recognition Mask R-CNN]]**
 +
 +{{tag> bge ia python sb semaphore }}
  
l_intelligence_du_semaphore.1548505074.txt.gz · Dernière modification: 2019/01/26 13:17 par serge