Récents articles

Cours web frontend - Angular 8

Chap 2 : Initialisation de notre première application

On a vu comment installer les dépendances nécessaires à une application web dans le chapitre précédent.

On va maintenant voir comment générer le squelette de base d’une application en Angular 8.

Création de l’app

On va générer notre application avec la commande CLI suivante :

  • ng new NomdeL’app

 

CLI va nous demander plusieurs questions concernant la génération :

Angular routing : nous le verrons dans un prochain chapitre. Cela permet de gérer la navigation au sein de l’application. On ne va pas s’en servir dans le chapitre actuel, mais vous pouvez mettre Oui.

Choix des feuilles de style : CLI nous propose entre CSS, SCSS et Sass. Le CSS étant le plus commun, on va garder celui-ci. Sachez que le compilateur transformera le SCSS et Sass en CSS. Ces deux derniers permettent juste une écriture des styles de façon plus lisible et rapide. Ce choix n’est pas définitif puisque vous pourrez le changer à n’importe quel moment plus tard dans le développement de votre application.

Comparaison syntaxique entre 3 langages de style

Cli va nous générer des fichiers. Pas besoin de savoir l’utilité de chaque pour le moment, nous le verrons dans le prochain chapitre. On va se déplacer dans le fichier racine du projet :

  • cd NomdeL’app

Pour enfin lancer :

  • ng serve

Cette dernière commande va nous permettre de build notre application. Et celle-ci est pratique, puisqu’il suffira de changer une seule ligne de code dans notre projet, pour que le projet soit re-buildé automatiquement, et que l’on voit les modifications dans le navigateur en temps quasi-réel.

 

Vous n’avez plus qu’a lancer votre navigateur préféré et aller sur :

  • http://localhost:4200/

 

Eeeeeeeeeh TADAAAAAAA

Je vous l’accorde ce n’est pas ouf. Mais c’était rapide non ?

 

Avant d’aller plus loin dans  la customisation de notre application web, dans le prochain chapitre 3, nous ferons une halte pour comprendre l’ensemble des composants crées précédemment.

Cours web frontend - Angular 8

Chap 1 : Installation des pré-requis

Pour créer le frontend d’une application avec le framework Angular, il va nous falloir installer quelques dépendances nécessaires. Rassurez-vous, rien de bien long 🙃

 

Node.Js & NPM

Pour faire simple, c’est un framework en Javascript permettant de réaliser des serveurs pour le backend. On en a besoin puisqu’il va nous fournir NPM. C’est le gestionnaire de packet pour le web, comme NuGet pour le C#, ou encore PiP pour Python. Il va nous permettre d’installer pleins de librairies nous facilitant le développement de notre application.

 

Vous pouvez le récupérer sur son site https://nodejs.org/en/

Installer la version que vous souhaitez cela importe peu. Il va créer un dossier Node sur le disque C. Vous devrez rajouter ce dossier C:\ProgramFiles\Node\ au PATH des variables d’environnement de votre système d’exploitation, pour que nous puissions utiliser les alias dans la console.

On peut alors tester que tout fonctionne correctement :

C’est OK pour nous, on a bien Node.Js et NPM qui sont accessible.

 

Angular & Angular/Cli

La prochaine étape va être d’installer la librairie Angular. Mais pourquoi alors parler de Angular/Cli ? CLI est une interface de ligne de commande pour Angular, une sorte d’extension. Elle va nous permettre de faciliter la création d’une application Angular par la suite en créant à notre place toute sorte d’objets pré codés, nous permettant alors de gagner un certain temps.

Dans une console on va alors se mettre à la racine du projet duquel on souhaite créer, et exécuter :

  • npm i @angular/cli

 

Vous pouvez voir l’ensemble des packets installé via :

  • npm list –depth=0

L’attribut –depth est facultatif. Il permet de réduire l’arbre des dépendances de l’ensemble des packets pour y voir plus claire

 

Nous voilà OK pour le chapitre suivant, auquel on va pouvoir initialiser notre première application !

 

optimisation hyper parametres gridsearch cv Cours théoriques - Deep learning

Réglages des hyper-paramètres

Workflow du CVGridSearch de SkLearn

Avoir un modèle qui fonctionne, c’est bien. Mais avoir un modèle optimisé, c’est mieux. Et il existe une multitude d’expérimentations et diverses techniques pour nous permettre de grappiller davantage de précision quant à la fiabilité de prédire de nouvelles données.

Je vous explique sans plus tarder comment régler au mieux l’ensemble des hyper paramètres de votre réseau de neurones. Je vous ai créé un dépôt sur Github (clique, clique 🙃) reprenant l’ensemble des bouts de code cités plus loin dans cet article.

 

Différence entre paramètres et hyper-paramètres

Un paramètre est interne au réseau de neurones. Il va évoluer durant l’ensemble du processus d’entrainement, lors de la backpropagation ( plus d’infos ici ).

Un hyper-paramètre est à l’inverse d’un paramètre, externe au processus d’entrainement, il en définit des propriétés. Il reste statique durant l’entrainement ( ex : batch size, epoch, learning rate…).

 

Optimisation des hyper-paramètres

Prenons un exemple simple. On souhaite optimiser deux hyper paramètres, qui sont le batch size et l’optimizer. On sait que le choix d’un hyper-param aura des conséquences sur l’apprentissage. On en connait les grandes lignes sur tel ou tel impacts qu’ils amènent, mais pour certains on ne sait pas d’avance quelles en sont les meilleures combinaisons entre eux.

 

Comment s’y prendre pour choisir les meilleures synergies ?

Le principe serait de tester diverses combinaisons. Vous avez la solution de créer autant de modèle que d’autant de combinaisons possibles. C’est redondant, lent, obligé de les lancer un à un ( si en plus vous en oubliez pas 😅 ). Ou vous avez la solution simple, rapide et efficace. Merci la GridSearchCV de Scikit-learn ! 😎

matrice hyper parametre
Tableaux contenant l’ensemble des combinaisons possible pour deux valeurs entre deux hyper-paramètres

Celle-ci va se charger toute seule d’effectuer autant d’entraînements que l’on à de combinaisons d’hyper-paramètres, et ce en quelques lignes de code.

 

La première chose à faire est de définir des listes de valeurs que l’on souhaite tester sur l’ensemble de nos hyper-paramètres :

 

On crée un dictionnaire regroupant l’ensemble de nos hyper-params précédent :

Vous pouvez cependant faire d’une pierre deux coups ces étapes précédente, je les dissocie pour bien expliquer 😉

 

Je vous passe l’ensemble des pré-process des données, ce n’est pas le but de ce chapitre aujourd’hui.

On va ensuite définir une fonction pour nous retourner un model construit :

Il se peut que vous ayez une erreur de paramètre non reconnu. Si cela vous arrive, vous devrez ajouter ce paramètre en argument de cette fonction, comme je l’ai fait dans l’exemple pour l’optimizer qui n’était pas reconnu.

 

On va ensuite wrapper notre modèle dans un KerasClassifier. Cette étape est primordiale, car c’est elle qui va nous permettre d’utiliser l’api de Scikit-Learn avec un modèle de Keras :

 

On va pouvoir associer un modèle avec notre dictionnaire englobant l’ensemble de nos combinaisons que l’on souhaite tester, et lancer l’entrainement sur notre jeu de données :

Vous pouvez lui passer en paramètre deux arguments qui peuvent être utile selon moi :

  • n_jobs : int or None, optional (default=None) : nombre de jobs à faire tourner en parallèle. Il est à défaut à 1. Pour utiliser l’ensemble des cœurs de votre processeur, mettez-le à -1.
  • cv : int, cross-validation generator or an iterable, optional :  détermine la stratégie de cross validation à utiliser. Par défaut à 3.

 

Une fois entraîné, on va pouvoir récupérer :

  • La combinaison d’hyper-paramètres qui nous a donné le meilleur score ( ligne 1 )
  • Le score de la meilleure combinaison ( ligne 2 )
  • Ou encore l’ensemble ( ligne 3 )

 

Petite astuce si vous souhaitez tester le meilleur modèle sur un nouveau jeu de données, de test par exemple. Vous devrez récupérer dans un premier temps le modèle généré par les meilleurs hyper-paramètres, puis ensuite l’évaluer sur le jeu de donnée souhaité.

resultat metriques
Résultats des métriques définit dans le code source précédent

 

Recherche quadrillage ou recherche aléatoire ?

On penserait qu’une recherche par quadrillage nous permet d’essayer l’ensemble des combinaisons possible, et donc forcément d’obtenir les meilleures valeurs. Cependant, un entrainement d’un tel réseau nécessitant du temps et une puissance de calcul importante, cela reste une solution techniquement très lente à mettre en place, et donc étant finalement une solution peu efficace contre rendu de nos diverses contraintes.

 

Exemple : Tester 3 hyper-paramètres, de range 1 à 100

Exemple d’une recherche par quadrillage : (padding de 1)

  •                 100 x 100 x 100 = 1 million de possibilités

Exemple d’une recherche aléatoire : (padding de 10)

  •                10 x 10 x 10 = 1 000 possibilités

 

On se rends facilement compte avec cet exemple, que la recherche aléatoire de variables prise aléatoirement dans une fourchette donnée, nous permet de tester bien plus de valeur sur un même temps donné. Si c’est plus rapide, on sera donc plus efficace via ces sauts de valeurs.

 

De plus, des articles scientifiques ont démontré qu’une recherche aléatoire donnait de meilleurs résultats, car certains paramètres ont d’avantages d’impact par rapport à d’autre concernant l’optimisation de la fonction de perte. En effet, ceux-ci ne sont pas tous équivalent à paramétrer.

cv gridsearch scikit learn
Comparaison entre une recherche par quadrillage et aléatoire pour optimiser une fonction

 

Références 

Random Search for Hyper-Parameter Optimization, James bergstra & Yoshua Bengio

 

transfer learning Cours théoriques - Deep learning

Transfer learning

En rédigeant mon dernier cours sur comment réaliser un recommandeur de hashtag pour image, j’ai utilisé une nouvelle approche pour me permettre de déployer mon projet de data science bien plus rapidement et efficacement ( du moins pour une première version ). Cela a dû être une nécessité pour la simple et bonne raison que c’est la première fois que je vous propose un cours avec un jeu de données bien plus conséquent que les autres fois.

Je vous présente de ce pas, le transfer learning 😏

Schéma du fonctionnement du transfer learning

Généralité

Définition

Le transfer learning comme son nom l’indique, est une approche permettant de transférer le savoir d’un modèle, à un autre. En l’occurrence, transférer les poids d’un modèle pré entraîné à une tâche précise, pour les associer à un autre modèle.

Dans des problématiques réelles ou l’on traite de data science, la vrai, vous allez vous taper le nez contre des dataset gigantesque pour permettre d’avoir un modèle qui couvre le maximum de cas possible, permettant de réaliser les meilleures généralisations sur de nouvelles variables. Le soucis étant que vous n’aurez peut-être pas ( comme moi à l’heure actuelle 😅 ) la puissance de calcul nécessaire pour réaliser ces opérations, vous obligeant à rester sur des inputs soit en quantité réduite, soit en qualité réduite. L’un comme l’autre a un effet nuisant à la bonne performance de votre modèle.

On peut se poser la question comment un réseau pourrait fonctionner sur un nouveau jeu de données, si celui-ci n’a rien à voir par rapport à celui sur lequel il a appris. Et bien il va falloir le ré-entraîner sur les nôtres, et pas de n’importe quelle façon, puisque que si on le ré-entraîne de la plus simple des manières, cela reviendrait au même de faire notre propre modèle à partir de zéro. On souhaite qu’il garde les plus grandes notions qu’il a appris durant son entrainement bien plus long que l’on ne pourrait le faire, et surtout sur l’importante quantité d’images que l’on ne pourrait rassembler sur un projet personnel, ou du moins sur un projet qui débute.

On va alors geler les couches basses du réseau, celle qui sont responsable de la détection de caractéristiques simples. On pourrait parler de formes géométriques simple dans le cas d’une classification d’image, pour vous donner une idée, tel que des traits horizontaux et verticaux. Ces formes simples étant la base de la constitution de n’importe quelles formes et structures, nous n’aurons pas besoin de les modifier. En d’autres termes, ce gel se traduit par l’impossibilité pour ces couches de neurones, de changer leurs poids.

Pour adapter le réseau à nos données, on va devoir ajouter notre propre classificateur qui va être adapté à nos données. Pour cela, on va supprimer les couches décisionnelles ( les couches dîtes hautes, qui servent à classifier correspondant aux couches de neurones entièrement connecté, appelé dense layer ou fully connected layer) du réseau pré-entraîné afin de pouvoir les remplacer par les nôtres, qui elles vont pouvoir apprendre les formes de plus en plus complexe, et donc pouvoir s’adapter à nos données qu’il n’aura jamais vu auparavant lors de son entrainement de base. C’est donc cette dernière étape qui va nous permettre d’adapter n’importe quel modèle sur un autre cas d’utilisation

 

Les grandes lignes de votre workflow pour mettre en place cette stratégie vont être les suivantes :

  • Récupération d’un modèle pré entraîné,
  • Adaptation de la structure du modèle à vos propres données d’entrées, et surtout à vos données de sortie souhaités,
  • Ré-entrainement partiel du modèle pré entraîné sur votre propre jeu de données.

 

Quand l’utiliser et pour quels avantages

  • Modèle déjà existant : il peut exister qu’une personne ait déjà rencontré la même problématique que vous. Il se peut donc qu’un modèle existe déjà pour la tâche que l’on essaye de traiter.
  • Pas assez de data : il se peut aussi que vous n’ayez pas assez de données pour pouvoir entraîner un modèle de A à Z
  • Pas assez de puissance de calcul : entraîner qu’une infime partie des couches d’un réseau de neurones va pouvoir accélérer son apprentissage

On peut alors traduire l’ensemble des points précédent par une diminution des contraintes techniques, ainsi qu’un gain de temps général.

 

Mise en place du code

La première chose va donc être de récupérer un modèle pré entraîné. Vous avez quelques choix concernant le traitement d’images sur le site de Keras. Mais vous avez des zoo, qui sont des répertoires entier de modèles pré-entraînés et gracieusement partagés par la communauté. Vous aurez donc peut être des chances d’avoir des personnes ayant travaillés sur des projets relativement proche du votre. Du moins, ça vaut le coup d’y jeter un coup d’œil. Une fois trouvé, téléchargé le modèle au format .hdf5 et chargez le.

Dans mon cas je vais en récupérer un directement depuis le site de Keras. Extrêmement pratique puisque on a le choix de vouloir ou non les couches de décisions. On ne les souhaite pas, afin d’adapter ce modèle à nos données.

 

Ensuite on gèle les couches basses du réseau :

 

On ajoute nos couches de décisions composée de fully connected :

 

On instancie un nouveau model en concaténant l’entrée du model de base, et la sortie de la dernière couche que nous venons d’ajouter à précédemment, ce qui nous donne :

 

Je ne vous joins pas le reste du code, mais vous n’avez plus qu’à compiler le modèle et l’entraîner avec les mêmes fonctions et argument que vous avez l’habitude d’utiliser, à savoir :

  • model.compile(…);
  • model.fit(…);
recommandeur hashtag image Cours pratiques - Deep learning

Classification d’images multi labels/classes

Pour ce nouveau cours, je vous propose de revenir sur de la classification d’image. Contrairement à mon cours sur la classification d’image simple, celui-ci sera légèrement différent en utilisant de la classification d’une multitude de label pour une même image donnée.

Le but est de créer un système permettant de proposer des hashtags en fonction d’une image donnée en entrée. Nous resterons sur nos outils habituels, à savoir Tensforflow en backend et Keras pour l’API de haut niveau, nous facilitant la mise en place d’un réseau de neurones, qui utilisera de la convolution pour cette fois-ci.

Comme d’habitude, le code source entièrement documenté est sur mon Github, libre à vous de venir pour me faire part d’éventuels correctifs et optimisation.

C’est parti ! 😉

ATTENTION : On va commencer à travailler sur des dataset assez conséquent en termes de taille, comparé aux autres tutoriels. Ce cours a pour principal but d’expliquer des méthodes, un cheminement, ainsi que des astuces pour constituer un projet en data science, et non pas d’avoir des modèles ultra performants, sinon je serais sur kaggle et non pas sur mon site perso. Travaillant sur un ordinateur portable dépourvue de carte graphique, je ne peux malheureusement pas entraîner de modèle performant.

resultat prediction
Résultat d’une prédiction de hashtag, pour une image donnée

Pré-requis

Nullement besoin d’être top 1 europe Kaggle pour comprendre mon code. Mais si vous souhaitez aller plus loin dans ce cours et pousser les performances de votre modèle, je peux vous conseiller deux autres articles qui vous seront utile :

 

Concernant le code, on va avoir besoin de quelques librairies externe pour ce projet.  Je vous laisse gérer leur installation via Conda ou Pip selon vos préférences et environnement à chacun :

  • Tensorflow
  • Keras
  • Pandas ( gestion de tableaux performants pour la lecture et écriture de certaines de nos données )
  • TQDM ( outils permettant de créer des barres de chargement au sein d’un shell, utile pour savoir où on en est du traitement de données en temps réel )
  • PIL ( gestion d’image pour leur lecture et écriture )
  • HARRISON dataset (torrent)
  • Fix image corrompue + liste méta data

 

Constitution du dataset

Pour créer un dataset, vous devrez crawler des réseaux sociaux proposant des images ainsi que des hastag, facilement récupérable via leur API. Je pense sans trop me tromper que les deux plus grands sont Instagram ainsi que Flickr.

 

Crawler FlickR

Directement via leur API public : https://www.flickr.com/services/api/

 

Malheureusement pour nous, Instagram a depuis quelques années, restreint l’accès à leur API, nous empêchant de récupérer nos données. Il existe néanmoins certaines astuces pour contourner tout ça.

 

Crawler instagram, Astuce 1

Vous pouvez récupérer des informations sur des profiles avec pas mal d’informations sous format JSON. Avec un simple parseur, vous pourrez faire votre propre outil de crawl via de simple liens :

Avoir des informations au format JSON pour un profil spécifique :

  • https://www.instagram.com/{pseudo_du_profil}/?__a=1

Vous pouvez donc avoir accès aux profils que vous souhaitez, si et seulement si celui-ci est en public.

Avoir des informations au format JSON concernant un hashtag spécifique :

  • https://www.instagram.com/explore/tags/{hashtag_a_tester}/?__a=1

Ne vous en faîte pas, vous pouvez récupérer les images via les liens disposés dans le fichier JSON.

 

Crawler instagram, Astuce 2

Certains malins ont réussi à faire des outils bien plus pratique comme celui-ci (instagram-scrapper). Pour l’avoir utilisé, vous pouvez effectuer des recherches selon des hashtag, et donc créer son propre dataset avec ses propres classes souhaitées.

 

Utiliser des dataset pré-existant

Comparatif de 3 dataset comportant des images associés à des hashtag

Je n’ai pas voulu perdre trop de temps à constituer mon propre dataset, et me concentrer sur mon algorithme. J’ai trouvé deux dataset pouvant être intéressant pour notre projet :

  • HARRISON : Celui qui me semble le plus adapté pour notre projet. En effet, il est plus récent, et crawler depuis instagram même. Bon compromis pour la taille. Chaque image comporte de 1 à 10 hashtag
  • MIRFLICKR : Peut donner éventuellement de meilleurs résultats car composé de bien plus d’images. Cependant, il est plus orienté photo que réseau social ; je m’explique. Ses tags sont principalement orientés pour la photographie, à en suivre le schéma suivant, qui montre le top des 10 hashtag les plus cités sur nos deux dataset. Je ne pense pas dans le cadre de notre projet, le fait de mentionner un constructeur (nikon,canon…)  apportent une plus valus pour notre recommandeur. En effet, lors de la constitution de ce dataset, les chercheurs ont utilisé le fichier EXIF ( Exchangable image file format ) qui sont associés à chaque photo , lorsque on est sur la plateforme Flickr.  Ce fichier contient des méta données concernant une multitude de paramètres sur les appareils photos ( constructeur, exposition, ouverture, taille des focales et objectifs, iso, résolution, compression, etc…).
comparatif top 10 word dataset
Top 10 des hashtag les plus présents

 

Pré traitement de nos données

Le dataset HARRISON est constitué de la façon suivante :

structure harrison dataset
Structure du dataset HARRISON

La façon dont est organisé le rangement des classes par dossier est parfait pour notre réseau, on ne touchera pas leur agencement. Cependant, on ne peut en dire autant pour la partie des fichiers texte qui contient l’ensemble de nos métas données qui caractérise nos classes d’images. On va devoir faire quelques arrangements.

La première étape va être de rassembler les liens des images avec leur hashtag respectif (data_list.txt & tag_list.txt) dans un seul et même fichier :


 

La seconde étape va être de changer le format du fichier vocab_index ; on supprime les espaces inutiles, et on forme des couples => « nomTag, idTag » :

 

Constitution du modèle & entrainement

On va pouvoir passer à la partie la plus fun des réseaux de neurones, entraîner notre réseaux (forcement, on a rien à faire 😎 ).

Petite astuce en cas de présence d’images qui seraient corrompues. Sois-vous téléchargez les deux images qui nous remontent des erreurs qui sont disponible sur le Github du dataset et vous aller les remplacer dans leurs dossier respectifs, soit vous pouvez forcer PIL à traiter ces images ci :

 

On va charger nos fichiers contenant nos métas donnés :

La 3ème ligne va être extrêmement importante, puisque on souhaite faire comprendre à notre réseau que l’image 2 contient à la fois le label « SNOW » et « MOUNTAINS » séparé par notre virgule, et non un seul label « SNOW,MOUNTAINS ». Pour cela on va convertir chacune de nos entrées en liste.

 

Nous pouvons définir l’ensemble de nos variables globales :

  • NB_CLASSES : va permettre de définir le nombre de neurone dans notre dernière couche du réseau. Nous souhaitons un neurone par classe, qui va permettre de déterminer la probabilité de la présence ou non de cette classe, qui sera entre 0 et 1.
  • NB_EPOCH : nombre d’époque durant l’entrainement. L’entrainement étant extrêmement long, je le laisse à 1 par obligation.
  • BATCH_SIZE : nombre de donnée envoyé dans le réseau par itération.
  • SHUFFLE : permet de mélanger les données. Important puisque dans nos fichiers, ils sont listés classe par classe et donc à la suite. On souhaite que le réseau apprenne de façon équilibré et arbitraire.
  • IMG_SIZE : permet de resize nos images. Correspond à la taille de tenseur en input du réseau.
  • TRAINSIZE_RATIO : définit le ratio entre jeu de donnée d’entrainement et de validation
  • TRAINSIZE : nombre d’image pour le jeu d’entrainement
  • LIST_CLASS : liste de nos labels
  • DIRECTORY_DATA : répertoire parent contenant le dataset harrison
  • DIRECTORY_TRAINED_MODEL : répertoire ou on va aller sauvegarder notre modèle, une fois qu’il sera entraîné.
  • COLOR_MODE : permet de choisir entre des images en couleurs, ou en grayscale.

 

On va ensuite définir nos appels de retours ( callback ) appelé à la fin de chaque itération :

  • modelCheckPoint : va permettre de définir comment on souhaite enregistrer notre modèle : répertoire, avec ou sans poids, etc.
  • earlyStopping : va permettre de juger l’évolution d’une métrique (validation_accuracy) sur le jeu de donnée. Si celle-ci n’évolue plus selon un certain paramètre défini, un certain gap (patiente), on stop l’entrainement

 

Nous allons ensuite charger nos images en mémoire. Contrairement au cours sur la classification d’image, on va utiliser un outils concu dans Keras qui est le ImageDataGenerator. Il va nous permettre des choses bien plus poussé contrairement à la méthode que j’avais pu utiliser il y a de cela quelques mois pour le chargement des images. J’avais à l’époque utilisé Numpy pour lire mes images, les transformers en tenseur, et les enregistrer sur le disque. Pour enfin dans un second temps les relire pour les charger en mémoire. L’avantage des imagesDataGenerator sont multiples

  1. Une seule lecture, pas d’écriture.
  2. C’est un générateur ; il envoie les données au fur et à mesure et permet donc de traiter de datasets bien plus volumineux car ne charge pas TOUT le dataset en RAM.

On a donc un gain de mémoire et de temps.

On définit une normalisation des données. Cela permet de traiter des données des images compris entre 0 et 1, et non plus sur l’ensemble de leurs échelles de couleurs RGB, qui s’étend de 0 à 255, ce qui permet une meilleure compréhension de la part de notre réseau ; il n’aime pas vraiment les valeurs extrêmes.

 

La classe ImageDataGenerator nous fournit 3 principales méthodes :

  1. flow()
  2. flow_from_directory()
  3. flow_from_datadrame()

C’est cette dernière que nous allons utiliser pour traiter nos images.

Nous allons créer un générateur pour nos images du jeu de donnée d’entrainement, ainsi qu’un second pour celle de validation. On va pouvoir lui fournir en entrée notre dataframe chargé précédemment avec l’ensemble des chemins vers nos images, avec leurs labels associés. Les principaux attributs que l’on va utiliser sont :

  • dataframe : dataframe contenant les méta données. Bien faire attention a dissocier les images du jeu d’entrainement et de validation à donner à nos deux générateur.
  • directory : répertoire contenant nos images.
  • x_col : nom de colonne contenant les chemins.
  • y_col : nom de colonne contenant les labels.
  • shuffle : permet de mélanger les images.
  • class_mode : choix entre le mode binaire ( deux classe à prédire ) ou categorical ( plusieurs ).
  • target_size : choix de la taille des images en entrée.
  • color_mode : choix entre images en couleurs, ou grayscale.
  • classes : listes des labels

 

Petit point à ne pas oublier pour la suite du projet, lorsque vous voudrez tester votre modèle pour effectuer de nouvelles prédictions sur de nouvelles images. Chose que j’ai bien entendu oublier lors du lancement du fichier pour la première fois 😅.

A savoir le fait d’enregistrer les labels avec leurs indices, sous format JSON pour faciliter le parsage par la suite du fichier. C’est grâce à lui que on pourra retrouver les labels en sortie dans la dernière couche de neurone du réseau.

 

Pour gagner du temps, on va effectuer du Transfer learning. On va récupérer un réseau qui sera pré entraîné sur un jeu de donne ( IMAGENET ). Dans ce cas-là, on va utiliser MobileNetV2, en précisant la taille d’entrée de nos images avec le nombre de canaux souhaité (3 pour couleurs, 1 pour grayscale). Ce qui nous donne la dimension d’entrée de (96,96,3). On lui indique que on ne souhaite pas avoir ses couches de décisions finales, et que on souhaite du max_pooling sur les couches de pooling.

Etant donnée que les images de IMAGENET et de notre dataset sont différentes, on aura donc des sorties différentes. C’est pour cela que précédemment je ne souhaitais pas d’inclure leurs couches supérieures. On va ajouter nos propres couches de décisions pour que le réseaux MobileNet soit utilisable sur nos images à nous. Cependant, on va geler les couches profondes pour qu’elle ne puisse pas être modifié lors de notre entrainement. C’est ça le but du transfer learning, utilisé des réseaux pré entraîné, mais en modifier la surcouche pour qu’il soit adapté à nos problèmes, tout en gardant les couches profondes intactes pour gagner du temps lors de l’entrainement.

La dernière ligne va nous permettre d’indiquer les entrées et sorties de nos deux modèles pour permettre de les fusionner afin d’en avoir un seul et unique. On n’oublie pas de compiler notre modèle en choisissant un optimizer de son choix. Vous pouvez trouver d’avantages d’optimizer ici.

Concernant la fonction d’objectif, il y a un article scientifique qui aurait démontré qu’avec un environnement ou les poids sont choisi de façon aléatoire à l’initialisation du réseau, que la cross-entropy serait plus performante que la mean-squared-error pour trouver un minimum local. L’article est disponible ici si vous souhaitez d’avantages d’informations, et vous pouvez trouver d’avantages de fonction de perte ici.

 

Dernière étape de ce chapitre, l’entrainement du réseau.

  • generator : définit le générateur du jeu de donnée d’entrainement.
  • validation_data : définit le générateur du jeu de donnée de validation.
  • callback : définit les appels de retours effectué à chaque fin d’époque.

 

Prédiction sur de nouvelles images

Le but est de créer un nouveau fichier ou on va devoir redéfinir le même environnement de pré-traitement des images que lors de l’entrainement, pour lui donner à notre modèle, des formats d’images identiques à celui durant lequel il a appris. La première étape va donc être de créer un fichier texte pour indiquer les chemins des images que l’on souhaite prédire leurs hashtags, en remplissant notre fichier imgTest.Txt.

 

On va donc pouvoir ensuite charger le modèle, charger notre dataframe contenant nos chemins vers nos images de test, accompagné de leurs labels respectifs.

Ensuite, on va recréer notre ImageDataGenerator avec les mêmes paramètres de normalization d’image que on avait lors de l’entrainement.

 

On va pouvoir définir notre générateur de prédiction basé sur notre modèle entraîné :

 

Pour une image en entrée, nous auront une sortie composée de 1000 prédiction entre 0 et 1, correspondant à nos 1000 classe.

On va devoir définir un interrupteur booleen, pour lequel on lèvera si un label est présent ou non dans une image si la prédiction de celui-ci dépasse la valeur de l’interrupteur. Pour notre modèle, on lève un flag de présence si une prédiction pour une classe donnée dépasse 10% de probabilité. On se chargera par la suite à charger notre fichier JSON crée précédemment.

 

On va ensuite itérer sur l’ensemble de nos images séparément :

On va pouvoir comparer le tableau de probabilité à la suite d’une prédiction d’une image, avec notre fichier JSON. Cela va nous permettre de savoir à quel label appartient tel ou tel flag qui aura été levé, vu que on a seulement sa position dans le tableau à la suite d’une prédiction.

 

Dernière étape du projet :

On va récupérer l’ensemble des chemins des images que l’on a insérer dans notre générateur de prédiction, et les fusionner à notre tableau des sorties de labels effectué précédemment. A votre souhait de vouloir les afficher dans la console, ou les enregistrer dans un fichier csv.

 

 

Axe d’amélioration

  • Vers une reconnaissance de lieux ou de monuments ?

En effet, on a peu parlé du fichier EXIF que compose les images venant de Flickr. Mais on pourrait penser à l’exploiter davantage pour éventuellement avoir de nouveaux types d’informations pertinentes qui pourrait nous renseigner, afin d’avoir un système permettant une reconnaissance de monuments connus, ou encore de lieux grâce aux données géographique présent, via la latitude et longitude.

 

Conclusion

Nous venons de voir à travers de ce projet comment réaliser un recommandeur de hashtag selon une image en entrée. Mais celle-ci est en réalité une simple classification d’image à multi label. On peut le comparer à une classification simple d’image comme sur mon cours sur comment classifier des fleurs. Les principaux changements entre ces deux types de classifieurs seront les suivant :

comparatif classification sortie multiple et sortie unique
Comparatif des différences entre un classifieur à sortie unique et un classifieur à sortie multiple
  • Fonction d’activation : Pour la dernière couche d’un classifieur à sortie unique, on souhaite une seule classe qui corresponde à notre donnée d’entrée. Par exemple un classifieur chien/chat ne nous donnera qu’une de ces deux classes en sortie. On a donc un impact entre les deux classes, elles sont dépendantes. En effet quand le modèle pense détecter une forte proba pour une classe ( chien 95% ), l’autre classe sera donc faible ( chat 5% ), car c’est les probas de l’ensemble des classes qui sont égale à 1 ( soit :  proba(chat) + proba(chien) = 1). On choisira alors la fonction d’activation softmax.  Alors que pour une classification à sortie multiple, on souhaite que le calcul de la proba des différentes classes soit indépendante, puisque plusieurs classes peuvent être présent dans notre donnée d’entrée. On aurait donc : 0 < proba(chat) < 1 et 0 < proba(chien) < 1. Pour cela on doit donc utiliser la fonction d’activation sigmoid. Pour comprendre les fonctions d’activations en détails, j’ai écrit auparavant un article disponible ici.
  • Fonction de perte : Celle-ci est choisi selon le problème à résoudre. Comme expliqué au point précédent, on n’a pas le même problème à résoudre. On aura donc pas la même fonction d’objectif.

 

Je vous joins ici l’ensemble de mon code source documenté et commenté sur mon profil Github, avec les informations nécessaire pour sa compilation et lancement. Vous aurez l’ensemble des informations nécessaires pour pouvoir en recréer un vous-même. Je compte d’ailleurs sur vous pour me proposer d’éventuelles corrections et optimisations pour le mien. 🙂

 

Remerciements

HARRISON16, Minseok Park and Hanxiang Li and Junmo Kim, HARRISON: A Benchmark on HAshtag Recommendation for Real-world Images in Social Networks, 2016

convolution et pooling Cours théoriques - Deep learning

Convolution, Pooling & Classification

Les réseaux de neurones à convolution, ou ConNets sont utilisés pour analyser des images. Leurs architectures sont basé sur le système de vision et d’analyse des animaux. C’est Yan LeCun, un chercheur français qui est à l’origine d’une grande partie de ces travaux sur la convolution. Il avait déjà réalisé en 1993 un système permettant à une camera de filmer et de reconnaître des chiffres écrit à la main.

On peux en distinguer plusieurs couches spécifiques :

Convolution

Architecture d'un réseau de neurones utilisant la convolution
Architecture d’un réseau de neurones utilisant la convolution

Ces couches vont permettre d’extraire des données, des caractéristiques de l’image. On va se servir de filtres, pour détecter des formes. Au fur et à mesure des couches, on va détecter des formes de plus en plus complexe. Par exemple à la première, les filtres vont mettre en évidence des courbes simple, traits et pixel. La suivante, en utilisant les filtres précédents, va apprendre à reconnaître des superpositions de courbes et de traits, pour détecter des formes plus complexe, et ainsi de suite, jusqu’aux couches les plus haute qui vont pouvoir détecter des visages, pour ne citer qu’un exemple.

 

Pooling

Cette étape permet de réduire la taille des images d’entrées, de réduire la charge de travail en diminuant les paramètres du réseau et donc la charge de calcul, tout en gardant les principales caractéristiques de l’image. Cela se passe via une fenêtre, qui va glisser pas à pas sur l’ensemble de l’image, et récupérer que certaines valeurs de l’image. Soit en prenant une moyenne des valeurs de pixels de la région analysée par cette fenêtre (meanPool), ou encore le maximum de celles-ci (maxPool), car il existe une multitude de type de pooling.

Explication d'une couche de pooling
Action de la couche de pooling

Classification

 

Extrait du dataset CIFAR-10
Extrait du dataset CIFAR-10

Le but de cette étape est de classer les images entrantes dans telle ou telle classe, en fonction des caractéristiques extraite durant les couches successives de convolution et pooling, via les couches de neurones entièrement connectés. Par exemple pour reconnaître un chat, ces couches vont permettre d’accentuer les caractéristique d’avoir 4 pattes, ou encore des poils. Elles vont donc en contrepartie diminuer les poids des caractéristiques qui représenterait une autre classe, tel que la présence de plume. Nous en ferons de même concernant nos mel-spectrogramme, nous allons classer ces images en fonction des phonèmes reconnue, et donc des mots.

train validation test set Cours théoriques - Machine learning

Découpage des datasets

Un jeu de donnée (dataset) va contenir d’énorme quantité de donnée. En effet, plus notre dataset sera grand et diversifié, plus notre modèle sera apte par la suite à prédire des résultats les plus justes possible. Le dataset doit être formaté de la façon suivante :

  • Train set : Celui-ci va être le plus volumineux en termes de donnée. En effet, c’est sur ce jeu ci que le réseau va itérer durant la phase d’entrainement pour pouvoir s’approprier des paramètres, et les ajuster au mieux. Certaines règles préconisent qu’il soit composé de 80% des données disponibles. C’est la phase d’apprentissage.
  • Validation set : Quant à lui, on préconise d’avoir environ 10% des données disponible. Ce jeu sera appelé une seule fois, à la fin de chaque itération d’entrainement. Il va permettre d’équilibrer le système. C’est la phase d’ajustage.
  • Test set : Ce dernier va avoir un rôle bien différent des autres, puisqu’il ne servira pas à ajuster notre réseau. En effet, il va avoir pour rôle d’évaluer le réseau sous sa forme finale, et de voir comment il arrive à prédire comme si le réseau était intégré à notre application. C’est pour cela qu’il doit être composé exclusivement de nouveaux échantillons, encore jamais utilisé pour éviter de biaiser les résultats en lui envoyant des donnés, qu’il connaîtrait déjà et qu’il aurait déjà appris lors de la phase d’entrainement ou de validation. Celui-ci encore peut être estimé de l’ordre de 10% des données disponible.
Data visualization Cours pratiques - Data visualization

Introduction à la data visualisation

Dans cet article je vais introduire le sujet autour de la data visualisation. Je ne ferrais qu’introduire et je n’irais pas plus loin car c’est un domaine dans laquelle les formations en mathématiques, statistiques et probabilités sont le cœur du métier et qui forme les data scientist. Ce sont des personnes qui vont analyser des bases de données et extraire des informations, afin de trouver d’éventuelle corrélations entres elle. En effet, il se peut que certains facteurs puissent influer les autres. Connaître ces informations peut ajouter de la plus-value aux entreprises. Mieux vous connaîtrez votre marché et les besoins des clients, plus vous optimiserez les ventes de vos produits.

Prenons un exemple simple. Il y a fort à parier que les ventes de parapluie soient plus importantes en hiver, qu’en été. Et cela peut venir d’un principal facteur, qu’est la météo.

Le secteur étant large, je vais me consacrer qu’a une infime partie du domaine. Je vais me servir de plusieurs bibliothèques, tout cela en python :

  • Matplotlib : la plus connue de toute, elle permet de faire beaucoup, beaucoup de chose. Pour rapidement résumer, elle permet de réaliser très simplement des graphiques 2D.
  • Seaborn : elle se base sur la librairie précédente, et propose des graphiques encore plus détaillés pour pousser d’avantage l’aspect data visualisation.

Comme d’habitude, les sources du dataset utilisé et l’ensemble de mon code est disponible sur mon profil Github.

C’est parti ! 😎

 

Origine du dataset

Nous avons comme jeu de donnée diverses mesures médicales prises sur 768 patients. Celui-ci va vous permettre via 7 attributs différents nous permettre de déceler une quelconque relation si une personne est diabétique ou non. Nous avons les attributs suivants :

  • Pregnancies : nombre d’enfant
  • Glucose : taux de glucose dans le plasma sanguin (mm Hg)
  • Blood pressure : pression artérielle
  • Skin thinckness : épaisseur de peau au niveau du triceps (mm)
  • Insulin : taux d’insuline (mu U/mL)
  • BMI : indice de masse corporel (IMC, poids en kg / ( taille en m)²)
  • Diabete pedigree function
  • Age (année)
  • Outcome : la sortie qui sera 0 pour non diabétique, et 1 pour diabétique

 

On peut noter que le dataset n’est franchement pas équilibré :

Equilibre du dataset 2

 

Premiers pas

 

Graphique tout individu confondu
Graphique tout individu confondu
Graphique non diabetique exclusif
Graphique non diabétique exclusif
Graphique diabetique exclusif
Graphique diabétique exclusif

On comparant les 3 graphiques précédent, on peut réaliser déjà quelques observations qui pourraient influencer ou non le fait d’être diabétique. Cela reste purement statistique et donc n’en fait pas une science absolue :

  • Glucose : il semblerait qu’un taux plus important de glucose dans le sang soit perçue chez une personne diabétique
  • Skin thickness : on peut voir qu’une personne diabétique à une peau plus fine en moyenne
  • Insulin : une valeur légèrement plus forte serait présente chez une personne diabétique

 

Sur certains attributs, on ne peut trouver d’informations concluantes :

  • BMI : Peu/pas d’influence
  • Blood pressure : Peu/pas d’influence
  • Diabete pedigree function : Peu/pas d’influence
  • Pregnancies : Peu/pas d’influence

 

 

 

Pair plot tout individu
Corrélation entre nos deux classes de sortie sur l’ensemble des attributs

 

Matrice de correlation
Matrice de corrélation

Remerciements

Smith, J.W., Everhart, J.E., Dickson, W.C., Knowler, W.C., & Johannes, R.S. (1988). Using the ADAP learning algorithm to forecast the onset of diabetes mellitusIn Proceedings of the Symposium on Computer Applications and Medical Care (pp. 261–265). IEEE Computer Society Press.

 

 

 

 

 

detecteur de harcelement Cours pratiques - Deep learning

Détecteur de harcèlement

Après avoir fait un article sur de l’image et un autre sur du son, cette semaine je m’attaque à du texte. Je vous propose de réaliser un classifieur de sentiments. A me perdre sur les réseaux sociaux, je croise énormément (et je pèse mes mots) de commentaires haineux, ou l’insulte gratuite est bien connue des espaces publics dans les commentaires. Le but de ce classifieur va être d’analyser un texte, et de nous retourner si celui-ci porte une atteinte morale à une personne, quel que soit son type.

Alors oui vous allez me dire il existe des datasets déjà existants sur des millions de tweets et qui fera bien mieux que moi en termes d’efficacité. Je vous l’accorde, mais ça peut être intéressant de connaître les outils pour ajuster son dataset en fonction de ses besoins. Par exemple, un dataset pour classifier des sentiments, qui soit en français, qui prennent en compte les emojis (qui peuvent apporter des informations en plus sur les intentions du message) et qui soit classifié via plusieurs types et non juste positif/négatif. Et bien cela reste inexistant. D’où le fait de savoir récolter soit même ses données est extrêmement important.

Comme d’habitude, le code sera entièrement disponible et commenté en détails sur Github :

 

Constituer son propre dataset

Dans les précédents articles, je ne m’attardais pas sur le dataset. Il en existe beaucoup pour réaliser des tâches simples, et surtout de bien plus gros et déjà annoté que le mien que je vais vous présenter, ce qui nous fait un gain de temps notable. Mais comment faire si, dans une entreprise, on se retrouve avec un besoin précis sur une tâche précise dont-il n’existe pas encore de dataset ? Et bien il n’existe pas 36 solutions, il faudra le créer soit même. Pour ce tutoriel, j’aurais très bien pu le faire à la main en utilisant le maximum de synonyme possible. Seulement, il y a de grande chance que notre réseau comprenne seulement nos phrases, puisque chaque personne à un style d’écriture bien différents. Pour avoir un maximum de variétés et surtout dans un minimum de temps, je vous propose de crawl le web !

 

Crawler le web ? 
C’est le fait de parser, d’analyser un site web et de récupérer des données. Je vous l’accorde, cette technique peut nous aider, mais ne sera pas approprié pour 100% des tâches, dans des cas précis, comme durant mon stage de master, j’ai eu besoin d’un type spécifique de donnée qui n’existait nulle part, auquel j’ai dû moi-même le constituer de A à Z. Mais pour le cas de notre classifieur, je vous propose de récupérer des données soit sur des sites telle que Jeux vidéo, Twitter ou encore l’espace commentaire de Youtube. Le but est d’avoir autant de commentaires positifs que d’injurieux.

Pour la récupération des données, il en existe pas mal, mais je vais vous parler des 3 principaux :

  • Scrappy : C’est le plus connu, le plus complet, mais aussi le plus complexe à l’utilisation. Il permet de récupérer depuis des api, les informations sous format JSON.
  • BeautifulSoup : Très connu aussi, je l’ai favorisé à Scrappy, quant au fait que la mise en place d’un spyder est beaucoup plus rapide et simple. En effet, il ne m’a fallu que quelques lignes pour faire mon script. Autant dire que pour débuter, c’est celui que je vous conseille !
  • Selenium : Celui-ci n’est pas son but premier de crawler pour récupérer des données. Il peut le faire mais ce n’est clairement pas le plus optimisé pour ce genre d’utilisation, puisqu’il est plus orienté pour réaliser des tests sur votre application web. Vous pouvez simuler les scénarios et naviguer de bout en bout sur votre site. Cependant, il permet de faire des actions telles que la visualisation dans votre navigateur, des différents scénarios et de voir en temps réel les actions et répercutions. Il permet aussi de réaliser des clicks sur une application, ce qui peut se révéler extrêmement utile si on doit rafraîchir des données via un bouton sur le site.
exemple de crawling via BeautifulSoup4
Exemple de récupération de données via BeautifulSoup

Le premier moyen que j’ai trouvé de récupérer des données est de crawl des forums de jeux vidéo, tel que JVC qui est notamment réputé pour avoir une communauté assez agressive entre leurs membres. Pour faire au plus simple j’ai utilisé BeautifulSoup. J’ai procédé de la façon suivante :

  • Récupération des données brutes : pour cela rien de plus simple, on parse les pages et on récupère tout cela dans un fichier texte en local
  • Nettoyage des données : et c’est ici l’étape la plus importante. En effet, le dataset doit être le plus complet, diversifié et correcte. Il ne faut pas oublier que c’est la data qui est à l’origine d’un bon ou d’un mauvais réseau en sortie, du moins en grande partie. J’ai pu rencontrer plusieurs soucis telle que l’encodage des phrases récupéré, avec les accents français écrit en code et donc qui m’a fait des phrases extrêmement bruités, ou encore des retours avec des phrases vide. Tout cela est donc à vérifier avant tout entrainement du réseau.
  • Format des données : il faut ensuite donner une structure identique entre chacune de nos données pour former une dataset homogène. J’ai réalisé de la sorte suivante :
    • Phrase 1, 0
    • Phrase 2, 1
    • Etc.

Je vais associer pour chaque extrait une classe, pour indiquer si ce message est soit normal (classe 0), ou soit injurieux et présentant un risque de harcèlement (classe 1).

Autant pour trouver des textes injurieux, sexistes, homophobe ou encore raciste, cela reste une chose assez simple via une recherche par mots clés. Autant pour trouver des datas qui soient positive, cela peut être plus complexe.
On se retrouve avec un premier ‘dataset’ (si on peut l’appeler ça un dataset.. :o) constitué de 1500 phrases. C’est peu, beaucoup trop peu de parser des sites indépendant. On va alors privilégier la quantité à la qualité pour ce cours ci, en allant crawler des réseaux sociaux, tel que Twitter. J’ai utilisé TweetScrapper, qui est un module libre dispo sur Github et qui est basé sur Scrapy. L’utilité de passer par ce module, est que l’on va pouvoir parcourir Twitter sans avoir besoin de l’API développeur, qui est accessible via des clés distribuées au compte goutte par Twitter. J’ai notamment essayé d’en récupérer en faisant une demande, auquel je me suis vu refuser 3 fois de suite ma demande. Je pense d’ailleurs qu’a notre ère ou la data est une ressource très convoitée, que Twitter tente de filtrer et de limiter leur accès.

C’est à ce moment-là que l’on voit que Scrapy est un outil extrêmement performant puisque qu’avec mon petit laptop, j’arrive à atteindre jusqu’à 1416 tweet récupéré par minute. Autant dire que c’est une autre paire de manche comparé à mon premier essai à crawl JVC ou encore Bodyguard pour récolter péniblement 1500 extraits.

 

Comment je m’y suis prit pour récolter des données qui soit offensante et non offensante ?
J’ai fait quelque chose d’extrêmement simple, en faisant des re recherche de tweet selon des mots clés. Je vous mets mes 2 fonctions utilisé via Scrappy :

 

  • Data négative :
    scrapy crawl TweetScraper -a query= »pute OR salope OR pd OR connasse OR encule OR bite OR cul OR connard OR batard OR enfoire OR abruti OR gueule » -a lang=fr

 

  • Data positive :
    scrapy crawl TweetScraper -a query= »content OR excellent OR bravo OR felicitations OR heureux OR super » -a lang=fr

 

Nettoyer le dataset

J’ai stoppé le crawling à grosso modo 50 000 extraits pour chacune de nos classes. Scrappy nous enregistre un fichier texte par tweet avec beaucoup d’informations qui nous ne serons pas utile. Or ce que l’on recherche, et d’avoir un fichier unique contenant l’ensemble des tweets avec un format le plus simple possible pour minimiser le pré traitement des données juste avant notre entrainement. Tout ce qui est fait en amont ne sera pas à faire en aval 😉

 

Exemple de tweet remonté directement depuis Scrapy :

{« usernameTweet »: « HIRASUS298 », « ID »: « 1066516448661725184 », « text »: « un jour jvai le croiser \u00e0 chatelet jvai lui niquer sa grand m\u00e8re surtout pcq un moment il sfoutait dla  gueule  des marocains », « url »: « /HIRASUS298/status/1066516448661725184 », « nbr_retweet »: 0, « nbr_favorite »: 1, « nbr_reply »: 0, « datetime »: « 2018-11-25 03:18:30 », « is_reply »: true, « is_retweet »: false, « user_id »: « 4537565739 »}

 

On va devoir réaliser plusieurs traitements de ce texte-là, afin de minimiser les temps de calculs et de faciliter le pré traitement avant d’entrainer notre réseau.

Premièrement j’ai commencé par ne récupérer que le texte du tweet et lui associer une classe, qui soit 0 ou 1 pour savoir si celui-ci est considéré comme offensant ou non. Le code est très simple je ne vais donc pas perdre de temps à l’expliquer ici, mais j’ai parcouru l’ensemble de mes fichier texte, je les ouvre et je récupérer seulement les données que j’ai besoin, car le tweet s’apparente comme état un dictionnaire. Je récupérer donc juste le contenu du champ TEXT, de la même façon que celui-ci serait un fichier JSON.

Nous obtenons à la suite de cette phase là le texte suivant :

un jour jvai le croiser \u00e0 chatelet jvai lui niquer sa grand m\u00e8re surtout pcq un moment il sfoutait dla  gueule  des marocains, 1

La seconde étape va être de nettoyer tout ces problèmes d’encodage. Merci python, je n’ai pas pu me débrouiller pour récupérer dès la source un texte correctement écrit… En effet j’ai eu un sacré souci concernant les accents et emojis, qui me renvoyer leur code. Tant pis, j’ai fait un nettoyage d’une façon qui s’apparente un peu à du bricolage, mais cela fonctionne et c’est le principal. On optimisera plus tard 😉 . J’obtiens le texte suivant.

un jour jvai le croiser a chatelet jvai lui niquer sa grand mere surtout pcq un moment il sfoutait dla  gueule  des marocains, 1

Malgré les fautes du monsieur, on arrive à un texte qui à du sens. Du moins un minimum de sens héhé. Une dernière étape va être de fusionner l’ensemble des tweets. En effet, rappelez vous que j’ai un fichier par tweet, ce qu’il me fait plus de 100 000 fichiers sous la main. Je vais donc pouvoir rassembler l’ensemble des tweets dans un même fichier grâce à des dataframes de Pandas.

 

Certaines de mes requêtes m’ont aussi renvoyé des textes vides. Il a fallu donc penser à plusieurs types de filtrage en plus en annexe, notamment à des textes qui étaient associés à des classes autres que 0 ou 1 suite à des soucis de crawling.

 

Vers une reconnaissance plus pointue ?

Pour l’article je n’ai souhaité que classifier un texte en fonction de deux états, qu’il soit positif ou négatif pour me faciliter la chose avec le dataset. Mais nous pourrions aller plus loin en proposant bien d’autres états de sortie quant à une entrée. En effet une chouette utilisation serait d’avoir plusieurs niveaux pour avoir une catégorie des plus précises concernant le type d’injure, par exemple :

  • Aucun risque
  • Haine
  • Homophobe
  • Raciste
  • Harcèlement morale
  • Insulte
  • Troll

 

Mon projet pourrait être bien plus robuste. On le lit souvent que la qualité du dataset va jouer pour beaucoup concernant les nouvelles prédictions du réseau. Il faut alors avoir un équilibre entre :

  • Le nombre de données : plus vous en avez mieux c’est, car vous apportez de la diversité. En effet, selon vos données, elles doivent venir de plusieurs origines afin de diversifier les réseaux sociaux, auquel nous avons des tranches d’âges différentes, et donc des façons de parler différentes, mais aussi des communautés et donc opinions différentes.
  • La qualité : mais dans l’autre cas avoir une infinité de donnée qui ne sont que peu pertinentes n’est pas bon non plus. Il faudra donc s’assurer que les données soient à la fois utiles et juste. Autant quand vous créer votre propre dataset avec vos propres données comme j’ai pu le faire dans le cours sur la reconnaissance vocale, vous connaissez l’ensemble des variables et donc vous savez ce que vous mettez dans votre jeu de donnée est juste et pertinent. Autant comme pour le cours d’aujourd’hui on ne vérifie pas les 100 000 données une par une pour s’assurer de la pertinence de chacune d’entre elle. En effet en se basant sur des mots clés je sais déjà par avance que certains de mes données seront mal classé. Exemple simple, il nous ait déjà à tous arriver d’inclure une insulte envers un amis proche, mais qui est un contexte amical.

 

Conclusion

Nous venons de réaliser un outils permettant de classifier si un texte est injurieux ou non. Cela peut pourrait être utile sur les plateformes d’échanges de commentaires des grands réseaux sociaux pour luter contre le harcèlement moral qui peut se présenter sous diverses formes.

installation cudnn cuda Cours pratiques - Deep learning

Configuration des dépendances pour utiliser le GPU (CUDA, cuDNN)

Le CPU, c’est bien. Le GPU, c’est mieux !

Nous avons installé tout ce qu’il nous faut pour lancer des entraînements de réseaux de neurones. Cependant, si on lance un entrainement à ce stade-là, nous allons taper exclusivement sur le CPU. Il serait dommage de ne profiter de l’accélération de calculs offert par notre carte graphique (et surtout au prix ou elles sont actuellement, on remercie NVIDIA hein 😉)

Nous allons devoir installer 2 outils nécessaires :

  • CUDA : C’est une technologie propriétaire de NVIDIA permettant d’effectuer du traitement parallèle via leur carte graphique, permettant un bien meilleur rendement.
  • cuDNN : C’est la librairie des primitives de NVIDIA concernant les réseaux de neurones. Elle va permettre d’accélérer nos traitements , qu’ils concernant les routines standard comme la backpropagation , les fonctions d’activations etc. Il fait partie du SDK de deep learning, et peut s’utiliser avec différents backend (Caffe, Caffe2, Chainer, Keras, Matlab, MxNet, Tensorflow et Pytorch).

Sur beaucoup de site, les gens renseigne que pour installer ces deux dépendances nécessaires, il suffit de les installer à la main depuis le site NVIDIA. Cuda s’installe facilement, mais pour cuDNN vous aller devoir vous créer un compte développeur et drag&drop leur fichier zip au bon endroit. Cette méthode à fonctionné pour mon premier laptop, mais pas le second, surement un soucis de version entre les deux versions. Bref, une installation pas des plus rapide et fonctionnel.

 

Installation

Du coup je vous propose de simplifier tout cela, en installant ces deux librairies directement via Anaconda. Ouvrez votre environnement souhaité, et taper les lignes suivantes :

  • conda install -c anaconda cudatoolkit
  • conda install -c anaconda cudnn

 

Et voilà. Simple, basique.😎