Retours d'expériences
sur l'IA
2022

Nicolas Decoster
@ogadaki
intro
intro
Nicolas Decoster
@ogadaki
1992 - 1999

thèse en traitement d'image
Bordeaux

ingénieur informatique
Nicolas Decoster
@ogadaki
Toulouse
1999 - 2007

informatique et science

Nicolas Decoster
@ogadaki
Toulouse
2007 - 2020
informatique et science
Nicolas Decoster
@ogadaki
Toulouse
2014 - now

médiation et vulgarisation
Nicolas Decoster
@ogadaki
Toulouse
2020 - now
démocratisation de la programmation

adacraft.org
R&T détection d’objets

2015
« Évaluation de l’apport de méthodes de détection
d’objets issues du domaine de la photo numérique à
celui de la télédétection »


on se limite à des
algorithmes
d'apprentissage supervisé
notre cas d'étude :
détection d'avions
données d'étude :
12 images Pléiades sur des aéroports
R&T WebAssembly

2018
WebAssembly ?
Web + Assembleur ?
?!?!?
"WebAssembly or wasm is a new portable, size- and load-time-efficient format suitable for compilation to the web."
portable
efficient
compilation to the web
webassembly.org :
fast!
safe!
#include <stdio.h>
int main() {
printf("WebAssembly\n");
}
$ ls webapp.*
webapp.html webapp.js webapp.wasm
$ emcc main.c -o webapp.html

WebAssembly
$ ls webapp.*
webapp.html webapp.js webapp.wasm
$ firefox webapp.html

s'ocuppe du sale boulot à votre place
compilation du C
émission du binaire WebAssembly
création du code JavaScript nécessaire
ajout de dépendances (stdio...)
etc.
liens avec canvas et WebGL
Et sous le capot ?
un format binaire
moteur WebAssembly dédié dans le navigateur
interaction avec le moteur JavaScript
format WebAssembly
(module
(table 0 anyfunc)
(memory $0 1)
(export "memory" (memory $0))
(export "_Z4facti" (func $_Z4facti))
(func $_Z4facti (param $0 i32) (result f64)
(local $1 i64)
(local $2 i64)
(block $label$0
(br_if $label$0
(i32.lt_s
(get_local $0)
(i32.const 1)
)
)
(set_local $1
(i64.add
(i64.extend_s/i32
(get_local $0)
)
(i64.const 1)
)
)
(set_local $2
(i64.const 1)
)
(loop $label$1
(set_local $2
(i64.mul
(get_local $2)
(tee_local $1
(i64.add
(get_local $1)
(i64.const -1)
)
)
)
)
(br_if $label$1
(i64.gt_s
(get_local $1)
(i64.const 1)
)
)
)
(return
(f64.convert_s/i64
(get_local $2)
)
)
)
(f64.const 1)
)
)
0000000: 6100 6d73 0001 0000 0601 6001 7f01 7c01
0000010: 0203 0001 0404 7001 0000 0305 0001 0701
0000020: 0215 6d06 6d65 726f 0279 0800 5a5f 6634
0000030: 6361 6974 0000 3f0a 3d01 0201 027e 2040
0000040: 4100 4801 000d 0020 42ac 7c01 0121 0142
0000050: 0221 4003 0220 0120 7f42 227c 7e01 0221
0000060: 0120 0142 0d55 0b00 0220 0fb9 440b 0000
0000070: 0000 0000 3ff0 000b
0000000: 0061 736d # WASM_BINARY_MAGIC
0000004: 0100 0000 # WASM_BINARY_VERSION
# section "Type" (1)
0000008: 01 # section code
0000009: 00 # section size (guess)
000000a: 01 # num types
# type 0
000000b: 60 # func
000000c: 01 # num params
000000d: 7f # i32
000000e: 01 # num results
000000f: 7c # f64
0000009: 06 # FIXUP section size
# section "Function" (3)
0000010: 03 # section code
0000011: 00 # section size (guess)
0000012: 01 # num functions
0000013: 00 # function 0 signature index
0000011: 02 # FIXUP section size
# section "Table" (4)
0000014: 04 # section code
0000015: 00 # section size (guess)
0000016: 01 # num tables
# table 0
0000017: 70 # anyfunc
0000018: 00 # limits: flags
0000019: 00 # limits: initial
0000015: 04 # FIXUP section size
# section "Memory" (5)
000001a: 05 # section code
000001b: 00 # section size (guess)
000001c: 01 # num memories
# memory 0
000001d: 00 # limits: flags
000001e: 01 # limits: initial
000001b: 03 # FIXUP section size
# section "Export" (7)
000001f: 07 # section code
0000020: 00 # section size (guess)
0000021: 02 # num exports
0000022: 06 # string length
0000023: 6d65 6d6f 7279 # export name
0000029: 02 # export kind
000002a: 00 # export memory index
000002b: 08 # string length
000002c: 5f5a 3466 6163 7469 # export name
0000034: 00 # export kind
0000035: 00 # export func index
0000020: 15 # FIXUP section size
# section "Code" (10)
0000036: 0a # section code
0000037: 00 # section size (guess)
0000038: 01 # num functions
# function body 0
0000039: 00 # func body size (guess)
000003a: 01 # local decl count
000003b: 02 # local type count
000003c: 7e # i64
000003d: 02 # block
000003e: 40 # void
000003f: 20 # get_local
0000040: 00 # local index
0000041: 41 # i32.const
0000042: 01 # i32 literal
0000043: 48 # i32.lt_s
0000044: 0d # br_if
0000045: 00 # break depth
0000046: 20 # get_local
0000047: 00 # local index
0000048: ac # i64.extend_s/i32
0000049: 42 # i64.const
000004a: 01 # i64 literal
000004b: 7c # i64.add
000004c: 21 # set_local
000004d: 01 # local index
000004e: 42 # i64.const
000004f: 01 # i64 literal
0000050: 21 # set_local
0000051: 02 # local index
0000052: 03 # loop
0000053: 40 # void
0000054: 20 # get_local
0000055: 02 # local index
0000056: 20 # get_local
0000057: 01 # local index
0000058: 42 # i64.const
0000059: 7f # i64 literal
000005a: 7c # i64.add
000005b: 22 # tee_local
000005c: 01 # local index
000005d: 7e # i64.mul
000005e: 21 # set_local
000005f: 02 # local index
0000060: 20 # get_local
0000061: 01 # local index
0000062: 42 # i64.const
0000063: 01 # i64 literal
0000064: 55 # i64.gt_s
0000065: 0d # br_if
0000066: 00 # break depth
0000067: 0b # end
0000068: 20 # get_local
0000069: 02 # local index
000006a: b9 # f64.convert_s/i64
000006b: 0f # return
000006c: 0b # end
000006d: 44 # f64.const
000006e: 0000 0000 0000 f03f # f64 literal
0000076: 0b # end
0000039: 3d # FIXUP func body size
0000037: 3f # FIXUP section size
format binaire
format texte
(s-expression)
format binaire avec commentaires
moteur WebAssembly
module
instance
imports et exports
mémoire linéaire
format binaire
Notions
$ wget http://zlib.net/zlib-1.2.11.tar.gz
$ tar xf zlib-1.2.11.tar.gz
$ cd zlib-1.2.11.tar.gz
$ emconfigure ./configure --prefix=./dist
$ emmake make
$ emmake make install
Emscripten pour compiler des outils existants
WebAssembly, pour faire quoi ?
jeux
édition de vidéo ou d'image
application musicale
reconnaissance d'image
VR et AR
visualisation et simulation scientifique
etc.
je prends
je prends
Exemples concrets
d'utilisation de WebAssembly


use case
Magellium - CNES
un outil de visualisation d'images satellite
avec traitements
100% côté navigateur
WebAssembly
pour le Deep Learning
OLD!
(2017)
Expérimentations
d'exécution d'inférence deep learning
en utilisant la bibliothèque WebDNN
avec son backend WebAssembly


image satellite Sentinel 2
tuile 223 × 223 pixels
masque de détection
de nuages épais
Inférence deep learning
par un réseau Unet appris avec Keras
utilise les 13 bandes de Sentinel 2


image satellite Sentinel 2
tuile 223 × 223 pixels
masque de détection
de nuages épais
Inférence deep learning
17 secondes pour une tuile sur un vieux portable


(intermède)
WebDNN avec backend "WebGPU"
iPhone 7
MacBook Pro
2016
WebAssembly
WebGPU
30 s
0,8 s
18 s
0,5 s
extension pour utiliser
un modèle Deep Learning
en programmation par blocs

adacraft.org
En lien avec Teachable Machine
(Google)
extension pour utiliser
un modèle Deep Learning
en programmation par blocs

+



Merci !
Nicolas Decoster @ogadaki
bonus
dans ces outils j'ai manipulé
des "petites images" (moins de 100 Mo)
dans des formats standards (PNG...)
lisibles par les navigateurs
en général
les données satellites
sont dans d'autres formats
JPEG 2000
très utilisé pour les images satellites
images de très grande taille
format de compression multiéchelle
encodages exotiques
(plus que trois "couleurs", pas de 8bits)
source : wikipedia
$ ll IMG_R2C1.JP2 -rw-r--r-- 1 ada ada 3.3G Nov 12 2009 IMG_R2C1.JP2 $ gdalinfo IMG_R2C1.JP2 Driver: JP2OpenJPEG/JPEG-2000 driver based on OpenJPEG library Files: IMG_R2C1.JP2 Size is 57344, 28672 Band 1 Block=4096x4096 Type=UInt16, ColorInterp=Red Overviews: 28672x14336, 14336x7168, 7168x3584, 3584x1792, 1792x896 NBITS=12 Band 2 Block=4096x4096 Type=UInt16, ColorInterp=Green Overviews: 28672x14336, 14336x7168, 7168x3584, 3584x1792, 1792x896 NBITS=12 Band 3 Block=4096x4096 Type=UInt16, ColorInterp=Blue Overviews: 28672x14336, 14336x7168, 7168x3584, 3584x1792, 1792x896 NBITS=12 Band 4 Block=4096x4096 Type=UInt16, ColorInterp=Undefined Overviews: 28672x14336, 14336x7168, 7168x3584, 3584x1792, 1792x896 NBITS=12
mais JPEG 2000 n'est pas un format lisible par les navigateurs
il existe des bibliothèques de lecture en C
OpenJPEG
open source
Kakadu
payant (licence de développement)
la référence pour le JPEG 2000
on utilise emscripten pour compiler Kakadu en WebAssembly
$ kdu_expand \
-i full_image.jp2 \
-o extract.bmp \
-region {0.3,0.05},{0.8,0.02}
Ligne de commande pour
extraire une partie d'une image JPEG 2000 et pour l'enregistrer en BMP


affichage dans le navigateur ?

bibliothèque JavaScript
affichage de
données cartographiques
et d'images


map.addLayer(new ol.layer.Tile({
source: new ol.source.TileImage({
tileLoadFunction: function (tile, zxyTileUrl) {
const [ x, y, w, h, reduce ] = getKduRegion(zxyTileUrl)
callWasmKduExpand([
'-i', inputJp2File,
'-o', subBmpFile,
'-region', `{${x},${y}},{${w},${h}})`,
'-reduce', `${reduce}`
])
const binary = readFileFromEmscriptenFS(subBmpFile)
const base64String = binaryArrayToBase64String(binary)
const dataUrl = 'data:image/bmp;base64,' + base64String
tile.getImage().src = dataUrl
}
})
}))
ol = OpenLayers
affichage ok et fluide !
(démo dans quelques slides)
mais...
uniquement sur des petites images JP2
(max 100 Mo)
raison :
fichiers stockés dans la mémoire du navigateur
(MEMFS d'emscripten)
comment lire et afficher
des images de plusieurs Go ?
utiliser l'API File de JavaScript
permet d'accéder à un intervalle d'octets si appelé depuis un Web Worker !
emscripten fournit
le pseudo système de fichiers WORKERFS
qui permet cela

wasm
archi pour fichier local
affichage d'un fichier local de
plusieurs Go
ok et fluide !
✔
affichage d'un fichier distant de
plusieurs Go ?


archi pour fichier local
archi pour fichier distant
wasm
wasm
affichage d'un fichier distant de
plusieurs Go
ok et fluide !
✔
WebAssembly
en dehors du navigateur
#include <stdio.h>
int main() {
printf("WebAssembly\n");
}
$ emcc main.c -o cli.js
$ ls
cli.js cli.wasm main.c
$ node cli.js
WebAssembly

détection d'avions avec l'algorithme ICF
traitements en batch de la
détection d'avions avec ICF
sur un ensemble de grandes images
avec le même binaire WebAssembly
mais côté serveur



Google Cloud
Functions
Google Cloud
PubSUb

old
High Resolution
Snow & Ice
Monitoring
Production de cartes
de glace et de neige
sur l'Europe
en "temps réel"

image Sentinel 2

temps réel ?
3 h
entre
image Sentinel 2
disponible (ESA)
cartes de neige et de glace
calculées

2019 - now
EEA
EEA
ESA
Union européenne
Copernicus permet de rassembler l'ensemble des données obtenues à partir de satellites environnementaux et d'instruments de mesure sur site, afin de produire une vue globale et complète de l'état de notre planète





~ 700 images par jour
arrivée progressive
entre 15h et 22h
mais pas toujours...
temps nécessaire
pour calculer
les cartes de neige et de glace
sur une image
~40 min
un job

Orchestrator
main process controlling the system
Administration
System monitoring and maintenance
Worker pool
run multiple Snow and Ice softwares
Database
job descriptions
Storage
standard S3 object storage
Data Access
S&I products for the end-users

worker VM configuration:
2 vCores 16 GB RAM 64 GB local SSD
jusqu'à 200 VM en même temps
hébergeur cloud utilisé
technologie de cet hébergeur

$ openstack flavor list
+-----+-----------+-------+------+-----------+-------+-----------+
| ID | Name | RAM | Disk | Ephemeral | VCPUs | Is_Public |
+-----+-----------+-------+------+-----------+-------+-----------+
| 1 | m1.tiny | 512 | 1 | 0 | 1 | True |
| 2 | m1.small | 2048 | 20 | 0 | 1 | True |
| 3 | m1.medium | 4096 | 40 | 0 | 2 | True |
| 4 | m1.large | 8192 | 80 | 0 | 4 | True |
| 5 | m1.xlarge | 16384 | 160 | 0 | 8 | True |
+-----+-----------+-------+------+-----------+-------+-----------+
$ openstack \
server create \
--flavor 1 \
--image 397e713c-b95b-4186-ad46-6126863ea0a9 \
--security-group default \
--key-name KeyPair01 \
--user-data cloudinit.file \
my_new_server
+--------------------------------------+-----------------------------------------------+
| Field | Value |
+--------------------------------------+-----------------------------------------------+
...
| accessIPv4 | |
| adminPass | E4Ksozt4Efi8 |
| created | 2016-11-30T14:48:05Z |
| flavor | m1.tiny |
| id | 89015cc9-bdf1-458a-8518-fdca2b4a5785 |
| image | cirros (397e713c-b95b-4186-ad46-6126863ea0a9) |
| key_name | KeyPair01 |
| name | my_new_server |
| project_id | 5669caad86a04256994cdf755df4d3c1 |
| properties | |
| security_groups | [{u'name': u'default'}] |
| status | BUILD |
| updated | 2016-11-30T14:48:05Z |
| user_id | c36cec73b0e44876a4478b1e6cd749bb |
+--------------------------------------+-----------------------------------------------+

resource "openstack_compute_instance_v2" "basic" {
name = "basic"
image_id = "397e713c-b95b-4186-ad46-6126863ea0a9"
flavor_id = "1"
key_pair = "KeyPair01"
security_groups = ["default"]
network {
name = "my_network"
}
}
Terraform
création d'une VM sur OpenStack
l'infrastructure du projet
est gérée avec Terraform
ça facilite les modifications
et les redéploiements
l'infrastructure est décrite avec du code
elle est versionnée comme tout autre code
le système comprend
un ensemble de services
création d'un job, sa configuration, son lancement, etc.
chaque service est un composant logiciel packagé dans un container Docker
comment s'assurer que les services sont bien en train de tourner sur une VM ?
Problématique :
Solution :
Nomad

bonus
Nomad est également utilisé
pour gérer les queues de jobs
de calcul des cartes
de neige et de glace
nomad server
VM nomad
nomad client
VM orchestrator
nomad client
VM worker 1
service job-config
service job-results
run job 64A8B
nomad client
VM worker 2
run job 197C0
etc.
service job-creation
service ...


Retours d'expériences sur l'IA
By Nicolas Decoster
Retours d'expériences sur l'IA
Quel traitement des données dans l’industrie du spatial ? Retour d’expérience - novembre 2020 - Université Fédérale Toulouse Midi-Pyrénées
- 224