Machine learning avec OVH prescience en quelques clics

Machine learning avec OVH prescience en quelques clics

Dans ses group labs, OVH a lancé prescience, une plateforme de machine learning. C'est gratuit pendant la phase alpha et j'ai donc décidé de tester le future produit.

Il faut demander un accès en bas de la page dédié à prescience et quelque temps après, on reçoit un mail avec le token pour s'identifier sur la pateforme :

mail prescience

J'ai utilisé un des dataset de base pour le machine learning : iris. Il s'agit d'un tableau contenant 150 entrées (disponible dans son intégralité sur cet article wikipédia).

On commence par créer un fichier csv avec les 150 entrées :

sepal_lenght;sepal_width;petal_lenght;petal_width;species
5.1;3.5;1.4;0.2;setosa
4.9;3.0;1.4;0.2;setosa
4.7;3.2;1.3;0.2;setosa
4.6;3.1;1.5;0.2;setosa
[...]
7.0;3.2;4.7;1.4;versicolor
6.4;3.2;4.5;1.5;versicolor
6.9;3.1;4.9;1.5;versicolor
5.5;2.3;4.0;1.3;versicolor
6.5;2.8;4.6;1.5;versicolor
[...]
6.3;3.3;6.0;2.5;virginica
5.8;2.7;5.1;1.9;virginica
7.1;3.0;5.9;2.1;virginica
6.3;2.9;5.6;1.8;virginica
6.5;3.0;5.8;2.2;virginica
[...]

En peut ensuite uploader ce fichier dans prescience :

source upload

Après avoir cliqué sur upload, le système télécharge le fichier et commence à le parser :

source parsing

Lorsqu'il a terminé, on peut préprocesser la source :

source preprocess

Le système nous demande alors quelques informations, notamment le label et le type de problème. Dans notre cas, tout est sélectionné automatiquement :

source preprocess détails

Lorqu'on clique sur sur preprocess, le système lance le préprocessing en quatre étapes :

preprocess

Les deux premières étapes sont plutôt rapides. Les deux suivantes peuvent prendre un peu de temps. Lorsqu'il a terminé le préprocessing, on peut lancer l’optimisation :

dataset optimise

Le système nous demande des paramètres que nous laissons tels quels :

dataset optimise détails

Lorsqu'on clique sur optimise, on obtient quelque chose comme ça :

optimise

Il faut maintenant le laisser travailler un peu. En effet, cette phase peut prendre du temps. À l'issue, on peut lancer l'entrainement :

dataset train

Le système nous demande un nom de modèle :

dataset train détails

Lorsqu'on clique sur train, on obtient cela :

trainning

Quand l'entrainement est terminé, on peut interroger le système. Par exemple, si on entre une longueur des pétales de 1.5 cm, une largeur des sépales de 3 cm, une largeur des pétales de 0.25 cm et une largeur des sépales de 5 cm, le système nous indique qu'il s'agit, avec une probabilité de 1, de l'espèce setosa(ce qui est le cas) :

query

Si on clique sur explain, on obtient le joli graphique suivant :

shap form

Enfin, il est possible d'interroger le système avec curl :

$ curl -X POST "https://prescience-serving.ai.ovh.net/eval/iris/transform-model" -H "Authorization: $token" -H "Content-Type: application/json" -d '{"arguments":{"petal_lenght":1.5,"sepal_width":3,"petal_width":0.25,"sepal_lenght":5}}'
{"result":{"species":"setosa","probability(setosa)":1.0,"probability(versicolor)":0.0,"probability(virginica)":0.0},"arguments":{"imputed_petal_lenght":{"dataType":"double","value":1.5,"opType":"continuous"},"imputed_sepal_width":{"dataType":"double","value":3.0,"opType":"continuous"},"imputed_petal_width":{"dataType":"double","value":0.25,"opType":"continuous"},"imputed_sepal_lenght":{"dataType":"double","value":5.0,"opType":"continuous"},"scaled_imputed_petal_lenght":{"dataType":"double","value":-1.2266889625508433,"opType":"continuous"},"scaled_imputed_sepal_width":{"dataType":"double","value":-0.15118917210787064,"opType":"continuous"},"scaled_imputed_petal_width":{"dataType":"double","value":-1.1917094761129958,"opType":"continuous"},"scaled_imputed_sepal_lenght":{"dataType":"double","value":-1.0113190222659707,"opType":"continuous"}}}

C'est un exemple très simple mais cela fonctionne plutôt bien.

Ainsi, si on possède des données, on peut, sans rien connaitre ou comprendre à l'apprentissage automatisé, mettre en œuvre du machine learning en quelques clics.

Merci OVH.

Pourquoi les géants du Web et du numérique dominent l'intelligence artificielle

Pourquoi les géants du Web et du numérique dominent l'intelligence artificielle

Ce billet conclut ma série de trois articles sur le machine learning.

Dans les précédents articles, nous avons vu qu'avec un minimum de connaissances informatiques, il était assez facilement possible de mettre en place des algorithmes d'apprentissage automatique, permettant, entre autres, de classifier des espèces de plantes à partir de caractéristiques, des images en fonction de leur contenu ou encore des visages.

selfie-reconnu

Mais surtout je concluais le deuxième article en disant que la principale difficulté était de trouver les images d'entraînement.

En effet, on comprend assez aisément que pour avoir des résultats pertinents, il faut avoir la plus grande quantité de données d'entrainement possible. Dans le domaine du machine learning, on dit souvent que les données sont plus importantes que les algorithmes. Ainsi, déjà en 2011, Peter Norvig, directeur de recherche chez Google, déclarait :

We don’t have better algorithms. We just have more data.

Google propose son assistant personnel intelligent gratuitement sur tous les smartphone Android, Apple fait de même avec Siri sur toute sa gamme, et Amazon vend ses Echo Dot à moins de $50. Tout ce que l'on dit à ces assistants est enregistré pour toujours. Ils disposent donc régulièrement de nouvelles centaines de milliers d'heures d'enregistrements, qui leur permettent d'améliorer la qualité des résultats de leur reconnaissance vocale et des réponses apportées.

Google offre d'autres services gratuitement, notamment son système reCAPTCHA qui permet de vérifier que les visiteurs d'un site sont bien humain. Pour cela, la plupart du temps, il s'agit d'une simple case à cocher mais parfois il faut reconnaitre des éléments sur une photographie. Cela permet à Google de valider les prédictions de ses algorithmes et de les nourrir pour accroitre la justesse des résultats.

Je pourrais encore citer d'autres exemples avec lesquels les géants du web alimentent sans cesse leurs bases de données dans le but d'améliorer les prédictions des algorithmes d'apprentissage automatique, mais, je pense que vous avez saisi l'idée.

Et donc, voilà pourquoi les géants du Web et du numérique sont les champions l'intelligence artificielle. Parce qu'ils ont accès aux données nécessaires à l'entrainement des algorithmes. Nous les leur fournissons gratuitement en échange des services qu'ils nous apportent. Ils n'hésitent pas à s'en nourrir constamment.

Si vous voulez créer quelque chose qui se base sur l’intelligence artificielle, il faudra avant tout trouver un moyen d’obtenir, si possible gratuitement, les données pertinentes et en quantité suffisante. Au final, ces données ou même la manière de les collecter pourraient-être un produit à elles seules.

Pour conclure, en entreprise, conservez soigneusement vos données commerciales et techniques, elles pourront peut-être valoir de l'or et servir un jour.

La reconnaissance faciale accessible à tous avec openface en 5 étapes simples

La reconnaissance faciale accessible à tous avec openface en 5 étapes simples

Cet article fait suite à mon billet précédent sur le machine learning. Il s'agit cette fois de classifier des visages ou, plus simplement, de mettre en place un système qui permet de reconnaître, de manière automatique, des personnes grâce à leur visage . Nous allons tester ce système sur les visages du selfie du tout Hollywood des Oscars 2014 :

selfie-oscar-2015

Sur cette image figurent Bradley Cooper, Ellen DeGeneres, Angelina Jolie, Brad Pitt, Meryl Streep, Julia Roberts, Jennifer Lawrence, Lupita Nyong'o, Peter Nyong'o Jr, Kevin Spacey, Jared Leto et Channing Tatum.

Étape 1 : Docker et images d'entrainement

Il faut télécharger et installer docker. Ensuite, il faut récupérer l'image d'openface et la lancer :

$ docker pull bamos/openface
$ docker run -it -v /Users/lemnet/openface:/openface bamos/openface /bin/bash
# cd openface

Ensuite, on crée des dossiers pour y placer nos images d'entrainement :

# mkdir training
# cd training
# mkdir Brad_Pitt
# mkdir Bradley_Cooper
[...]
# cd ..

Ensuite, il faut télécharger une vingtaine de photos pour chaque personne et les placer dans le sous-dossier correspondant :

# tree
.
├── Brad_Pitt
│   ├── 01.jpg
│   ├── 02.jpg
[...]
│   └── 25.jpg
├── Bradley_Cooper
│   ├── 01.jpg
│   ├── 02.jpg
[...]
│   └── 25.jpg
[...]

Étape 2 : Détection de visage et alignement

# /root/openface/util/align-dlib.py ./training/ align outerEyesAndNose ./aligned/ --size 96

Pour toutes les images contenues dans les sous-dossiers du dossier training le script détecte les visages, les extrait, aligne les yeux et le nez, redimensionne les images et place le résultat dans le dossier aligned. Voici deux images montrant ces multiples étapes avec une photo de Brad Pitt et une photo de Bradley Cooper :

brad-pitt-aligned-resizedbradley-cooper-aligned-resized

Étape 3 : Représentation des images alignées

# /root/openface/batch-represent/main.lua -outDir ./result/ -data ./aligned/

À partir des images alignées, ce script génère deux fichiers csv dans le dossier result. Le premier, nommé labels.csv contient les labels. Il ressemble à ça :

1,./aligned/Brad_Pitt/24.png
1,./aligned/Brad_Pitt/17.png
[...]
2,./aligned/Bradley_Cooper/02.png
2,./aligned/Bradley_Cooper/08.png
[...]

Le second, nommé reps.csv contient pour chaque image une représentation numérique :

-0.079513750970364,0.043242372572422,0.07426492869854,-0.091558545827866,0.06730080395937,0.01907422952354,-0.010245048440993,0.043403118848801,-0.01080765388906,-0.0019726541358978,0.029274379834533,0.011781117878854,-0.10427265614271,-0.18958739936352,0.082550443708897,0.045127235352993,-0.096091546118259,-0.017451703548431,0.075089387595654,-0.040827058255672,0.0083134556189179,0.083514250814915,0.025891171768308,-0.1870334893465,0.016636870801449,0.1201656088233,0.076108574867249,-0.089855946600437,0.13932466506958,-0.11345455050468,0.062359347939491,-0.072660997509956,0.12187822908163,-0.0017955830553547,0.15879856050014,-0.025152010843158,0.12112107872963,0.019075144082308,0.14927686750889,-0.069870434701443,0.1209364682436,-0.096725597977638,0.03348121792078,0.059552174061537,-0.094909250736237,0.079473905265331,0.052089180797338,-0.062602028250694,-0.17977291345596,-0.11288245022297,-0.23634988069534,-0.015410038642585,-0.0026467381976545,0.010406941175461,-0.081556968390942,0.023243123665452,0.0054560410790145,-0.056465104222298,-0.30349093675613,0.092260658740997,-0.074208624660969,-0.10985157638788,0.13710018992424,-0.015253474004567,0.21344821155071,0.031170791015029,-0.086570285260677,-0.039965011179447,0.016601404175162,-0.019380843266845,-0.053903806954622,-0.045722220093012,-0.097987584769726,-0.034954115748405,0.075692936778069,-0.039322711527348,-0.047042615711689,0.086616508662701,-0.0038034450262785,-0.064381942152977,-0.10132753103971,0.044696487486362,0.027787212282419,0.13075566291809,-0.013653952628374,-0.015349956229329,0.022534357383847,0.10326029360294,-0.047985222190619,0.046620875597,0.17566956579685,0.0075213755480945,-0.13740640878677,0.096532210707664,0.052546411752701,-0.019534885883331,-0.022727446630597,0.063606709241867,-0.051598604768515,0.025997584685683,-0.094908900558949,-0.13522194325924,-0.10364888608456,-0.089708864688873,0.12060751020908,0.068853013217449,0.19906789064407,0.061816807836294,0.075233280658722,-0.047512516379356,-0.054883949458599,-0.06100058555603,-0.0027660827618092,0.0016581763047725,0.13476423919201,-0.072945423424244,-0.078956924378872,-0.067385271191597,0.082239367067814,0.045021571218967,0.08066825568676,-0.018503317609429,0.0010944502428174,0.050739988684654,0.086741372942924,0.011823086068034,0.094880275428295,-0.0049750739708543
-0.070263981819153,-0.064780130982399,0.068833753466606,-0.079573705792427,-0.02393763884902,0.056701745837927,-0.025278033688664,0.10987707227468,0.072828710079193,-0.012801049277186,0.031829673796892,-0.026127202436328,-0.11176656186581,-0.13374063372612,0.090488865971565,-0.041589949280024,-0.14681378006935,0.044288713485003,0.10873435437679,-0.15384067595005,0.0046405284665525,0.16082474589348,-0.0067559820599854,-0.1942777633667,-0.014278737828135,0.1302190721035,0.055440001189709,-0.10188861936331,0.042436596006155,-0.13196943700314,0.077907674014568,-0.091224417090416,0.083212152123451,-0.049031566828489,0.14888316392899,-0.03791756555438,0.09282723814249,-0.010352308861911,0.14886169135571,0.035943761467934,0.13995899260044,0.00011858189100167,-0.073888853192329,0.061065085232258,-0.11892623454332,-0.13252264261246,-0.035222668200731,-0.10962913930416,0.02320571616292,-0.11148305237293,-0.15579849481583,-0.0012985581997782,0.040522128343582,0.10002072900534,-0.11489909887314,0.016101259738207,0.14151233434677,-0.11592414230108,-0.19397619366646,0.009063757956028,-0.069678321480751,-0.12178941071033,0.065132349729538,0.050163809210062,0.053401399403811,0.0057254293933511,0.066441938281059,-0.05257598310709,0.17400214076042,0.00010578936780803,-0.011980256065726,-0.025771487504244,0.01014574803412,0.014672530815005,0.030921567231417,-0.10137071460485,-0.18099300563335,-0.026000754907727,-0.056350953876972,-0.051783930510283,-0.040815364569426,0.12529125809669,0.12283923476934,0.11534231901169,0.072093278169632,0.0099285449832678,0.10711506009102,0.09900077432394,-0.031046276912093,-0.069916144013405,0.098551474511623,0.049529325217009,-0.067352935671806,-0.0083199115470052,0.0075457850471139,-0.099030457437038,-0.04363788664341,0.058397993445396,-0.082195706665516,0.081268534064293,-0.064576953649521,-0.079441629350185,0.01824301853776,-0.1133379638195,0.14663629233837,-0.022325491532683,0.17956200242043,-0.051539111882448,0.011463063769042,0.032830137759447,-0.035160392522812,-0.10720814019442,-0.0049185594543815,-0.063472390174866,0.072514407336712,-0.051096092909575,0.031789872795343,-0.10537253320217,0.07302663475275,-0.13138537108898,0.14706198871136,-0.05070673674345,0.042252391576767,-0.051124904304743,0.062476176768541,-0.056198608130217,0.088456481695175,0.17326207458973
[...]

Étape 4 : Entraînement

# /root/openface/demos/classifier.py train ./result/

Ce script va générer un modèle SVM (Machine à vecteurs de support) dans le fichier classifier.pkl. Il sera utilisé pour reconnaître les visages dans l'étape suivante

Étape 5 : Reconnaissance

# /root/openface/demos/classifier.py infer --multi ./result/classifier.pkl selfie.jpg

Ce script tente de reconnaitre les visages et retourne quelque chose comme ça :

=== selfie.jpg ===
List of faces in image from left to right
Predict Jennifer_Lawrence @ x=623 with 0.83 confidence.
Predict Ellen_DeGeneres @ x=981 with 0.37 confidence.
Predict Channing_Tatum @ x=1002 with 0.28 confidence.
Predict Channing_Tatum @ x=1146 with 0.20 confidence.
Predict Julia_Roberts @ x=1359 with 0.45 confidence.
Predict Ellen_DeGeneres @ x=1392 with 0.84 confidence.
Predict Kevin_Spacey @ x=1751 with 0.76 confidence.
Predict Bradley_Cooper @ x=2051 with 0.78 confidence.
Predict Brad_Pitt @ x=2187 with 0.76 confidence.
Predict Peter_Nyongo_Jr @ x=2779 with 0.78 confidence.

On remarque que Channing Tatum et Ellen DeGeneres ont été trouvés deux fois, mais surtout que des résultats textuels sont difficiles à interpréter avec des images contenant beaucoup de visage (option --multi). Ainsi, en modifiant quelque peu le script, on peut obtenir assez facilement l'image suivante, plus facilement interprétable :

selfie-reconnu

Sur l'image, on remarque que :

  • six visages sont reconnus avec un indice de confiance supérieur à 75 % (en vert).
  • un visage est reconnu avec un indice de confiance compris entre 40 % et 75 % (en orange).
  • deux visages sont reconnus avec un indice de confiance compris entre 25 % et 40 % (en rouge). Pour l'un des deux, l'algorithme se trompe.
  • un visage est reconnu avec un indice de confiance inférieur à 25 % (Channing Tatum dans le carré rouge dans l'oreille de Ellen DeGeneres)

Huit visages sont reconnus correctement et il n'y a que deux erreurs : Meryl Streep n'est pas reconnue et un visage inexistant est détecté dans l'oreille de Ellen DeGeneres.

Conclusion

On constate qu'il n'est pas compliqué de mettre en place un système de reconnaissance faciale en cinq étapes simples. Au final, la phase la plus compliquée est, en fait, de trouver les images d'entraînement.

Le machine learning aujourd'hui et ce que cela implique

Le machine learning aujourd'hui et ce que cela implique

Le machine learning, ou apprentissage automatique ou statistique en français, cet article wikipédia nous dit que cela "concerne la conception, l'analyse, le développement et l'implémentation de méthodes permettant à une machine (au sens large) d'évoluer par un processus systématique, et ainsi de remplir des tâches difficiles ou impossibles à remplir par des moyens algorithmiques plus classiques."

Avant tout, je précise que je ne suis pas un spécialiste du domaine.

En se basant sur des exemples issus d'une série de vidéos de Google Developers, nous allons voir à quoi cela correspond plus concrètement. Pour cela nous utiliseront Scikit-learn et TensorFlow, des bibliothèques python libres d'apprentissage automatique.

  1. Classification d'éléments par caractéristiques

Il s'agit d'être capable de classifier des éléments à partir d'un jeu de données contenant des caractéristiques.

Dans cet exemple, nous allons tenter de classifier des iris dans leur sous-espèce à partir de la longueur et de la largeur des sépales et des pétales. Pour cela nous disposons du tableau suivant contenant 150 entrées (disponible dans son intégralité sur cet article wikipédia) :

longueur des sépales largeur des sépales longueur des pétales largeur des pétales espèce
5,1 3,5 1,4 0,2 setosa
4,9 3 1,4 0,2 setosa
4,7 3,2 1,3 0,2 setosa
4,6 3,1 1,5 0,2 setosa
5 3,6 1,4 0,2 setosa
5,4 3,9 1,7 0,4 setosa
4,6 3,4 1,5 0,2 setosa
[...]
7 3,2 4,7 1,4 versicolor
6,4 3,2 4,5 1,5 versicolor
6,9 3,1 4,9 1,5 versicolor
5,5 2,3 4 1,3 versicolor
6,5 2,8 4,6 1,5 versicolor
5,7 2,8 4,5 1,3 versicolor
[...]
6,3 3,3 6 2,5 virginica
5,8 2,7 5,1 1,9 virginica
7.1 3 5,9 2,1 virginica
6.3 2,9 5,6 1,8 virginica
6.5 3 5,8 2,2 virginica
7.6 3 6,6 2,1 virginica
[...]

Le code suivant utilise une méthode générant un arbre de décision. Il résout le problème en quelques lignes :

import numpy as np
from sklearn.datasets import load_iris
from sklearn import tree

# (1)
# import des donnees
iris = load_iris()

# (2)
test_idx = [0, 50, 100] 
# donnees entrainement
train_target = np.delete(iris.target, test_idx)
train_data = np.delete(iris.data, test_idx, axis=0)
# donnees test
test_target = iris.target[test_idx]
test_data = iris.data[test_idx]

# (3)
# entrainement
clf = tree.DecisionTreeClassifier()
clf = clf.fit(train_data, train_target)

# (4)
txt_result =['setosa', 'versicolor', 'virginica']
# calcul et affichage des resulats
result = clf.predict(test_data)
for i in range(len(result)):
    print str(test_data[i]) + " --> ",
    print txt_result[result[i]]

Dans l'ordre, on effectue les opérations suivantes :

  • Importer toutes les données
  • Exclure la première setosa (idx 0), la première versicolor (idx 50) et la première virginica (idx 100) des données d'entrainement, pour les utiliser comme données de test
  • L'algorithme créé un arbre de décision
  • Calculer et afficher les résultats pour les données de test

A l'exécution du script, on remarque que l'arbre de décision créé par l'algorithme, permet effectivement de catégoriser l'espèce :

$ python arbre_iris.py
[ 5.1  3.5  1.4  0.2] -->  setosa
[ 7.   3.2  4.7  1.4] -->  versicolor
[ 6.3  3.3  6.   2.5] -->  virginica

Avec un peu plus de code, de manière à visualiser son fonctionnement, on peut générer une image représentant l'arbre de décision qui a été créé par l'algorithme :

iris

On peut aussi utiliser la méthode des k plus proches voisins. Pour cela il suffit de changer deux lignes dans le code précédent :

import numpy as np
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier # <--------------- ligne changee

# import des donnees
iris = load_iris()

test_idx = [0, 50, 100] 
# donnees entrainement
train_target = np.delete(iris.target, test_idx)
train_data = np.delete(iris.data, test_idx, axis=0)
# donnees test
test_target = iris.target[test_idx]
test_data = iris.data[test_idx]

# entrainement
clf = KNeighborsClassifier() # <--------------- ligne changee
clf = clf.fit(train_data, train_target)

txt_result =['setosa', 'versicolor', 'virginica']
# calcul et affichage des resulats
result = clf.predict(test_data)
for i in range(len(result)):
    print str(test_data[i]) + " --> ",
    print txt_result[result[i]]

À l'exécution du script, on obtient les mêmes résultats qu'auparavant, l'algorithme catégorise bien l'espèce :

$ python arbre_iris.py
[ 5.1  3.5  1.4  0.2] -->  setosa
[ 7.   3.2  4.7  1.4] -->  versicolor
[ 6.3  3.3  6.   2.5] -->  virginica

On constate donc qu'avec une quinzaine de ligne de code, il est assez simple de classifier des éléments à partir d'un jeu de données contenant des caractéristiques numériques.

  1. Classification d'images

Il s'agit d'être capable de classifier des images, en entrainant un algorithme avec d'images connues.

Dans cet exemple, nous allons tenter de différencier et catégoriser des images de roses et de tulipes. Pour cela nous utiliserons inception, un réseau pré-entrainé développé par Google. Pour terminer son entrainement, nous lui fournirons 641 images de roses et 799 images de tulipes, dont voici un échantillon :

rosestulipes

On commence par terminer l'entrainement de l'algorithme avec la commande suivante :

$ python retrain.py \
--bottleneck_dir=/bottlenecks \
--model_dir=/inception \
--output_graph=/retrained_graph.pb \
--output_labels=/retrained_labels.txt \
--image_dir /img

Elle prend un certain temps et affiche les éléments suivants :

Looking for images in 'roses'
Looking for images in 'tulipes'
Creating bottleneck at /bottlenecks/roses/9433167170_fa056d3175.jpg.txt
Creating bottleneck at /bottlenecks/roses/9458445402_79e4dfa89c.jpg.txt
[...]
Creating bottleneck at /bottlenecks/tulipes/8712263493_3db76c5f82.jpg.txt
Creating bottleneck at /bottlenecks/tulipes/8712266605_3787e346cd_n.jpg.txt
[...]
2016-12-25 18:46:40.000000: Step 0: Train accuracy = 59.0%
2016-12-25 18:46:40.236750: Step 0: Cross entropy = 0.643191
2016-12-25 18:46:40.583488: Step 0: Validation accuracy = 50.0%
2016-12-25 18:46:43.671932: Step 10: Train accuracy = 81.0%
2016-12-25 18:46:43.672876: Step 10: Cross entropy = 0.514823
2016-12-25 18:46:44.015942: Step 10: Validation accuracy = 87.0%
[...]
2016-12-25 19:04:52.943261: Step 3999: Train accuracy = 98.0%
2016-12-25 19:04:52.944066: Step 3999: Cross entropy = 0.088042
2016-12-25 19:04:53.190913: Step 3999: Validation accuracy = 85.0%
Final test accuracy = 93.0%
Converted 2 variables to const ops.

Après qu'il a analysé les 1440 images, nous obtenons deux fichiers : "retrained_graph.pb" et "retrained_labels.txt". À partir de ces deux fichiers, nous pouvons tenter d'identifier des images en utilisant le code suivant :

import tensorflow as tf, sys

image_path = sys.argv[1]

# Read in the image_data
image_data = tf.gfile.FastGFile(image_path, 'rb').read()

# Loads label file, strips off carriage return
label_lines = [line.rstrip() for line in tf.gfile.GFile("./retrained_labels.txt")]

# Unpersists graph from file
with tf.gfile.FastGFile("./retrained_graph.pb", 'rb') as f:
    graph_def = tf.GraphDef()
    graph_def.ParseFromString(f.read())
    _ = tf.import_graph_def(graph_def, name='')

with tf.Session() as sess:
    # Feed the image_data as input to the graph and get first prediction
    softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')

    predictions = sess.run(softmax_tensor, {'DecodeJpeg/contents:0': image_data})

    # Sort to show labels of first prediction in order of confidence
    top_k = predictions[0].argsort()[-len(predictions[0]):][::-1]

    for node_id in top_k:
        human_string = label_lines[node_id]
        score = predictions[0][node_id]
        print('%s (score = %.5f)' % (human_string, score))

Il suffit ensuite de lui passer une image en argument et il l'identifie lorsque c'est possible :

$ python label_image.py rose.jpg
roses (score = 0.99040)
tulipes (score = 0.00960)
$ python label_image.py tulipe.jpg
tulipes (score = 0.99649)
roses (score = 0.00351)
$ python label_image.py marguerite.jpg
roses (score = 0.66204
tulipes (score = 0.33796)

On constate que, lorsqu'on lui fournit une image de rose, il l'identifie à 99 %. Il en est de même pour la tulipe. Lorsqu'on lui fournit une image contenant une marguerite, un type d'image pour lequel l'algorithme n'a pas été entrainé, il tente tout de même de l'identifier comme une rose ou une tulipe. Mais les indices de confiance sont beaucoup moins tranchés et on peut conclure qu'il ne s'agit ni d'une rose, ni d'une tulipe.

Ainsi, de nouveau, une quinzaine de ligne de code permet de classifier des images pour lesquelles l'algorithme a été entrainé.

  1. Ce que cela implique

Dans le cas du premier exemple, on pourrait étudier les données du tableau et en déduire un arbre de décision, qu'un développeur pourrait transformer en code. Cependant, le nombre de lignes nécessaires serait beaucoup plus important et à chaque nouvelle problématique l'arbre de décision devrait être de nouveau créé et retraduit en code.

C'est là toute la puissance des algorithmes d'apprentissage automatiques, le même code peut être réutilisé pour des problèmes différents.

Dans le cas du second exemple, c'est totalement différent. Il s'agit d'une problématique qu'on ne peut pas résoudre en utilisant des méthodes de développement procédurales classiques. Seuls les réseaux de neurones permettent d'obtenir des résultats fiables.

Comme nous l'avons montré dans les paragraphes précédents, aujourd'hui, des outils libres tels que Scikit-learn ou TensorFlow permettent de mettre en œuvre, sans trop de difficultés, des algorithmes d'apprentissage automatique. De ce fait, il n'est plus nécessaire de disposer d'une grosse équipe de recherche et développement pour pouvoir les implémenter dans les entreprises.

Quand je repense aux quelques fois où j'ai été confronté à des problématiques de classements, que j'ai dû résoudre avec des centaines de lignes de codes, je me dis qu'aujourd'hui je pourrais en venir à bout beaucoup plus simplement et rapidement.