Introduction à Green, le modèle de classification des Plantes Médicinales avec MobileNetV2 et Focal Loss
Introduction à Green, le modèle de classification des Plantes Médicinales avec MobileNetV2 et Focal Loss
Afin de sauvegarder la mémoire de l'utilisation des plantes dites médicinales de l’Afrique en général et de la Côte d’ivoire en particulier, nous avons pensé à développer une bibliothèque numérique accessible à tous, sans distinction de classe sociale ou d'origine et ce avec les outils dont nous disposons actuellement.
La base fondamentale de cette bibliothèque est un modèle d’apprentissage profond qui permet la reconnaissance des plantes qui servent à l’usage médicinal traditionnel.
Ainsi, nous vous présentons aujourd’hui Green, notre modèle de deep learning conçu pour identifier quatre plantes médicinales traditionnelles. Ce modèle alimente l'application mobile DrGreen et démontre comment combiner le transfert par apprentissage, les fonctions de pertes personnalisées et techniques d'augmentation de données pour obtenir des performances robustes avec un dataset limité.
Notre principal défi est de classifier 4 espèces de plantes médicinales que sont l’Artemisia (Artemisia annua) qui a des propriétés antipaludiques, le Carica (Carica papaya) qui est utilisé pour la santé digestive, le Goyavier (Psidium guajava) contre la diarrhée et enfin le Kinkeliba (Combretum micranthum) pour lutter contre la fièvre, la fatigue et le paludisme dont les contraintes sont les suivantes:
- Dataset limité : 1,164 images seulement
- Déséquilibre des classes : 20.7% à 30.6% par classe
- Déploiement mobile : modèle léger requis
- Contraintes temps réel : inférence rapide nécessaire
Architecture du Modèle
Choix de MobileNetV2
MobileNetV2 a été sélectionné pour plusieurs raisons techniques :
base_model = tf.keras.applications.MobileNetV2(
include_top=False,
weights='imagenet',
input_tensor=inputs,
pooling='avg'
)
base_model.trainable = False # Transfer learning avec base gelée
Les avantages :
- Inverted Residuals : réduction de la complexité computationnelle
- Linear Bottlenecks : préservation des caractéristiques importantes
- Lightweight : 2.3M paramètres totaux, 82K entraînables
- Pré-entraîné ImageNet : knowledge transfer efficace
Architecture Complète
Input (224×224×3)
↓
MobileNetV2 Base (frozen)
↓
Global Average Pooling
↓
Dropout(0.6) ← Forte régularisation
↓
Dense(64, ReLU) + L2(0.02) ← Feature extraction
↓
Batch Normalization ← Stabilisation
↓
Dropout(0.3) ← Régularisation supplémentaire
↓
Dense(4, Softmax) + L2(0.02) ← Classification finale
Paramètres clés :
- Total : 2,340,484 paramètres
- Entraînables : 82,372 (3.5%)
- Non-entraînables : 2,258,112
Focal Loss : La Clé de la Performance
Pourquoi Focal Loss ?
La Categorical Cross-Entropy standard traite tous les exemples de manière égale. Avec un dataset limité et déséquilibré, cela pose un problème :
Cross-Entropy standard
loss = -Σ y_true * log(y_pred)
Problèmes :
- Les exemples faciles dominent le gradient
- Les classes minoritaires sont sous-représentées
- Pas de focus sur les hard examples
Implémentation de Focal Loss
Vous trouverez le code complet sur Kaggle
L’impact de Gamma
Un exemple concret :
# Easy example : p_t = 0.9
focal_weight = (1 - 0.9)^2 = 0.01 # Poids très réduit
# Hard example : p_t = 0.3
focal_weight = (1 - 0.3)^2 = 0.49 # Poids important
# Ratio : 0.49 / 0.01 = 49x plus d'attention sur les hard examples !
Pipeline de Données et Augmentation
Stratégie d'Augmentation Agressive
Avec seulement 931 images d'entraînement, l'augmentation est cruciale(Code complet sur Kaggle) :
Nous justifions nos choix par les paramètres suivants :
Rotations importantes (±108°) : les plantes peuvent être photographiées sous n'importe quel angle
Flips vertical + horizontal : pas d'orientation canonique pour les feuilles
Variations photométriques : conditions d'éclairage variables en milieu naturel
Pipeline Optimisé(Code complet sur Kaggle)
Nos optimisations clés sont les suivantes:
num_parallel_calls=AUTOTUNE : TensorFlow optimise automatiquement le parallélisme
prefetch(AUTOTUNE) : prépare le batch suivant pendant l'entraînement du batch actuel
shuffle(1000) : buffer de 1000 images pour randomisation efficace
Stratified Split : Éviter le Class Collapse
Le Problème avec Random Split
# ❌ BAD : Split aléatoire
train_ds, val_ds = tf.keras.utils.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="both",
seed=42
)
Le problème avec un petit dataset est que le split aléatoire peut créer des déséquilibres :
- Classe A : 90% en train, 10% en validation
- Classe B : 70% en train, 30% en validation
- Risque de validation set non représentatif
Alors notre solution est d’utiliser Stratified Split:
from sklearn.model_selection import train_test_split
train_paths, val_paths, train_labels, val_labels = train_test_split(
all_image_paths,
all_labels,
test_size=0.2,
random_state=42,
stratify=all_labels # ← La clé !
)
Résultat : distribution identique dans train et validation
Impact : validation accuracy plus fiable et pas de class collapse !
Optimisation et Régularisation
Learning Rate Schedule : Cosine Decay
steps_per_epoch = len(train_labels) // batch_size
total_steps = steps_per_epoch * epochs
lr_schedule = tf.keras.optimizers.schedules.CosineDecay(
initial_learning_rate=0.0005, # LR initial
decay_steps=total_steps,
alpha=0.01 # LR final = 0.01 * initial = 0.000005
)
Les avantages du Cosine Decay sont la décroissance douce comparé à un step decay brutal, il évite les oscillations en fin d'entraînement et enfin un LR(Learning Rate) final non-nul pour fine-tuning.
Stack de Régularisation
1. Dropout (60% + 30%)
x = tf.keras.layers.Dropout(0.6)(x) # Après GAP
# ...
x = tf.keras.layers.Dropout(0.3)(x) # Après Dense
2. L2 Regularization
kernel_regularizer=tf.keras.regularizers.l2(0.02)
3. Batch Normalization
x = tf.keras.layers.BatchNormalization()(x)
4. Label Smoothing (15%)
# Dans Focal Loss
y_true = y_true * 0.85 + 0.15/4 # Soft labels
5. Class Weights
# Pondération dynamique inversement proportionnelle à la fréquence
class_weights = {
0: 1.076, # Artemisia (sous-représenté)
1: 0.769, # Carica (surreprésenté)
2: 1.276, # Goyavier (le plus sous-représenté)
3: 0.999 # Kinkeliba (équilibré)
}
Early Stopping Intelligent
callbacks = [
tf.keras.callbacks.EarlyStopping(
monitor='val_accuracy',
patience=15, # Attend 15 epochs sans amélioration
restore_best_weights=True, # Restaure les meilleurs poids
mode='max'
),
tf.keras.callbacks.ModelCheckpoint(
filepath='models/best_model_v7.keras',
monitor='val_accuracy',
save_best_only=True,
mode='max'
)
]
Métriques et Évaluation
Métriques Multi-dimensionnelles
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=lr_schedule),
loss=FocalLoss(gamma=2.0, alpha=0.25, label_smoothing=0.15),
metrics=[
tf.keras.metrics.CategoricalAccuracy(name='accuracy'),
tf.keras.metrics.TopKCategoricalAccuracy(k=2, name='top2_accuracy')
]
)
Top-2 Accuracy : crucial pour une app mobile
Accuracy : 69.10%
Top-2 Accuracy : 88.41% ← L'app peut proposer 2 suggestions
Analyse de la Matrice de Confusion
cm = confusion_matrix(y_true, y_pred)
# Analyse per-class
for i, class_name in enumerate(class_names):
class_mask = y_true == i
class_acc = (y_pred[class_mask] == i).mean()
print(f"{class_name}: {class_acc*100:.2f}%")
les résultats obtenus sont Artemisia: 67.27%, Carica: 73.24%, Goyavier: 60.42% et enfin Kinkeliba: 71.19%
Leçons Apprises
1. Dataset Quality > Quantity
Avec seulement 1,164 images :
- Stratified split crucial
- Augmentation agressive nécessaire
- Transfer learning indispensable
2. Loss Function Matters
Focal Loss vs Cross-Entropy :
- +12% accuracy sur classes minoritaires
- Convergence plus stable
- Pas de class collapse
3. Régularisation Multi-niveaux
Stack de régularisation :
Dropout (0.6 + 0.3)
+ L2 (0.02)
+ Batch Normalization
+ Label Smoothing (0.15)
+ Early Stopping (patience=15)
= Modèle robuste sans overfitting
4. Validation Set Design
Le split stratifié a éliminé :
- Validation accuracy instable
- Class collapse sur certaines runs
- Métriques non représentatives
5. Mobile-First Architecture
MobileNetV2 offre le meilleur trade-off :
- Légèreté : 2.3 MB en FP16
- Performance : 69% accuracy, 88% top-2
- Vitesse : 40ms sur smartphone
Le modèle Green démontre qu'avec une architecture bien pensée et des techniques modernes (Focal Loss, stratified split, régularisation multi-niveaux), il est possible d'obtenir des performances robustes même avec un dataset limité.
Le projet présente un modèle performant avec une précision de 69,10 % et 88,41 % en top-2. Il est optimisé pour le déploiement mobile (taille de 2,3 Mo, inférence en 40 ms). Des techniques comme le split stratifié ont été utilisées pour éviter l'effondrement des classes, et la Focal Loss a été employée pour gérer le déséquilibre des données.
Le code complet est disponible sur GitHub
Références
Sandler et al., "MobileNetV2: Inverted Residuals and Linear Bottlenecks", CVPR 2018
Lin et al., "Focal Loss for Dense Object Detection", ICCV 2017
Shorten & Khoshgoftaar, "A survey on Image Data Augmentation for Deep Learning", Journal of Big Data 2019
Yosinski et al., "How transferable are features in deep neural networks?", NeurIPS 2014
Auteur: Équipe DrGreen
Licence : Apache 2.0
Date : Décembre 2025
Pour toute question technique, ouvrez un issue sur le dépôt GitHub
Trop long ? Obtenez un résumé rapide de cet article généré par l'IA.
📧 Restez informé
Recevez une notification par email à chaque nouvel article ou modification
Commentaires (0)
Aucun commentaire pour le moment. Soyez le premier à commenter !
Laisser un commentaire
Vous commentez en tant que :