La compression réduit la taille et la latence des LSTM pour les dispositifs en magasin tout en gardant une précision exploitable. J’explique les techniques clés (downsizing, pruning magnitude, INT8) et comment les mettre en œuvre, mesurer l’impact (taille, MAPE, latence) et choisir la meilleure option.
Pourquoi compresser un LSTM pour l’edge ?
Compresser un LSTM pour l’edge réduit la mémoire utilisée, la consommation énergétique et la latence, tout en diminuant les coûts opérationnels lorsqu’on exécute des prédictions massives en magasin.
- Mémoire limitée : Les dispositifs edge en retail (terminaux, MCU, gateways) offrent souvent quelques centaines de kilo-octets à quelques méga-octets de RAM.
- Puissance CPU/MCU limitée : Les microcontrôleurs (MCU) et CPU embarqués ont des fréquences et des unités flottantes faibles, ce qui allonge le temps d’inférence pour un modèle non optimisé.
- Latence réseau : Les connexions en magasin peuvent être intermittentes ou à bande passante réduite, ce qui impose d’exécuter les inférences localement.
- Coûts de prédiction à grande échelle : Une réduction de la taille entraîne moins d’accès mémoire et des inférences plus rapides, ce qui se traduit par une économie d’énergie et de coûts à l’échelle (exemple simple : 1 000 prédictions/jour sur 100 magasins = 100 000 inférences/jour).
- Chiffres concrets : Un paramètre en float32 occupe ≈4 bytes. La quantification en INT8 (entier 8 bits) permet jusqu’à 4x de réduction de taille par paramètre (source TensorFlow Lite).
- Repère pratique : Un LSTM de 64 unités de référence cité occupe 66.25 KB et affiche un MAPE (Mean Absolute Percentage Error, erreur moyenne absolue en pourcentage) de 15.92% (±0.10). Ces repères servent à comparer l’impact des techniques de compression sur la taille et la précision.
- Impact sur l’expérience client : La latence affecte les interactions en temps réel (caisses, affichage dynamique).
- Résilience en boutique : L’exécution locale évite les interruptions liées au réseau et garantit la continuité des prédictions.
- Coût cumulé : Même une micro-optimisation (réduction de 50 ms par inférence) devient significative à grande échelle et réduit la consommation électrique totale.
- Études et guides pratiques : Deep Compression (Han et al., 2016) décrit pruning, quantization et encoding.
- Ressources officielles : Le guide TensorFlow Model Optimization couvre le pruning.
- Ressources officielles : Le guide TensorFlow Lite décrit la quantification post-training (INT8).
- Je m’appuie aussi sur des jeux de données industriels, par exemple le dataset Kaggle « Store Item Demand Forecasting » pour des validations terrain.
| Contrainte | Impact | Indicateur mesurable |
| Mémoire | Taille du modèle | Taille en KB |
| Latence | Temps d’inférence | ms / inference |
| Précision | Qualité des prévisions | MAPE (%) |
- Sources :
- https://arxiv.org/abs/1510.00149
- https://www.tensorflow.org/model_optimization/guide/pruning
- https://www.tensorflow.org/lite/performance/post_training_quantization
- https://www.kaggle.com/c/demand-forecasting-kernels-only/data
Comment reproduire le benchmark
Voici un protocole réplicable pour reproduire le benchmark de compression d’un LSTM sur le retail edge, avec dataset, découpage temporel, métrique et nombre de runs.
Description du dataset
- Le dataset utilisé est le Kaggle Store Item Demand Forecasting Dataset (nom exact).
- Échantillon utilisé : 5 magasins × 10 articles = 50 séries temporelles, soit environ 72 000 échantillons d’entraînement.
- Format des séries : enregistrements journaliers (date, ventes).
- Fenêtrage : séquences glissantes de longueur 14 jours pour prédiction day+1 (single-step).
Prétraitement et split
- Imputations : remplacer les valeurs manquantes par 0 si absence de vente, ou interpoler si données sporadiques.
- Normalisation : utiliser StandardScaler (moyenne/écart-type) ou MinMaxScaler [0,1] selon la distribution.
- Fenêtres : créer X de formes (N,14,1) et y de forme (N,1).
- Shuffle : mélanger uniquement au niveau des batches pendant l’entraînement; garder split chronologique pour éviter fuite temporelle.
- Split : train/val/test chronologique (p.ex. 70/15/15) pour simuler déploiement réel.
Protocole d’entraînement
- Hyperparamètres clés : epochs=50, batch_size=64, optimizer=Adam, loss=MSE. Ajuster selon early stopping.
- Répétitions : exécuter 3 runs indépendants et prendre la moyenne ± écart-type.
- Métrique principale : MAPE (Mean Absolute Percentage Error). Formule : MAPE = (100/n) * Σ |(y_true – y_pred) / y_true|. Attention : instable si y_true proche de 0, et non symétrique.
Exemple de code minimal (Keras)
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras.layers import LSTM, Dense
# Seed pour reproductibilité
np.random.seed(42)
tf.random.set_seed(42)
def create_windows(series, seq_len=14):
X, y = [], []
for i in range(len(series)-seq_len):
X.append(series[i:i+seq_len])
y.append(series[i+seq_len])
return np.array(X)[...,None], np.array(y)
def build_lstm(units=64, seq_len=14):
model = Sequential([LSTM(units, input_shape=(seq_len,1)), Dense(1)])
model.compile(optimizer='adam', loss='mse', metrics=['mape'])
return model
# Exemple d'usage avec une seule série
series = pd.read_csv('sample_series.csv')['sales'].fillna(0).values
X, y = create_windows(series)
model = build_lstm(64)
history = model.fit(X, y, epochs=20, batch_size=64, validation_split=0.15, verbose=0)
mape = model.evaluate(X, y, verbose=0)[1] # retourne [loss, mape]
print('MAPE:', mape)
Reproductibilité
- Fixer seeds pour numpy, random et tf; consigner versions (Python, TensorFlow). Exemple : TensorFlow 2.x, Python 3.8+.
- Logger résultats par run dans un fichier CSV/JSON pour calculer moyenne et écart-type des 3 runs.
Résultats de référence
- Baseline LSTM 64 unités : taille 66.25 KB, MAPE 15.92% (±0.10) pour comparaison.
| Étape | Action | Outil |
| 1 | Récupérer échantillon 50 séries | Kaggle CSV / pandas |
| 2 | Prétraiter et normaliser | pandas / sklearn.preprocessing |
| 3 | Créer fenêtres 14 jours | numpy / custom |
| 4 | Entraîner 3 runs | TensorFlow/Keras |
| 5 | Logger et calculer moyenne MAPE | pandas -> CSV/JSON |
Quelles réductions d’architecture tester
Voici comment tester rapidement la réduction du nombre d’unités cachées d’un LSTM pour une application retail sur edge.
Principe
- Réduire le nombre d’unités diminue directement le nombre de paramètres et donc la taille du modèle stocké et la mémoire vive utilisée à l’inférence.
- Formule simple pour le nombre de paramètres d’une couche LSTM: 4 * ((input_dim + hidden_dim) * hidden_dim + hidden_dim). Cette formule tient compte des quatre portes d’un LSTM (entrée, oubli, sortie et état candidat) et des biais associés.
- Réduire hidden_dim provoque une réduction quadratique partielle des paramètres (le terme hidden_dim * hidden_dim) et donc une baisse sensible de la taille binaire.
Expérimentations recommandées
- Tester au minimum ces architectures: 64 (baseline), 32, 16 unités. Comparer ensuite 1×32 vs 2×16 (LSTM empilé) comme alternative qui change la profondeur.
- Entraîner from-scratch chaque configuration en gardant le même nombre d’epochs, la même seed et les mêmes splits train/val pour assurer la comparabilité.
Exemple de code Keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dropout, Dense
import tensorflow as tf
def build_lstm(units, features=10):
model = Sequential([
LSTM(units, input_shape=(14, features)),
Dropout(0.2),
Dense(1)
])
model.compile(optimizer='adam', loss='mse')
return model
# Afficher nombre de paramètres et taille estimée
m = build_lstm(32, features=10)
params = m.count_params()
size_kb = params * 4 / 1024 # float32 = 4 bytes
print("Params:", params, "Estimated size (KB):", round(size_kb,2))
Tableau de comparaison (template)
| Units | Param_Count | Estimated_Size_KB | Validation_MAPE | Inference_Latency_ms |
| 64 | … | … | … | … |
| 32 | … | … | … | … |
| 16 | … | … | … | … |
| 2×16 | … | … | … | … |
Mesurer la latence en mode edge avec batch_size=1, faire la moyenne sur 1000 inférences (par exemple using timeit) et reporter la médiane et le 95e centile. La latence est cruciale pour l’expérience utilisateur et pour dimensionner la CPU/RAM du device.
Interprétation pratique
- Si passer de 64 à 32 unités réduit la taille d’environ 2x et n’ajoute que 1–2% de MAPE, c’est souvent un bon compromis pour l’edge.
- Après réduction d’unités, envisager la quantization int8 (≈4x réduction de taille) et le pruning (sparsity contrôlée) pour gagner encore en mémoire et latence.
- Pour éviter l’overfitting quand on réduit la capacité: utiliser régularisation (Dropout, L2), early stopping sur validation et data augmentation si possible.
Comment appliquer pruning magnitude et INT8 quantization
Pour compresser un LSTM destiné au retail edge, on supprime d’abord les poids proches de zéro via magnitude pruning, puis on quantifie en INT8 (post-training ou via quantization-aware training) pour réduire la taille et accélérer l’inférence.
Pruning by magnitude
La méthode supprime les poids de faible amplitude (proche de zéro), ce qui crée de la sparsité. Références importantes : le guide TensorFlow Model Optimization et l’article « Deep Compression » (Han et al., 2016) qui montre 2x–5x ou plus selon combinaisons pruning+quantization.
import tensorflow as tf
import tensorflow_model_optimization as tfmot
prune_low_magnitude = tfmot.sparsity.keras.prune_low_magnitude
pruning_params = {
'pruning_schedule': tfmot.sparsity.keras.PolynomialDecay(
initial_sparsity=0.0,
final_sparsity=0.5,
begin_step=1000,
end_step=10000)
}
def build_model():
inputs = tf.keras.Input(shape=(timesteps, features))
x = prune_low_magnitude(tf.keras.layers.LSTM(64), **pruning_params)(inputs)
x = prune_low_magnitude(tf.keras.layers.Dense(32, activation='relu'), **pruning_params)(x)
outputs = prune_low_magnitude(tf.keras.layers.Dense(1), **pruning_params)(x)
model = tf.keras.Model(inputs, outputs)
return model
model = build_model()
model.compile(optimizer='adam', loss='mse')
callbacks = [tfmot.sparsity.keras.UpdatePruningStep()]
model.fit(train_ds, epochs=5, callbacks=callbacks)
model = tfmot.sparsity.keras.strip_pruning(model)
model.save('pruned_saved_model')
Mesurer la sparsity via tfmot.sparsity.keras.get_prunable_weights ou en inspectant les poids. Mesurer la taille des poids compressés après gzip ou conversion TFLite. S’attendre à 2x–5x réduction combinée, impact MAPE variable : souvent <+1–3% MAPE avec pruning modéré, mais valider sur validation représentative.
Post-training INT8 quantization
Différences principales : dynamic range quantization réduit uniquement les poids, full integer post-training quantization convertit poids et activations en INT8, QAT (quantization-aware training) simule la quantification pendant l’entraînement pour réduire la perte d’exactitude (voir Jacob et al., 2018).
converter = tf.lite.TFLiteConverter.from_saved_model('pruned_saved_model')
converter.optimizations = [tf.lite.Optimize.DEFAULT]
def representative_dataset():
for _ in range(200): # 100-500 échantillons représentatifs recommandés
yield [next(representative_gen)] # array shape (1,timesteps,features)
converter.representative_dataset = representative_dataset
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8 # ou tf.uint8 selon hardware
converter.inference_output_type = tf.int8
tflite_model = converter.convert()
open('model_int8.tflite','wb').write(tflite_model)
Choisir int8 vs uint8 selon le backend matériel : certains accélérateurs exigent uint8 (unsigned), d’autres supportent int8 (signed).
Quantization-aware training (QAT)
import tensorflow_model_optimization as tfmot
q_aware_model = tfmot.quantization.keras.quantize_model(model)
q_aware_model.compile(optimizer='adam', loss='mse')
q_aware_model.fit(train_ds, epochs=3, validation_data=val_ds)
# Exporter et convertir en TFLite INT8 comme ci-dessus
Mesures post-compression
Mesurer taille .tflite en Ko, latence d’inférence (ms) sur le hardware cible (ex: Raspberry Pi, MCU, NPU), et delta MAPE. Tester en A/B ou shadow mode avant déploiement pour détecter régression réelle en magasin.
Pratiques pour le retail edge
- Fournir une dataset représentative des magasins (saisonnalité, promos) pour la quantification et les tests.
- Conserver logs et métriques pour monitorer le drift et prévoir rollback si MAPE augmente.
- Prioriser robustesse sur gains extrêmes de compression si risque business important.
Tableau récapitulatif
| Baseline | size_KB | expected_size_factor | validation_MAPE_delta | inference_latency_change | risk_level |
| Baseline | e.g. 10240 | 1.0 | 0% | 0% | Low |
| Downsized | e.g. 6144 | ~0.6 | +1–2% | -10% | Medium |
| Pruned | e.g. 3072 | ~0.3 | +1–3% | -20% | Medium |
| INT8 post-training | e.g. 1280 | ~0.125 | +1–4% | -30%+ | Medium |
| QAT INT8 | e.g. 1400 | ~0.14 | +0–2% | -30%+ | Low–Medium |
- https://www.tensorflow.org/model_optimization/guide/pruning
- https://www.tensorflow.org/lite/performance/post_training_quantization
Comment choisir et déployer en magasin
Réponse courte : Le choix dépend des contraintes hardware, de la tolérance à l’erreur (MAPE acceptable) et de la fréquence des prédictions (batch vs online).
1) Critères de choix
- Mémoire disponible : mesurer RAM et stockage libre en Mo/Go.
- CPU et accélérateurs : distinguer ARM Cortex‑A (applications edge) vs Cortex‑M (microcontrôleurs) ; présence de NPU/TPU ou de support NNAPI.
- Fréquence de prédiction : batch (nuit) permet plus de compression ; online exige faible latence.
- Tolérance MAPE : MAPE = Mean Absolute Percentage Error (Erreur Absolue Moyenne en %). Définir seuil business (ex. 5% pour pricing, 10–20% pour stock basique).
- Consommation énergétique et coût par inference : important pour POS alimentés par batterie.
2) Workflow de sélection
- Mesurer baseline sur hardware cible : taille modèle, latence p50/p95, MAPE sur dataset en magasin.
- Tester versions downsized (réduction couches/unité) pour évaluer perte d’exactitude.
- Appliquer pruning (élimination de poids : 2×–10× réduction typique selon sparsité) et réévaluer.
- Appliquer quantization INT8 (taille ≈4× plus petite, latence souvent 2×–3× meilleure) (voir TensorFlow Lite quantization).
- Choisir la solution la plus compacte respectant le seuil MAPE défini.
3) Déploiement technique
- Packaging : convertir en .tflite (TensorFlow Lite) pour inference embarquée.
- Intégration : utiliser TF Lite Interpreter en Python ou C++ ; sur Android privilégier NNAPI ; sur ARM Cortex exploiter ARM Compute Library.
- Vérifications : sanity checks (inference sur échantillons connus), shadow logging (exécuter modèle cloud + edge en parallèle pour comparer sans impacter prod).
4) Monitoring et maintenance
- Métriques à monitorer : MAPE en production, taux d’échec d’inference, latence 95e percentile, dérive des distributions d’entrée.
- Réentraînement : planifier réentraînement périodique (ex. mensuel) ou déclenché par dérive > seuil.
- Rollback : versioning modèle, feature flag pour basculer rapidement vers last‑good model.
5) Checklist de déploiement
| Hardware check | CPU, RAM, NPU présents et tests passés |
| Modèle & version | ID version, hash, métadonnées |
| Taille fichier | Poids .tflite et empreinte mémoire |
| Test latency | p50/p95 conformes |
| Test accuracy on-store dataset | MAPE sous seuil |
| Monitoring pipeline | Logs, alertes, dashboards |
| Plan rollback | Procédure et accès aux versions précédentes |
6) Exemples de cas d’usage retail
- Prédiction journalière de demande pour réassort automatique : contrainte batch nightly, tolérance MAPE 10–15% ; technique recommandée = downsizing + quantization.
- Recommandations en point de vente par client (online) : contrainte latence <100 ms, faible MAPE souhaité ; technique recommandée = INT8 + NPU/NNAPI.
- Détection d’anomalies de trafic caisse : contrainte latence modérée, sensibilité élevée aux faux positifs ; technique recommandée = pruned model + shadow logging pour calibration.
| Technique | Taille | Latence | Implémentation | Risque |
| Baseline float32 | Grande | Élevée | TF Lite float | Faible perte d’accuracy |
| Pruning | Moyenne→faible | Variable | TensorFlow Model Optimization | Risque de dégradation si over‑pruned |
| INT8 quantization | ≈4× plus petite | Meilleure (×2–3) | TF Lite, NNAPI, ARM | Faible si calibré correctement |
| Knowledge distillation | Faible | Très faible | Former petit student model | Complexe à entraîner |
# Exemple de chargement TFLite en Python
import tflite_runtime.interpreter as tflite
interpreter = tflite.Interpreter(model_path="model.tflite")
interpreter.allocate_tensors()
Prêt à réduire votre LSTM pour l’edge retail et gagner en performance ?
La compression combine plusieurs leviers complémentaires : réduction d’architecture pour gains simples, pruning pour supprimer poids redondants, et INT8 pour gains de taille et vitesse (jusqu’à ~4x). Le bon choix dépend du hardware, du seuil de MAPE acceptable et de la fréquence des prédictions. En suivant un protocole reproductible (dataset, métriques, 3 runs) et en testant chaque technique sur le hardware cible, on obtient un modèle déployable en magasin, plus rapide et moins coûteux. Bénéfice client : prédictions locales plus fiables, latence réduite et coûts opérationnels moindres.
FAQ
-
Qu’est-ce que la quantification INT8 et pourquoi l’utiliser ?
La quantification INT8 convertit les poids et/ou activations en entiers 8 bits, réduisant la taille des modèles jusqu’à 4x et accélérant l’inférence sur hardware compatible. Elle nécessite un jeu de calibration représentatif et peut être post-training ou via Quantization Aware Training (QAT). -
Le pruning dégrade-t-il toujours la précision ?
Pas nécessairement. Un pruning par magnitude bien calibré (ex: target sparsity 30–50%) peut réduire fortement la taille sans perte sensible de MAPE. Mais il faut mesurer et, si nécessaire, combiner avec fine-tuning ou QAT. -
Comment mesurer l’impact réel en magasin ?
Mesurez taille du binaire (.tflite), latence moyenne et p95 sur le hardware cible, et MAPE sur un jeu de test issu du magasin. Utilisez shadow runs et A/B pour valider en production avant bascule. -
Quelle technique essayer en premier pour un prototype ?
Commencez par réduire l’architecture (64→32→16) : simple à implémenter et souvent suffisant. Si besoin, ajoutez pruning puis INT8 pour gains supplémentaires. -
Quelles ressources suivre pour implémenter ces techniques ?
Consultez le guide TensorFlow Model Optimization (pruning & QAT), et TensorFlow Lite quantization docs pour les conversions INT8. La littérature classique inclut l’article Deep Compression de Han et al. pour le contexte sur pruning et quantization.
A propos de l’auteur
Franck Scandolera — expert & formateur en Tracking avancé server-side, Analytics Engineering, Automatisation No/Low Code (n8n) et intégration de l’IA en entreprise. Responsable de l’agence webAnalyste et de l’organisme de formation Formations Analytics. J’accompagne des clients comme Logis Hôtel, Yelloh Village, BazarChic, Fédération Française de Football, Texdecor sur le déploiement d’IA au bord (edge) et l’optimisation des modèles. Dispo pour aider les entreprises => contactez moi.
⭐ Analytics engineer, Data Analyst et Automatisation IA indépendant ⭐
- Ref clients : Logis Hôtel, Yelloh Village, BazarChic, Fédération Football Français, Texdecor…
Mon terrain de jeu :
- Data Analyst & Analytics engineering : tracking avancé (GTM server, e-commerce, CAPI, RGPD), entrepôt de données (BigQuery, Snowflake, PostgreSQL, ClickHouse), modèles (Airflow, dbt, Dataform), dashboards décisionnels (Looker, Power BI, Metabase, SQL, Python).
- Automatisation IA des taches Data, Marketing, RH, compta etc : conception de workflows intelligents robustes (n8n, App Script, scraping) connectés aux API de vos outils et LLM (OpenAI, Mistral, Claude…).
- Engineering IA pour créer des applications et agent IA sur mesure : intégration de LLM (OpenAI, Mistral…), RAG, assistants métier, génération de documents complexes, APIs, backends Node.js/Python.






