Machinator pour les nuls

Le Lab

Matchinator est un projet réalisé pour le challenge « Lab » organisé par la société Carboat Média et dont la présentation finale s’est déroulée au cours du séminaire 2018 à Barcelone. L’objectif de ce challenge consistait à proposer un prototype à partir d’un des objets connectés mis à la disposition de tous les participants (Raspberry Pi, Google Home, Lego Mindstorms, Alexa, Horloge connectée, etc). Ces projets devaient être réalisés en équipe, et chaque équipe était mise en concurrence afin de déterminer, au travers d’un vote d’environ 70 personnes, le projet qui respectait au mieux les principaux critères, à savoir : idée innovante, qualité de la réalisation et qualité de la présentation.

Contexte du projet

Pour répondre aux différentes attentes, aussi bien les nôtres que celles d’un marché de niche en plein expansion, la décision fut de prendre le Google home. Les assistants vocaux sont de plus en plus présents dans nos foyers. Les utilisations de plus en plus diversifiées et intelligentes, et tout cela dans des environnements de plus en connectés. Dans un tel contexte, il était évident de voir arrivé sur le marché les géants américain Google et Amazon avec leur proposition d’assistant vocal. Le premier avec son Google Home, le second avec Alexa. Pour le projet Matchinator, le choix s’est porté sur le device pensé par Google : le Google Home. Ce choix se justifie principalement en rapport aux différentes technologies qui l’accompagne.

Le Google Home

Le Google Home est l’enceinte connectée développé par Google et disponible sur le marché depuis le 4 septembre 2016 en magasin (4 octobre en précommande). Il fut annoncé au cours la Google I/O qui s’est déroulé en mai 2016.  Le Google Home se décline en plusieurs versions : Google Home Mini, Google Home et Google Home Max. La différence entre ces versions s’observe principalement sur la qualité sonore, la taille et bien sûr le prix. L’intérêt principal du Google Home est son aspect « intelligent », poser des questions vocalement à la machine, comme il les posera à un être humain, et ainsi obtenir une réponse. Vous pourrez par exemple vérifier la météo, connaître l’heure qu’il est à New-York, remplir votre liste de courses, ou encore demander tout autres informations toutes plus inutiles les unes que les autres (tout ce qu’on aime quoi…).

Le Google Match

Pour comprendre le projet Matchinator, il faut avant tout savoir que les concepteurs sont tous issus de la même feature team au sein de la société : l’équipe SODA. Cette dernière est en charge d’un projet nommé CarMatch, et dont l’intérêt principal est de faire la correspondance entre les données clients (marque, modèle, version, puissance fiscale, etc.) et le référentiel DAB. Cette correspondance est déterminée à l’aide d’un algorithme de matching (Matchin…). La deuxième inspiration vient d’une application web utilisée pour trouver un individu, celui auquel pense l’utilisateur, suite à un jeu de questions/réponses successives. L’idée étant d’apporter un peu de magie à l’utilisateur en apportant une réponse finale valide tout en minimisant le nombre de question/réponse. Cette application, bien connue sous le nom d’Akinator (…ator), apporte un sens au nom Matchinator, qui n’est autre que la contraction de Matching et Akinator (oui, c’est évident, mais il fallait bien le placer quelque part).

L’intérêt de Matchinator ?

La question est désormais de comprendre l’intérêt de ce projet. Comme précisé en début d’article, le principal objectif était la qualité du projet en matière d’innovation. Quoi de plus innovant qu’un projet aussi sérieux qu’amusant ? Matchinator y répond pour vous, et à vive voix ! Un projet sérieux, car la finalité est de proposer un concept qui soit tout simplement exploitable sur le marché, et amusant, car il fait appel à des technologies qui nous font retomber en enfance, époque où chacun d’entre nous se faisait déjà une idée du futur. Alors non Matchinator n’est pas un skate volant, mais il vous fera parler, vous répéter, parfois vous énerver (on reste sur un prototype hein). De cette manière, nous avons souhaité mettre en avant une fonctionnalité intéressante proposée par La Centrale qui consiste à fournir une idée sur la côte d’un véhicule. L’utilisateur devra simplement fournir assez d’informations à Machinator pour la laisser déduire de ces dernières la version exacte de son véhicule et ainsi fournir automatiquement la côte dudit véhicule. Simple, rapide, efficace.

L’intérêt de Matchinator !!!!

Le véritable intérêt de ce projet réside dans le besoin de fournir aux clients une estimation la plus précise possible de la côte d’un véhicule. En effet, aujourd’hui, les données utilisées pour déterminer ladite côte sont celles fournis par la préfecture. Ces données sont généralement incomplètes et ne suffisent pas à déterminer la version exacte du véhicule. Sachant que deux versions partageant le même couple marque/modèle peuvent être vendues à des prix très différents (selon les options par exemple), l’estimation de la côte se voit directement impacté par la diminution de sa précision. Pour répondre à ce problème, Matchinator tentera de rentrer directement en contact avec l’utilisateur. Après la récupération des données de la préfecture, si plusieurs versions sont compatibles, Matchinator demandera directement à l’utilisateur, par le biais de questions, des informations supplémentaires sur les caractéristiques de son véhicule. Le but étant d’affiner le nombre de versions compatible jusqu’à trouver la meilleure. LaCentrale sera ensuite en mesure de fournir à l’utilisateur une estimation exacte de la côte de son véhicule.

La technologie Dialogflow

Avant de rentrer dans le détail de l’application avec un exemple d’user story et des explications plus techniques sur sa conception, il semble inévitable de faire un petit tour auprès de la technologie au cœur de l’application : Dialogflow.

Dialogflow est un Chat Bots conversationnel développé anciennement par Speaktoit sous le nom d’Api.ai. La première release est mise à disposition des développeurs en 2014, puis est racheté en 2017 par Google qui la renomme Dialogflow. Ce dernier dispose d’une interface graphique efficace pour initier l’intégralité des évènements sans avoir besoin d’une seule ligne de code. « Quoi ?! Moi, je suis, INGÉNIEUR INFORMATICIEEEEN ! ». Évidemment, le travail de reconnaissance des phrases utilisateurs est effectué de manière transparente par Dialogflow grâce au machine learning et à son api Cloud Version Language. La configuration des conversations est donc à effectuer intégralement avec l’UI. Concernant sa logique de fonctionnement, il est fortement conseillé de se diriger vers la documentation officielle. À des fins de clarté pour la suite, nous mettrons en exergue quelques mots-clefs issus de la documentation officielle :

  • Agent: l’agent est en quelque sorte un fil de discussion, une suite de questions/réponse (succession d’intent) avec l’utilisateur.overview-diagram
  • Intent: l’intent correspond à l’entité principale d’une conversation gérée par Dialogflow. Elle consiste en 3 étapes distinctes : l’utilisateur fournis l’input dans un contexte précis (voir définition suivante), Dialogflow traite cet input, puis retourne une réponse. Pour construire un intent, on commencera par fournir un ensemble de mots (phrases) qui permettront de déclencher ce dernier lorsque l’utilisateur les prononcera, on les appelle des ‘training phrases’.
  • Context: un contexte contient l’ensemble des données issues de la requête utilisateur. Ce contexte possède une durée de vie à définir et mesuré en nombre d’intent invoqué. Il permet ainsi de garder en mémoire les données d’un intent à un autre.
  • Event: permet d’invoquer un intent sans passer par la communication avec l’utilisateur. Peut être invoqué par exemple par un trigger depuis le backend de l’application.
  • Fulfillment: correspond au webhook qui sera invoqué au déclenchement d’un intent.

Contexte et cas d’utilisation

La présence ou non d’un contexte en particulier est également déterminant pour le déclenchement d’un intent. Pour l’exemple, prenons une application de musique qui pourra effectuer deux actions : lancer une musique et obtenir le nom de l’artiste auteur de cette musique. Nous créons donc deux intents : le premier se déclenchera au moment où l’utilisateur fournira une phrase du type « Musicator, lance la musique XXX », la deuxième lorsque l’utilisateur fournira une autre phrase du type « Quel est l’auteur de cette musique ? ». Maintenant, que se passe-t-il si l’utilisateur, au lancement de l’application, pose directement la deuxième question ? Comme vous l’aurez compris (enfin j’espère), le deuxième intent devrai se déclencher. Et pourtant, comment Musicator peut fournir une réponse sachant qu’aucune musique n’a été lancé ? Et c’est maintenant qu’entre en jeu les contextes. En effet, l’idée est de créer un contexte en sortie du premier intent : si l’utilisateur commence par demander le lancement de la musique XXX, l’application tentera dans un premier temps de récupérer le nom de l’artiste à partir du nom de la musique (via un appel webhook par exemple), il ouvrira ensuite un nouveau contexte dans lequel il persistera le nom de la musique et le nom de l’artiste, et enfin il lancera la musique. A présent, si la question de l’auteur est posée, Dialogflow connaîtra la réponse, stocké dans le contexte ouvert précédemment. Cela induit une nouvelle logique dans le déclenchement d’un intent, qui sera possible que si un certain contexte est présent et vivant en entrée de cet intent (si besoin évidemment). Ce dernier pourra à son tour ouvrir de nouveaux contextes en sortie, rendant possible le déclenchement d’autres éventuelles intents.

Cet exemple illustre bien tout l’intérêt des contextes et du lien étroit que ces derniers disposent avec les intents. Suivez ce lien si vous souhaitez obtenir un aperçu de la façon dont on crée un projet simple avec Dialogflow.

Matchinator et Dialogflow

Matchinator-4194-b968a693-0

Le schéma précédent présente le graphe des possibilités de l’application Machinator, dont chaque nœud illustre une étape, et chaque arête le passage d’une étape à une autre. Plus précisément :

    • Les rectangles représentent des actions : en vert, les actions effectuées sur Dialogflow (attente d’une phrase prononcée par l’utilisateur ou le bot), et en bleu, les actions effectuées côté serveur (logique de l’application).
    • Les losanges représentent quant à eux des décisions à prendre sur le serveur.
    • Les parallélépipèdes blancs représentent les contextes en entrée et en sortie. La création d’un nouveau contexte est illustrée par sa police d’écriture en gras.
  • Les labels jaunes représentent quant à eux les intents.

Instant publicité

machinator

Vous disposez d’un Google home ? Bon début. Vous avez un véhicule à vendre ? Cool. Vous désirez connaître une estimation de la côte de cette dernière ? Parfait. Plus qu’à lancer l’application Matchinator et amusez-vous ! Pour les grands et les petits, n’ayez qu’une seule et unique peur, devenir accro, car avec Matchinator, acheter pour revendre deviendra votre nouvelle passion !

Bref, installez l’application et profitez du discours de présentation par Machinator elle-même (oui oui !) :

Bonjour.
Je me présente, je m’appelle Matchinator et j’ai le pouvoir de déterminer la valeur de votre véhicule.
Pour cela rien de plus simple, donnez-moi le numéro de votre plaque d’immatriculation ainsi que votre kilométrage, et je serai apte à déterminer la côte de votre véhicule.
De plus, si vous le souhaitez, je peux déposer une annonce directement sur le site LaCentrale. L’adresse e-mail utilisée sera celle de votre compte Google associé à votre Google assistant. Je vous souhaite de bien vous amuser.

Macro-tchinator

Ainsi, le déroulement macro d’une utilisation de Matchinator peut se résumer comme suit : vous avez votre véhicule et vous connaissez la plaque d’immatriculation de ce dernier. Vous lancez l’application, le bot vous demandera l’immatriculation, que vous lui fournirez. À partir de cette immatriculation, il cherchera l’ensemble des versions associées. S’il ne trouve aucune version, déçu, il coupera la conversation. S’il trouve exactement une version, il exprimera l’intitulé exact de la version, puis demandera son kilométrage. Une fois le kilométrage connu, il vous retournera si possible la côte estimé de la version. Prenons le cas ou à partir de l’immatriculation il trouve plusieurs versions : il commencera par vous indiquer la marque et le modèle des versions trouvées, puis se suivra la fameuse succession de questions/réponses dans le but d’affiner les résultats, déterminer la bonne version, et enfin retourner la côte de cette dernière.

Micro-tchinator

A présent, disséquons chaque mécanique illustrée précédemment. N’hésitez pas à jeter un œil aux schémas associés pour mieux comprendre (petite technique de cow-boy, t’inquiète c’est free).

Partie 1 – Obtention du numéro minéralogique

1

L’application se lance sur le nœud ‘start’. L’intent ‘welcome’ est automatiquement déclenché par Dialogflow. Ce dernier lui permet de poser une question à l’utilisateur. La réponse à cette question est primordiale, nous avons donc besoin de la stocker en mémoire. C’est la raison pour laquelle nous ouvrons en sortie de cette intent le contexte ‘awaiting-license-plate’. A cet instant, l’application est mise en attente d’une réponse à l’initiative de l’utilisateur. Celle-ci donnée est valide, un intent est à nouveau déclenché, le ‘user-provide-license-plate’. Pour information, ce dernier avait besoin de deux entités pour pouvoir se déclencher: une réponse valide (par rapport au type de phrase attendu par Dialogflow) de l’utilisateur et le contexte ‘awaiting-license-plate’ vivant en entrée (à l’ouverture d’un nouveau contexte, on lui affecte une durée de vie, qui décrémente de 1 pour chaque intent déclenché depuis sa création. Si cette durée de vie tombe à zéro, le contexte est détruit, de même pour les données qui l’accompagnent).

Partie 2 – Obtention des versions

find_version

Le dernier intent déclenché aura quant à lui la tâche de vérifier si l’immatriculation fournis par l’utilisateur est valide. Pour cela, il fera appel à un webhook (application externe qui simulera un utilisateur), correspondant au backend de notre application. Ainsi, depuis ledit backend, il sera déterminé si l’immatriculation est associée à zéro, une ou plusieurs versions. Selon le résultat, et toujours depuis le server, un event sera utilisé afin de déclencher le bon intent.

Partie 3 – zéro version trouvée

find_version

Si l’immatriculation n’existe pas ou qu’elle existe mais n’est associé à aucune version, alors l’intent ‘user-provides-license-plate’ retournera comme réponse la fermeture de l’application.

Partie 4 – une version trouvée

3

Dans le cas où exactement une version est trouvée, le backend ouvrira lui-même un nouveau contexte, que l’on nommera ‘version-found’, qui permettra de stocker la version trouvée. Ensuite, à l’aide de l’event ‘version-found-event’, l’intent ‘version-found’ sera déclenché. Ce dernier permet d’exprimer le libellé exact de la version trouvée et précédemment stocké dans le contexte ‘version-found’ puis de poser la question du kilométrage. En sortie de cet intent, un nouveau contexte est ouvert, en parallèle du premier, nommé ‘awaiting-mileage’, afin de stocker la valeur de kilométrage ainsi obtenue.  Nouvelle mise en attente de l’application jusqu’à l’expression de l’utilisateur. La réponse fournis, l’intent ‘user-provide-mileage’ se déclenche, suivi par un nouvel appel webhook qui se chargera de récupérer la valeur de la côte de la version. Si la côte est introuvable, alors l’intent fournira comme seule réponse la fermeture de l’application, sinon elle exprimera cette valeur puis fermera à son tour l’application.

Partie 5 – plusieurs versions trouvées

Une partie aussi complexe qu’intéressante. L’immatriculation nous permet d’obtenir un certain nombre de versions pour un seul couple marque/modèle. Ainsi, en réponse de l’intent ‘user-provide-license-plate’ (rappelez-vous qu’à ce stade du workflow nous nous trouvons toujours dans cet intent), Matchinator nous énoncera la marque, le modèle, ainsi que le nombre de versions trouvées. C’est alors qu’on met en place la succession de question/réponse à l’instar de l’application Akinator (pour rappel, l’idée est de permettre à l’application de « deviner » la personne à laquelle pense l’utilisateur en posant un minimum de questions simples). De la même façon, Machinator se contentera de déterminer la bonne version parmi toutes les possibilités.

find_multiples_version

Pour cela, on commence par initialiser un nombre maximum de questions à poser depuis le backend de l’application, après quoi, s’il reste plusieurs versions en course, on ouvre le contexte ‘version-found’ dans lequel on stocke une version aléatoire parmi les n restantes et on se redirige vers le cas 4.

A l’inverse, dans le cas où le nombre maximum de questions n’est pas atteint, on calcule, côté backend toujours, le mot le plus représenté parmi les versions restantes. Tant qu’un mot est présent dans toutes les versions, on le supprime. Nous nous chargeons ensuite de sélectionner la finition présente le plus grand nombre de fois afin de filtrer un maximum de versions pour chaque question. Pour cela, à l’aide d’un event porté par le backend, l’intent ‘ask-for-word-candidate’ se déclenchera et ouvrira un nouveau contexte : ‘awaiting-word-candidate’.

Machinator demandera ensuite si le mot précédemment sélectionné apparaît en tant que finition dans la version de l’utilisateur. Nouvelle attente. Avec l’ouverture du dernier contexte, deux intents sont fins prêts à se déclencher, et ce en fonction de la réponse de l’utilisateur. Si l’utilisateur répond oui, c’est l’intent ‘user-provides-word-candidate-yes’ qui se déclanchera, sinon l’intent ‘user-provides-word-candidate-no’. Quel que soit la réponse, les versions présentes dans le contexte ‘matched-versions’ (toujours persistant) se mettrons à jour. Selon s’il répond oui ou non, on supprimera toutes les versions ne possédant pas le mot sélectionné, sinon toutes les versions le possédant. Les versions mise à jour, on renouvelle le contexte ‘matched-versions’ en incrémentant sa durée de vie de 1 (qui, pour rappel, se décrémente toute seule à mesure que les questions défilent). L’idée étant de garder ce contexte ouvert tant qu’il reste plus d’une version. A nouveau, on vérifie le nombre de versions restantes, s’il est supérieur à un, on réitère depuis le début, sinon on stocke la dernière version dans le contexte ‘matched-version’, est on redirige l’application vers le cas 4.

Architecture de l’application

Blank Diagram

L’utilisateur est en lien avec Google et ses serveurs par l’intermédiaire de son objet connecté le Google Home. Ce dernier communique ensuite avec Dialogflow au travers du Google assistant. Dialogflow, comme décrit précédemment, a plusieurs possibilités : traiter la requête utilisateur et envoyer une réponse directement depuis ses propres serveurs, ou bien faire appel à un webhook (en l’occurrence le backend de notre application).

La technologie Amazon AWS a été utilisée avec un certain nombre d’outils qu’elle propose. L’API REST développé est hébergée dans API Gateway, un VPC Link est ensuite intégré dans API Gateway afin d’intégrer l’API aux ressources VPC gérées par le load balancer. Le serveur web est quant à lui hébergé au sein d’une instance Amazon EC2. Ce dernier peut potentiellement communiquer avec l’application Matching Immat, elle-même hébergée sur Amazon AWS.

Le projet aujourd’hui?

Les difficultés rencontrées sont principalement liées à Dialogflow. Cette technologie repose sur des principes que nous ne rencontrons que rarement. Si vous en êtes là, alors vous avez lu les parties précédentes (attention sur WordPress un bot vous surveille, je le saurai). Si certaines phrases vous ont fait défauts, si certaines ont été relues, voir relues encore, alors vous nous comprendrez. Le principe des contextes, des intents ou des events sur Dialogflow est déroutant, rien de très compliqué, juste déroutant.

Soyons clair, le projet est encore à l’état de POC. Il s’agit simplement d’un prototype qui repose à la fois sur une idée et sur une technologie nouvelle. En tant que développeur, notre principal objectif était d’une part la participation au concours « Le Lab », mais surtout prendre du plaisir à tester de nouvelles technologies. Dans cette idée, nous avons fait, puis nous avons refait, ensuite testé, pour refaire à nouveau, recyclé, rejoué et débuggé, et ainsi de suite jusqu’au fameux dernier jour.

C’est pourquoi le projet fonctionne, et très bien même, mais reste actuellement incomplet. Les magics numbers sont là et feront de l’oeil à tout ceux qui oseront s’aventurer dans le code. Les tests unitaires sont nombreux, approximativement zéro. Des problèmes résolus en dur dans le code, peu de factorisation. Bref, pas toujours propre, certes, mais cette confidence me permettra de dormir la conscience tranquille.

Et puis de toute façon on a gagné, alors bon…

ScalaIO 2017

La 4ème édition de ScalaIO a eu lieu les 2 et 3 novembre 2017 dans les locaux de l’école CPE à Lyon. Il s’agit de l’événement principal de la communauté Scala en France mais il y a également une forte composante internationale avec environ la moitié des talks qui sont donnés en anglais et de nombreux participants et speakers étrangers.

Comme chaque année, nous avons eu droit à une excellente conférence avec de très bonnes sessions, de nombreux speakers renommés et une organisation remarquable. Cette année un accent particulier avait été mis sur l’ouverture aux moins expérimentés avec pas mal de communication en amont sur cet aspect et les deux tiers des talks qui étaient accessibles aux débutants.

Ceux qui veulent faire fondre leurs neurones n’étaient pas en reste pour autant avec comme à l’accoutumée des sessions avancées sur des sujets complexes tels que la théorie des catégories ou bien toutes les merveilles que l’on peut faire avec le système de types de Scala. Autre nouveauté de cette année, l’ensemble des sessions a été filmé et elles devraient donc être très certainement disponibles prochainement en streaming.

Lire la suite

Serverless : API de recherche la centrale

Plusieurs articles sur les architectures AWS API Gateway et AWS Lambda pointaient du doigt certains problèmes tout en reconnaissant les nombreux avantages de ces nouvelles stacks.
Nous avons lancé un projet pilote 100% Serverless sur Amazon Web Services afin de nous faire notre propre idée.

L’objectif était le suivant :

  • Offrir une API REST de recherche utilisant ElasticSearch comme moteur de recherche
  • Scalabilité totale
  • Temps de réponse lors des pic à 600 requêtes par seconde :
    • Moyenne < 40ms
    • p50 < 10ms
    • p95 < 90ms
    • p99 < 200ms
  • Rester dans des couts comparables à une architecture REST classique
  • Temps avant mise en production : 1 mois

Lire la suite

Comment j’ai vécu mon premier Hackathon

Qui veut aller à un hackathon ?

Quand on nous a parlé du hackathon je me suis dit ‘c’est pas pour moi, c’est pour les gens qui dorment avec leur ordinateur’.

Après quelques jours de réflexion je me suis dit que moi-même je passe quand même environ 16 heures par jour sur l’ordinateur (le temps cumulé entre le travail et à la maison), que moi aussi je suis curieux,  et que moi aussi j’aime bien faire ceci cela (la preuve c’est que j’ai toujours un projet perso en cours sur lequel je bosse sur mon temps libre).

Après avoir discuté avec un collègue, nous nous sommes convaincu l’un l’autre que ce serait intéressant d’y aller. Quelques jours après on était 4 à vouloir y participer. Cool. Vu que le hackathon se déroulerait en Allemagne, c’était mieux d’y aller à plusieurs et d’éviter de se retrouver tout seul parmi d’autres.On avait à peu près 2 semaines devant nous pour « nous préparer ».On se disait qu’il fallait se préparer, préparer des trucs, faire de la recherche sur Internet, etc.

Les deux semaines écoulées, résultat : rien préparé 🙂

Finalement on s’est dit qu’il vallait mieux y aller l’esprit libre, et comme  nous avons souvent des idées pour créer un projet, ça devrait bien se passer.

En même temps on se demandait si les autres participants seraient meilleurs que nous et si on n’allait pas rentrer la tête baissée.

Jour J : Le départ

Nous arrivons là bas, là-bas, c’est Berlin, ville historique du groupe Axel Springer

On voit déjà pas mal de monde installé, en train de bosser sur je ne sais pas quoi. En les voyant, nos craintes ont disparu. On se disait, on peut quand même faire quelque chose de raisonnable, voir plus que ça.

La motivation était double : la satisfaction personnelle et le fait qu’on représentait notre société au sein du groupe, et que des gens ont pensé que nous avions le niveau pour y faire face, donc il fallait assurer.

En attendant nous avions discuté entre nous et échangé vite fait avec un autre participant.

Heure H : présentation du concours

Après la présentation, on était toujours ensemble mais on était que 4 développeurs. On savait qu’il fallait avoir plusieurs profils dans l’équipe afin de pouvoir faire quelque chose de sympa et joli.

On commence à se demander ce qu’on pouvait faire comme projet. Pas trop d’idée géniale à ce moment là. Par chance, 2 filles nous abordent : elles ont une idée et cherchent des développeurs. Après avoir échangé 3 minutes, on dit oui, on va faire équipe ensemble.

Toute la soirée on a alors essayé de se mettre d’accord sur ce qu’on nous allions réellement essayer de faire. Avec la barrière de la langue (des allemands et des français se parlant en anglais) et avec notre manque d’enthousiasme sur l’idée en elle-même, à minuit nous étions un peu paumés.

Mais après une bonne nuit de sommeil, au matin en se retrouvant dans les locaux, l’idée nous paraissait meilleure que la veille. On a commencé à 9 heures et sauf les pauses pour manger, nous avons bossé non stop. C’était du boulot mais dans une très bonne ambiance.

Nous 4, on se connaissait déjà étant collègues dans la même société, mais on avait pas réellement pas bossé ensemble. Durant cette journée on s’est bien amusé : il y avait de la bonne nourriture, des jus de toute type, de la bière.

En fin de journée on avait quelque chose de présentable dont nous étions plutôt fiers :

On était fatigués mais on s’était bien amusé en travaillant.

Le lendemain matin : présentation des projets

On se retrouve de nouveau tous les 6. On était plutôt en forme, de bonne humeur.

Quelques heures après, nous et tous les autres participants on était présents dans une grande salle, au dernier étage d’une grande tour appartenant au groupe. Très sympa la salle, belle vue, des petits fours.

Après que chaque équipe ait présenté son projet devant une grande salle bien remplie (et donc avec le stress qui viens avec) nous apprenons que nous n’avons pas gagné.

Tant pis. On n’avait pas perdu, c’est juste qu’on n’avait pas gagné. Nuance. Mieux que ça : on a vécu une super expérience, et on sait que l’année prochaine on fera mieux (oui, on ira aussi l’année prochaine pour prendre notre revanche ;)).

On rentrant au travail le lendemain, beaucoup nous ont félicité. C’est très plaisant 🙂

A refaire.

Corneliu Croitoru, développeur CBM.

L'équipe Sportify

L’équipe Sportify

Quand nos annonces prennent l’R : Nettoyage

Cette article fait suite au premier article sur la découverte des données.

Après avoir identifié nos données, l’étape suivante dans tous projets de machine learning est de “nettoyer la donnée”, ceci afin de la rendre plus facilement exploitable et de supprimer les cas incohérents ou trop marginaux (outliers)

cars <- read.csv("finalcars.csv", sep=",", header=TRUE, stringsAsFactors = FALSE)

stringsAsFactors = FALSE nous permet de désactiver la conversion automatique en Factor, cela nous permet d’éviter des optimisations intempestives et notamment de conserver le millésime (yearModel) en tant qu’entier

  • En visualisant le résumé du dataframe, nous observons des NA que nous supprimons :
summary(cars)
##     brand              model             version         
##  Length:258320      Length:258320      Length:258320     
##  Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character  
##                                                          
##                                                          
##                                                          
##                                                          
##   yearModel           mileage             gearbox             energy      
##  Length:258320      Length:258320      Min.   :     0.0   Min.   : 1.000  
##  Class :character   Class :character   1st Qu.:     2.0   1st Qu.: 2.000  
##  Mode  :character   Mode  :character   Median :     2.0   Median : 2.000  
##                                        Mean   :    13.7   Mean   : 1.905  
##                                        3rd Qu.:     2.0   3rd Qu.: 2.000  
##                                        Max.   :999999.0   Max.   :11.000  
##                                        NA's   :123        NA's   :7       
##      doors           powerDin         priceNew           price        
##  Min.   : 0.000   Min.   :    -1   Min.   :      0   Min.   :      0  
##  1st Qu.: 4.000   1st Qu.:    90   1st Qu.:  17200   1st Qu.:   9600  
##  Median : 5.000   Median :   111   Median :  24000   Median :  13990  
##  Mean   : 4.314   Mean   : 65529   Mean   :  26400   Mean   :  17384  
##  3rd Qu.: 5.000   3rd Qu.:   149   3rd Qu.:  31000   3rd Qu.:  20500  
##  Max.   :11.000   Max.   :999999   Max.   :1076400   Max.   :4190000  
##  NA's   :1

Lire la suite

Quand nos annonces prennent l’R

Cette présentation fait suite au tools in action que nous avons donné à Devoxx cette année. L’objectif étant de montrer l’intérêt de R pour découvrir, nettoyer puis enrichir nos données avec des approches de type machine learning.

Chez Car&Boat Media, grâce au site de dépot d’annonces de véhicules d’occasions lacentrale.fr, nous avons à notre disposition plus de 280 000 annonces en publication. Nous souhaitons dans cette présentation vous montrer ce que l’on peut faire très facilement avec R pour découvrir, manipuler et jouer avec la donnée en partant d’un simple dump de ces annonces.

Pour illustrer cela de façon concrète nous allons élaborer un modèle simple de prédiction de prix de vente d’un véhicule (algo supervisé), un équivalent de la cote automobile.

Ensuite nous formerons des groupes de données proches en utilisant un algo non supervisé cette fois (kmeans) pour définir des catégories de véhicules.

Partie 1 : découverte du dataset

Nous avons obtenu un dump au format CSV de toutes les annonces en cours de publication, nous allons l’explorer pour déterminer ce que nous allons pouvoir en faire.

  • Chargement du fichier csv :
cars <- read.csv("finalcars.csv", sep=",", header=TRUE)

Nous créeons ainsi le dataframe cars, structure composée de lignes et de colonnes, que l’on peut assimiler à une table en BDD relationelle.

  • A quoi ressemblent nos premières lignes :
head(cars)

##    brand model                                   version yearModel mileage
## 1 ABARTH   500      1.4 16V T-JET 595 50EME ANNIVERSAIRE      2014     500
## 2 ABARTH   500                      1.4 16V T-JET ABARTH      2012   46750
## 3 ABARTH   500                   1.4 16V TURBO T-JET 140      2012   52250
## 4 ABARTH   500 1.4 16V TURBO T-JET 160CH 595 TURISMO BVR      2012    8800
## 5 ABARTH   500 1.4 16V TURBO T-JET 160CH 595 TURISMO BVR      2013   17850
## 6 ABARTH   500 1.4 16V TURBO T-JET 160CH 595 TURISMO BVR      2013    6911
##   gearbox energy doors powerDin priceNew price
## 1       1      1     3   999999        0 31990
## 2       2      1     3      134        0 13500
## 3       2      1     2   999999        0 14500
## 4       1      1     3      140        0 20690
## 5       1      1     2      140        0 19990
## 6       1      1     2      160        0 21980

Lire la suite