Classification de l’agriculture avec Fastai: formation, interprétation et déploiement sur le visage étreint | par Mehmet alp démiral | Mai 2025
Nous avons identifié le chemin où se trouve l’ensemble de données, puis utilisé Path.ls () pour répertorier les dossiers de l’ensemble de données, vérifiant que chaque dossier est une catégorie et est dans le bon format.
# Import required libraries
from fastai.vision.all import *
import matplotlib.pyplot as plt
from fastai.vision.widgets import *# A.1 Download the data (Assuming already downloaded & extracted into 'data/')
path = Path('dataset/garbage_classification') # Change this to your actual folder
# A.1.1 Inspect the folder layout
path.ls()
Ici, j’ai pris la première image du dossier et je l’ai chargée, puis j’ai défini les paramètres de transformation pour différentes augmentations de données. Puis a converti l’image en tenseur et a appliqué ce pipeline de transformation.
img_path = get_image_files(path)(0)
img = PILImage.create(img_path)aug_tfms = aug_transforms(size=224,
flip_vert=True,
max_rotate=45.0,
max_zoom=1.2,
max_lighting=0.5,
max_warp=0.3,
p_affine=0.75,
p_lighting=0.75)
pipeline = Pipeline(aug_tfms, split_idx=0)
img_tensor = TensorImage(array(img).transpose(2,0,1)).unsqueeze(0).float()/255
augmented_img_tensor = pipeline(img_tensor)(0)
show_image(augmented_img_tensor, title="Augmented Image")
plt.show()
Ici, je montre un seul exemple d’image que j’ai obtenu en appliquant une augmentation des données, afin que vous puissiez voir l’effet des opérations.
Ici, je crée une bloc de données qui définit la façon dont nous lisons et traitons les images et les étiquettes. Je récupére les images des dossiers et extrait les étiquettes des noms des dossiers. J’ai divisé au hasard les données en un ratio Val Train à 75% – 25%. Tout d’abord, je redimensive toutes les images à 240 px, puis pendant la formation, j’applique les techniques d’augmentation que j’ai testées ci-dessus aux images. Enfin, je crée des dataloaders à partir de cette structure et spécifie 64 images à traiter à la fois.
# A.2. Create the DataBlock and dataloaders
garbage_block = DataBlock(
blocks=(ImageBlock, CategoryBlock), # A.2.1 Define blocks
get_items=get_image_files, # A.2.2 How to get images
get_y=parent_label, # A.2.3 Get label from folder name
splitter=RandomSplitter(valid_pct=0.25, seed=42),# Split train/valid
item_tfms=Resize(240), # A Word on Presizing (larger resize first)
batch_tfms=aug_transforms(size=224,
flip_vert=True,
max_rotate=45.0,
max_zoom=1.2,
max_lighting=0.5,
max_warp=0.3,
p_affine=0.75,
p_lighting=0.75) # A.2.4 Batch transforms
)dls = garbage_block.dataloaders(path, bs=64)
# A.3.1 Show batch
dls.show_batch(max_n=9, figsize=(8, 8))
J’utilise le show_batchMéthode pour afficher 9 exemples d’images du lot que j’ai créé, afin que je puisse vérifier à quoi ressemblent les images.
Dans cette section, je vérifie que toutes les étiquettes sont sous la forme correcte
# A.3.2 Check labels
print(dls.vocab)
print(f"Number of classes: {len(dls.vocab)}")
Ici, j’éloque un modèle avec l’architecture RESNET34 en utilisant Fastai vision_learnerfonction. Je prépare le modèle à la formation avec le accuracy métrique et entraînez-la pour 2 époques avec le fine_tune(2) fonction.
# A.4.1 Train a simple model
learn = vision_learner(dls, resnet34, metrics=accuracy)
learn.fine_tune(2)
Dans cette section, les exemples où le modèle formé fait le plus d’erreurs est analysé. En utilisant le ClassificationInterpretationClasse, les 20 images qui entraînent les plus grandes pertes dans les prédictions du modèle sont visualisées. Ceci est utile pour comprendre dans quelles classes le modèle lutte et où il fait des prédictions incorrectes.
# A.4.2 Interpret model
interp = ClassificationInterpretation.from_learner(learn)
interp.plot_top_losses(20, nrows=5)
En visualisant les pertes supérieures, j’ai examiné les cas où le modèle a fait le plus d’erreurs. Cela m’a permis d’observer les images avec les images mal classées ClassificationInterpretation. Certaines images étaient incorrectes ou mal étiquetées. Par conséquent, j’ai décidé d’utiliser DataCleanerPour nettoyer les données et recycler le modèle avec des exemples plus précis.
Avec ImageClassifierCleaner J’ai supprimé les données incorrectes, des données non pertinentes et corrigé les étiquettes d’images incorrectement étiquetées.
cleaner = ImageClassifierCleaner(learn)
cleaner
Après avoir nettoyé les données et recyclé mon modèle, j’ai analysé ses performances plus en détail avec la matrice de confusion, qui m’a permis de voir quelles classes le modèle prédit correctement et quelles classes il confondait. En particulier, en identifiant les classes fréquemment confuses, j’ai mieux compris les faiblesses du modèle.
Dans cette étape, pour former plus avancé et mieux modéliserlearn.lr_find() La fonction est utilisée pour déterminer le taux d’apprentissage optimal du modèle. Cette méthode génère un graphique en calculant les valeurs de perte correspondant à différents taux d’apprentissage. Le graphique visualise comment la perte change à mesure que le taux d’apprentissage augmente, permettant à l’utilisateur de choisir un taux d’apprentissage approprié.
# B.1 Learning Rate Finder
learn.lr_find(suggest_funcs=(minimum, steep, valley, slide))
Le choix d’un taux d’apprentissage approprié avant de commencer la formation du modèle peut affecter considérablement la précision et le temps de formation du modèle. Pour cette raison, les valeurs de perte correspondant à différents taux d’apprentissage ont été analysées en utilisant le learn.lr_find()Fonction fournie par la bibliothèque Fastai.
Le valley valeur obtenue dans l’étape de recherche de taux d’apprentissage, 7.585775847473997e-07a été choisi comme taux d’apprentissage optimal pour la formation du modèle. Cette valeur représente une région où la perte est proche du minimum et le modèle ne commence pas à tirer.
Dans cette étape, le modèle a été formé pour 6 époques avec la fonction learn.fine_tune(6, base_lr=7.585775847473997e-07). À la fin de la formation, le premier modèle a été sauvé sur le chemin 'models/resnet34_base.pkl’. De cette façon, le modèle pourrait être rechargé et utilisé plus tard.
# Choose best learning rate
# Let's pick value just before loss shoots up
learn.fine_tune(6, base_lr=7.585775847473997e-07)
learn.export('models/resnet34_base.pkl')
Dans cette étape, j’ai utilisé le resnet34 Modèle à nouveau et a essayé de former un modèle plus complexe et avancé et a essayé de le faire avec l’apprentissage du transfert. Fastai simplifie l’apprentissage du transfert en remplaçant la dernière couche du modèle pré-formé.
Nous pouvons voir la dernière couche du modèle avec le learn.model(1) commande. Nous pouvons donc voir combien de classes la dernière couche du modèle est configurée pour prédire.
# B.3 Transfer Learning
# used resnet34; the last layer is replaced by fastai
learn.model(1)
Et puis pour les valeurs optimales du taux d’apprentissage pour le gel + train → Ungeeze + Méthode de train de train utilisée lr_find() fonction à nouveau.
learn.lr_find(suggest_funcs=(minimum, steep, valley, slide))
Le graphique du graphique du taux de perte / d’apprentissage est:
Dans cette étape, je gèle d’abord les couches précédemment formées du modèle, afin que le modèle puisse s’adapter rapidement à la nouvelle tâche tout en préservant les fonctionnalités qu’il a déjà apprises. Pour sélectionner le taux d’apprentissage, j’ai examiné le graphique du taux de perte / apprentissage et identifié les points élevés et minimums pour choisir un petit taux d’apprentissage optimal pour 3 époques.
Ensuite, je déboutais le modèle pour former toutes les couches et utiliser différents taux d’apprentissage pour différentes couches, généralement avec des taux d’apprentissage plus bas dans les premières couches et des taux d’apprentissage supérieurs dans les couches ultérieures pour affiner le modèle plus efficacement.
Une fois l’entraînement terminé, j’ai également enregistré ce deuxième modèle qui a obtenu avec cette technique avec learn.export('models/resnet34_freeze_unfreeze_lr.pkl') fonction.
# Freeze + Train → Unfreeze + Train (B.3) step
learn.freeze()
learn.fit_one_cycle(3, 6.309573450380412e-07)
learn.unfreeze()
learn.fit_one_cycle(3, lr_max=slice(4.786300996784121e-05, 6.309573450380412e-07)) # B.4 Discriminative LRs
learn.export('models/resnet34_freeze_unfreeze_lr.pkl')
Dans cette étape, nous utilisons ResNet50un modèle plus puissant, et s’entraîner en mode de précision mixte avec to_fp16(). La précision mixte améliore la vitesse de calcul et utilise plus efficacement la mémoire du GPU. Le modèle est formé par fin_tuning pour 5 époques, puis le modèle est enregistré dans 'models/resnet50.pkl’PATH. ResNet50 .
# B.6 Mixed Precision & Model Capacity
# Use resnet50 and to_fp16
learn = vision_learner(dls, resnet50, metrics=accuracy).to_fp16()
learn.fine_tune(5) # increase epoch
learn.export('models/resnet50.pkl')
Dans ce projet, j’ai formé et enregistré trois modèles différents: la base ResNet34 le ResNet34développé avec des techniques avancées telles que la méthode de congé ResNet50Formé avec une précision mixte, qui est un modèle plus puissant. J’ai effectué la tâche de classification d’image en utilisant ces modèles. J’ai vécu et appris l’importance de la formation, de l’interprétation, de l’amélioration et de l’optimisation des modèles avec différentes méthodes.
Vous pouvez accéder aux codes appartenant au projet et au processus de formation ici.
Vous pouvez accéder à l’application Gradio sur ici.
