SE5 ECEAI/eceai 2023/2024/ValleeSellali

De wiki-se.plil.fr
Révision datée du 28 janvier 2024 à 12:47 par Fvallee (discussion | contributions) (Video)
Aller à la navigation Aller à la recherche

Groupe Vallée-Sellali

Séance n°1:

Machine virtuelle créée sur chassiron :

Hostname       :  ValSel

Distribution    :  bookworm

Stockage  : 10G

Mémoire vive : 1G

Mot de passe habituel

Les fichiers /etc/network/interfaces, /etc/resolv.conf et /etc/apt/sources.list ont été modifiés comme demandés.

Raspberry 4 :

Communication via le port série possible

Login : valsel Pwd : pasglop

STM32F401RE : Nanoedge et IDE installés, conception d'un code pour tester le capteur en cours


Séance n°2 (18/12/2023) :

Raspberry connectée au WiFi SE5

Connexion ipv6 possible entre la VM et la raspberry

Données du capteur lues et envoyées au port série

Création d'un programme python client à destination de la raspberry qui : lit le port série, stocke les données reçues, envoie les données reçues en http vers le "serveur" présent sur la VM

Création d'un programme python serveur à destination de la VM qui reçoit et stocke les données


Séance 3 (19/12/2023) :

Création des datasets : main fermée et main ouverte (Une ligne = 16 * 16 données, environ 30 lignes par fichier)

Choix de garder les capteurs en 4x4 pour un compromis vitesse de création des datasets/temps d'entrainement du modèle/efficacité du capteur de mouvement.

Entrainement du modèle avec les datasets sur NanoEdge


Séance 4 (20/12/2023)

Création de nouveaux datasets et de fichiers de tests : (100 lignes de 16 * 16 données)

Création d'un script Python utilisant la bibliothèque sklearn pour implémenter un algorithme de classification SVM, à destination de la Raspberry et de la VM

Le choix de main ouverte/main fermée se questionne, on utilise pas l'aspect mouvement que permet les algorithmes.

Les algorithmes donnent un bon résultat avec une précision proche de 70%. La communication entre la VM et la zabeth sur laquelle on teste les fichiers pythons fonctionne.

Du microcontrôleur, on reçoit les données brutes et l'estimation de l'état de la main. Le fichier python sur la zabeth, à destination future de la raspberry, reçoit ces données via le port série, les stocke dans un fichier txt, fait une estimation de l'état de la main, et envoie les données brutes à la VM en utilisant TCP/IP avec l'adresse IPV6 de la VM.

La VM reçoit les données mais ne les traite pas encore.


Travail hors des séances et rendu final :

Extension du programme sur la STM aux 64 capteurs.

Nouveau choix de test qui prend en compte les mouvements.

Création de nouveaux datasets adaptés : lignes de 64 * 16 données, une ligne correspond à une itération du mouvement, environ 170 lignes par datasets pour une prise en compte de plusieurs cas

(passage rapide, passage lent, hauteurs différentes).

Les mouvements sont :

- Mouvement de gauche à droite

- Mouvement de droite à gauche

- Aucune présence

Pour pouvoir tester les modèles résultant de ces datasets, 3 fichiers de tests sont créés contenant chacun une trentaine d'itérations du mouvement.

Avec Nanoedge, entraînement d'un nouveau modèle à destination de la STM. Le modèle le plus efficace avec nos fichiers de tests sont, contrairement aux premières séances, un modèle MLP (multilayer

perceptron). Résultats avec nos fichiers de tests : précision de 90%

En effet, les modèles SVM ne semblent pas adaptés à nos datasets => Adaptation du code python de la raspberry pour utiliser lui aussi un modèle MLP, ce qui est plus efficace.

Modèle résultant avec comme input les fichiers de tests : 70% de précision sur Droite à gauche, 68% de gauche à droite, 100% si aucune présence.

Intégration du code GestionData.py dans la raspberry ainsi que du modèle créé par mlpAlgo.py (uniquement l'output)

Réseau :

- La STM32 envoie les données brutes + l'estimation du mouvement issue de son modèle intégré par le port série (knowledge.h, nanoEdgeAi.h, libneai.a et appTof.c sont disponibles en annexe)

- La Raspberry Pi reçoit ces données brutes, les stocke dans un fichier texte, estime le mouvement effectué, et affiche l'estimation en plus de celle de la STM. Ensuite, les données brutes sont transmises à la VM par TCP/IP en IPV6, à la condition que 1024 données soient présentes à chaque lecture. Si ce n'est pas le cas, les données "corrompues" ne sont pas transmises puisqu'inexploitables. (Voir GestionData.py en annexe)

- La VM reçoit les données par paquet de 1024 entiers, stocke les données dans un fichier txt, et fait une estimation du mouvement en utilisant le même modèle que celui présent dans la raspberry pi.


Lors des tests, nous avons constaté que la communication TCP ne semblait pas permise depuis un ordinateur externe au réseau des zabeths vers la VM : le ping est possible, mais la communication ne semble pas. Nous avons donc fait le choix d'utiliser un ordinateur personnel pour montrer l'efficacité du projet : le fonctionnement est similaire, les données sont envoyées sur la machine personnelle en IPV6.


#Vidéo :


#Annexe

Tous les codes rendus en annexe sont dans leur version finale et ont été utilisés au cours du projet.

Codes externes ayant servis à l'entraînement :

Les fichiers de type data ou test ont été réalisés en lisant le port série et en insérant directement les données dans le fichier texte à condition que les données ne soient pas corrompues.

mlpAlgo.py : programme permettant de générer un modèle utilisant l'algorithme MLP

#Import mlp model
from sklearn import neural_network
from sklearn import metrics
import joblib

GtoD_path = 'data_GtoD.txt'
DtoG_path = 'data_DtoG.txt'
GtoD_test_path = 'test_GtoD.txt'
DtoG_test_path = 'test_DtoG.txt'
rien_path = 'data_rien.txt'
rien_test_path = 'test_rien.txt'

GtoD_train = []
DtoG_train = []
GtoD_target = []
DtoG_target = []
rien_train = []
rien_target = []
test = []
data = []
targets = []
target_test = []

def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):
    try:
        # Ouverture du fichier en mode lecture
        with open(nom_fichier, 'r') as fichier:
            # Lecture du contenu du fichier ligne par ligne
            lignes = fichier.readlines()

            # Pour chaque ligne, conversion en liste d'entiers
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]
            target_tab = len(tableau_filtre) * [target_int]

        return tableau_filtre, target_tab
    
    except FileNotFoundError:
        print(f"Le fichier {nom_fichier} n'a pas été trouvé.")
        return []
    except Exception as e:
        print(f"Une erreur s'est produite : {e}")
        return []

# Exemple d'utilisation
GtoD_train, GtoD_target = ReadAndFill(GtoD_path, GtoD_target, 2)
DtoG_train, DtoG_target = ReadAndFill(DtoG_path, DtoG_target, 1)
rien_train, rien_target = ReadAndFill(rien_path, rien_target, 0)
data = GtoD_train + DtoG_train + rien_train
targets = GtoD_target + DtoG_target + rien_target

#Create a svm Classifier
clf = neural_network.MLPClassifier(max_iter=5000000)

#Train the model using the training sets
clf.fit(data, targets)
joblib.dump(clf, 'modele_mlp2.pkl')

test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)

#Predict the response for test dataset
pred = clf.predict(test)
print(pred)
# Model Accuracy: how often is the classifier correct?
print("Fichier de test actuel :",GtoD_test_path)
print("Accuracy:",metrics.accuracy_score(target_test, pred))

test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)

#Predict the response for test dataset
pred = clf.predict(test)
print(pred)
# Model Accuracy: how often is the classifier correct?
print("Fichier de test actuel :",DtoG_test_path)
print("Accuracy:",metrics.accuracy_score(target_test, pred))

test, target_test = ReadAndFill(rien_test_path, target_test, 0)

#Predict the response for test dataset
pred = clf.predict(test)
print(pred)
# Model Accuracy: how often is the classifier correct?
print("Fichier de test actuel :",rien_path)
print("Accuracy:",metrics.accuracy_score(target_test, pred))

mlpPredic.py : Code similaire servant à tester de charger un modèle créé et sauvegardé auparavant

#Import mlp model
from sklearn import neural_network
from sklearn import metrics
import joblib

GtoD_test_path = 'test_GtoD.txt'
DtoG_test_path = 'test_DtoG.txt'
rien_test_path = 'test_rien.txt'

test = []
data = []
targets = []
target_test = []

def ReadAndFill(nom_fichier, target_tab, target_int, taille_sous_liste=1024):
    try:
        # Ouverture du fichier en mode lecture
        with open(nom_fichier, 'r') as fichier:
            # Lecture du contenu du fichier ligne par ligne
            lignes = fichier.readlines()

            # Pour chaque ligne, conversion en liste d'entiers
            tableau = [[int(nombre) for nombre in ligne.split()] for ligne in lignes]
            tableau_filtre = [sous_liste for sous_liste in tableau if len(sous_liste) == taille_sous_liste]
            target_tab = len(tableau_filtre) * [target_int]

        return tableau_filtre, target_tab
    
    except FileNotFoundError:
        print(f"Le fichier {nom_fichier} n'a pas été trouvé.")
        return []
    except Exception as e:
        print(f"Une erreur s'est produite : {e}")
        return []

#Create a svm Classifier
clf = joblib.load('modele_mlp.pkl')

test, target_test = ReadAndFill(GtoD_test_path, target_test, 2)

#Predict the response for test dataset
pred = clf.predict(test)
print(pred)
# Model Accuracy: how often is the classifier correct?
print("Fichier de test actuel :",GtoD_test_path)
print("Accuracy:",metrics.accuracy_score(target_test, pred))

test, target_test = ReadAndFill(DtoG_test_path, target_test, 1)

#Predict the response for test dataset
pred = clf.predict(test)
print(pred)
# Model Accuracy: how often is the classifier correct?
print("Fichier de test actuel :",DtoG_test_path)
print("Accuracy:",metrics.accuracy_score(target_test, pred))

test, target_test = ReadAndFill(rien_test_path, target_test, 0)

#Predict the response for test dataset
pred = clf.predict(test)
print(pred)
# Model Accuracy: how often is the classifier correct?
print("Fichier de test actuel :",rien_test_path)
print("Accuracy:",metrics.accuracy_score(target_test, pred))

Codes internes à la STM :

Codes internes à la Raspberry pi :

Codes internes à la VM (présents en réalité sur la machine personnelle) :