← Retour au blog

Edge AI inference au plus pres

Lucian BLETAN

L’edge AI déplace l’exécution des modèles là où les données naissent: caméras, capteurs, postes de travail, terminaux industriels. On y gagne en latence, en résilience et en confidentialité: moins d’allers-retours réseau, moins d’exposition des données brutes. Le revers: des ressources limitées, des connexions intermittentes et des mises à jour qui doivent rester sûres et ciblées. Ce guide propose des cas d’usage, des contraintes à garder en tête et un mode opératoire concret pour livrer des modèles compacts.

prérequis

  • un modèle déjà utile hors ligne (latence/CPU mesurés localement).
  • un format d’inférence portable (ONNX, TFLite) et un runtime compatible.
  • des métriques de service (latence P95, CPU/RAM, taux d’erreurs) à collecter.
  • un mécanisme d’actualisation des modèles (OTA) avec canal de retour d’expérience.

aperçu rapide

  • profiler d’abord: latence cible, budget CPU/RAM, autonomie énergétique.
  • compresser intelligemment: quantification, pruning, distillation.
  • limiter les flux: post-traiter à la périphérie, remonter des résumés.
  • synchroniser sobrement: delta updates, canary, rollback fiable.
  • prévoir le hors-ligne: caches, files locales, stratégie de retry.
  • tracer et auditer: versions, hachages, profils d’usage et incidents.

cas d’usage

  • contrôle qualité en usine (vision embarquée sur ligne de production).
  • détection d’anomalies réseau (sondes locales avec agrégation périodique).
  • assistants sur terminaux internes (OCR, classification, NER) sans cloud.

edge ai

usine

controle visuel

rejet automatique

reseau

anomalies flux

alerte locale

terminaux

ocr formulaire

assistant technique

contraintes

  • mémoire et CPU limités selon le matériel (CPU arm, GPU léger, NPU).
  • connectivité variable (wifi instable, 4g saturée, réseau isolé).
  • mises à jour segmentées (batches, fenêtres de maintenance, dépôts locaux).

pratiques

  • quantification et pruning pour tenir la latence cible.
  • caches et profils d’usage pour éviter les recalculs inutiles.
  • fallback hors-ligne pour les fonctions critiques (dégradé acceptable).
update:
  canary_percent: 5
  rollback_on_error: true

tutoriel pas-à-pas

étape 1: profiler le modèle sur la cible

Mesurez la latence, l’utilisation CPU/RAM et la consommation énergétique sur l’appareil final (pas sur votre laptop).

# exemple générique de profilage onnxruntime (pseudo)
python infer.py --model model.onnx --input sample.npz --warmup 10 --iters 200 --metrics out.json

étape 2: convertir et quantifier

Convertissez au format d’inférence et appliquez une quantification post-entraînement si acceptable pour la tâche.

# quantification post-entrainement onnx (exemple minimal)
from onnxruntime.quantization import quantize_dynamic, QuantType
quantize_dynamic(
    model_input="model_float.onnx",
    model_output="model_int8.onnx",
    weight_type=QuantType.QInt8
)

étape 3: pruner et distiller si besoin

Réduisez les couches/neurones les moins contributifs et distillez vers une architecture plus petite.

# pseudo: score de salience et pruning (illustratif)
import numpy as np
def prune(weights, keep=0.7):
    mag = np.abs(weights).ravel()
    thr = np.quantile(mag, 1 - keep)
    mask = np.abs(weights) >= thr
    return weights * mask

étape 4: packager le runtime d’inférence

Figez les versions de vos dépendances et choisissez un runtime stable compatible CPU/GPU/NPU de l’appareil.

# artefacts versionnés
models/
  model_int8.onnx
runtime/
  onnxruntime==1.16.0
app/
  main.py
  config.yaml

étape 5: traiter au plus près et résumer

Filtrez, lissez, agrégerez: n’envoyez que le strict nécessaire (scores, échantillons, anomalies) et conservez localement les raw si exigé.

# post-traitement local: seuillage et résumé
def summarize(scores, thresh=0.85):
    flags = [i for i,s in enumerate(scores) if s >= thresh]
    return {"count": len(scores), "flags": flags[:10], "p95": float(np.percentile(scores, 95))}

étape 6: mettre à jour prudemment (canary + rollback)

Déployez par lots restreints, comparez les métriques et revenez en arrière automatiquement si la qualité ou la latence se dégradent.

Noeuds_ProdNoeud_CanaryOrchestrateurNoeuds_ProdNoeud_CanaryOrchestrateuralt[métriques OK][métriques KO]push modèle v1.2 + politiquemétriques (latence↑? erreurs?)rollout progressif (10% -> 50% -> 100%)rollback vers v1.1

flux de données à la périphérie

connecté

hors-ligne

capture capteur/caméra

prétraitement local

inférence embarquée

post-traitement et résumé

cache/file locale

envoi sécurisé vers hub

dashboard et alertes

exemples complets

cas 1: contrôle qualité visuel en usine (classification simple)

# exécution locale batchée pour lisser la latence
import numpy as np
import onnxruntime as ort
from time import perf_counter

sess = ort.InferenceSession("model_int8.onnx", providers=["CPUExecutionProvider"])
input_name = sess.get_inputs()[0].name

def run_batch(images):
    t0 = perf_counter()
    preds = sess.run(None, {input_name: images})[0]  # logits
    p95 = float(np.percentile(np.max(preds, axis=1), 95))
    return {"preds": preds.argmax(1).tolist(), "p95_conf": p95, "latency_ms": int((perf_counter()-t0)*1000)}

explications: on traite par petits lots pour amortir les coûts, on remonte un résumé (p95 confiance, latence) au lieu de chaque prédiction brute.

cas 2: détection d’anomalies réseau offline-first

# fenêtre glissante locale + file de remontée
from collections import deque
import json, time

window = deque(maxlen=300)  # 5 min à 1s
queue = []

def update(value, now=None, z_thresh=4.0):
    now = now or time.time()
    window.append(value)
    mu = sum(window)/len(window)
    var = sum((x-mu)**2 for x in window)/max(1,len(window)-1)
    z = 0 if var == 0 else (value-mu)/(var**0.5)
    if abs(z) >= z_thresh:
        queue.append({"ts": now, "z": z, "mu": mu, "val": value})

def flush_if_connected(send):
    if is_connected():
        payload = json.dumps(queue[-1000:])
        send(payload)

explications: détection locale, stockage d’événements, envoi opportuniste quand le réseau est disponible.

erreurs courantes et solutions

  • modèle trop gros -> latence et chauffe -> quantifier en int8, distiller, réduire la résolution/entrée.
  • sync agressive -> coût réseau et batterie -> différer, compresser, regrouper par lots, fenêtre de silence.
  • absence de rollback -> service bloqué -> versionner, conserver N-1, tester canary, automatiser le retour arrière.
  • logs verbeux bruts -> fuite de données -> résumer, anonymiser, chiffrer au repos et en transit.
  • dépendances non figées -> écarts de perf -> pinner versions et vérifier hachages des binaires.

faq

  • Quels cas d’usage gagnent le plus à passer à l’edge ? Ceux où la latence est critique (vision, contrôle), où la connexion est intermittente, ou quand les données ne doivent pas sortir du site.

  • La quantification va-t-elle dégrader la qualité ? Un peu parfois. Mesurez avant/après: si la dérive est tolérable pour la tâche, gardez l’int8; sinon, essayez la quantification hybride.

  • Comment mettre à jour des milliers de noeuds sans risque ? Utilisez des vagues canary, comparez les métriques (qualité, latence, erreurs) et prévoyez un rollback automatique et testé.

  • Que remonter au cloud pour piloter sans exposer les bruts ? Des résumés: latence P95, taux d’erreurs, compteurs d’événements, échantillons anonymisés si nécessaire.

  • Que faire en cas de perte réseau prolongée ? Basculer en mode dégradé: caches locaux, quotas sur la file, purge la plus ancienne, et reprise incrémentale à la reconnexion.