rkonan commited on
Commit
2e748b3
·
1 Parent(s): 6a4f05e
converted_txt/DST_Rapport_final_Reco_plant.txt ADDED
@@ -0,0 +1,2565 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Projet Datascientest
2
+ Reconnaissance de plantes
3
+
4
+ Rapport final
5
+
6
+ Ela CIMEN
7
+ Yao N Guessan Roland KONAN
8
+ Yacine MADI SAID
9
+ Nicolas RINCÉ
10
+
11
+ 09/06/2025
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+ Table des matières
29
+
30
+ Partie 1 : Cadrage du projet ...................................................................................................5
31
+
32
+ Contexte ........................................................................................................................................ 5
33
+
34
+ Objectifs ........................................................................................................................................ 5
35
+
36
+ Description des macro-objectifs .................................................................................................... 5
37
+ Localiser et classifier l’espèce d’une plante dans une image ......................................................................5
38
+ Localiser et classifier la maladie éventuelle touchant la plante dans cette même image ............................5
39
+ Bâtir une application renvoyant les informations de ces classifications à l’utilisateur sur la base d’une
40
+ photographie prise sur son smartphone. ..................................................................................................6
41
+
42
+ Jalons du projet ............................................................................................................................. 6
43
+
44
+ Schéma de fonctionnement de l’application ................................................................................. 6
45
+
46
+ Niveaux d’expertise ...................................................................................................................... 7
47
+ Niveaux d’expertise interne ......................................................................................................................7
48
+ Recours à expertise externe .....................................................................................................................7
49
+
50
+ Partie 2 : Exploration et DataViz ............................................................................................7
51
+
52
+ Jeux de données ............................................................................................................................ 7
53
+ Soumis et exploités ..................................................................................................................................7
54
+ Soumis et non exploités ...........................................................................................................................8
55
+ Constats ...................................................................................................................................................8
56
+
57
+ Pertinence ..............................................................................................................................9
58
+
59
+ Variables ....................................................................................................................................... 9
60
+
61
+ Description .................................................................................................................................. 10
62
+
63
+ Limitation des données ............................................................................................................... 10
64
+
65
+ Partie 3 : Pré-Processing et feature engineering..................................................................11
66
+
67
+ Création du dataframe des caractéristiques................................................................................ 11
68
+
69
+ Nettoyage des données et étapes de traitement ........................................................................ 11
70
+
71
+ Transformations des données ..................................................................................................... 12
72
+ Traitement des images ........................................................................................................................... 12
73
+
74
+ Visualisations et Statistiques....................................................................................................... 14
75
+ Corrélation entre variables du dataframe .............................................................................................. 14
76
+ Relations avec les variables cibles ......................................................................................................... 14
77
+
78
+ Distribution des données ............................................................................................................ 14
79
+ Distribution des espèces dans le dataframe “high quality” ...................................................................... 14
80
+ Distribution des espèces dans le dataframe “low quality” ....................................................................... 15
81
+ Mesure d’amélioration de la qualité des images ..................................................................................... 15
82
+
83
+ Analyses statistiques ................................................................................................................... 17
84
+
85
+ Conclusions pré-modélisation ..................................................................................................... 18
86
+
87
+ Partie 4 : Modélisation ........................................................................................................18
88
+
89
+ Classification du problème .......................................................................................................... 18
90
+
91
+ Type de problème de machine learning ...................................................................................... 18
92
+
93
+ Tâches de machine learning ........................................................................................................ 18
94
+
95
+ Métriques de performance utilisées pour comparer les modèles ............................................... 18
96
+ Métrique principale ................................................................................................................................ 18
97
+ Métriques secondaires ........................................................................................................................... 18
98
+
99
+ Choix du modèle et optimisation ................................................................................................ 19
100
+ Algorithmes testés ................................................................................................................................. 19
101
+ Résultats par modèle ............................................................................................................................. 19
102
+ KERAS ........................................................................................................................................... 19
103
+ 1-
104
+ FastAI............................................................................................................................................ 23
105
+ 2-
106
+ Torch ............................................................................................................................................ 24
107
+ 3-
108
+ AlexNet ......................................................................................................................................... 26
109
+ 4-
110
+
111
+ Optimisation ............................................................................................................................... 29
112
+ Phase 1 .................................................................................................................................................. 29
113
+ Phase 2 .................................................................................................................................................. 35
114
+
115
+ Stratégies de traitement des images Cassava ............................................................................. 41
116
+ 1. Augmentation massive des classes minoritaires .................................................................................. 41
117
+ 2. Filtrage basé sur un score multi-critères ............................................................................................. 42
118
+ 3. Relabellisation automatique basée sur le score ................................................................................... 42
119
+ 4. Fine-tuning des modèles sur les nouveaux datasets ............................................................................ 43
120
+ 5. Résultats obtenus ............................................................................................................................... 43
121
+ 6. Analyse des résultats .......................................................................................................................... 44
122
+ 7. Conclusion de l’étude d’amélioration sur Cassava ............................................................................... 45
123
+ Étude de l’ensemblage des modèles ....................................................................................................... 46
124
+ Conclusion sur le choix des ensembles de modèles ................................................................................. 49
125
+
126
+ Partie 5 : Conclusions tirées .................................................................................................49
127
+
128
+ Difficultés rencontrées pendant le projet.................................................................................... 49
129
+ Principal verrou scientifique rencontré ................................................................................................... 49
130
+
131
+ Difficultés détaillées par catégorie .............................................................................................. 49
132
+ Prévisionnel ........................................................................................................................................... 49
133
+ Jeux de données..................................................................................................................................... 50
134
+ Compétences techniques/théoriques ..................................................................................................... 50
135
+ Pertinence ............................................................................................................................................. 50
136
+ IT ........................................................................................................................................................... 50
137
+ Autres .................................................................................................................................................... 51
138
+
139
+ Bilan .....................................................................................................................................51
140
+
141
+ Contribution principale dans l'atteinte des objectifs ................................................................... 51
142
+
143
+ Modifications depuis la dernière itération .................................................................................. 51
144
+
145
+ Résultats obtenus et comparaison au benchmark....................................................................... 51
146
+
147
+ Performances atteintes ............................................................................................................... 51
148
+ Comparaison aux benchmarks de la littérature ....................................................................................... 51
149
+
150
+ Atteinte des objectifs du projet................................................................................................... 52
151
+ Objectif 1 : Classification des espèces (✅ Atteint) .................................................................................. 52
152
+ Objectif 2 : Détection des maladies (⚠ Partiellement atteint)................................................................. 52
153
+ Objectif 3 : Application Streamlit (✅ En cours) ....................................................................................... 52
154
+
155
+ Processus métier d'inscription .................................................................................................... 52
156
+ Agriculture de précision ......................................................................................................................... 52
157
+ Services aux professionnels .................................................................................................................... 52
158
+ Applications grand public ....................................................................................................................... 52
159
+
160
+ Suite du projet .....................................................................................................................52
161
+
162
+ Pistes d'amélioration des performances ..................................................................................... 52
163
+ Amélioration des données ...................................................................................................................... 52
164
+
165
+ Optimisations architecturales ..................................................................................................... 53
166
+ Techniques avancées.............................................................................................................................. 53
167
+
168
+ Déploiement et optimisation ...................................................................................................... 53
169
+
170
+ Contribution à l'accroissement de la connaissance scientifique .................................................. 53
171
+ Avancées méthodologiques .................................................................................................................... 53
172
+
173
+ Connaissances domaine-spécifiques ........................................................................................... 53
174
+
175
+ Impact scientifique et sociétal .................................................................................................... 54
176
+
177
+
178
+
179
+
180
+
181
+ Partie 1 : Cadrage du projet
182
+
183
+ Contexte
184
+
185
+ La cible du projet est d’offrir à un individu, ne bénéficiant pas de l’expertise pour reconnaître
186
+ une plante et sa maladie éventuelle, la capacité de l’identifier via l’appareil photo de son
187
+ smartphone
188
+
189
+ ● Du point de vue technique, il s’agit d’utiliser des algorithmes de machine learning,
190
+ pour analyser les images et classifier les espèces de plantes, détecter les maladies et
191
+ réaliser des analyses statistiques afin de déterminer, le cas échéant, les corrélations
192
+ entre espèces de plantes et maladies associées.
193
+
194
+ ● Du point de vue économique, l’application construite pourra aider un certain nombre
195
+ (agriculteurs, distributeurs de plantes, paysagiste, …) à détecter
196
+ d’acteurs
197
+ précocement les maladies et éviter des pertes de récoltes ou de chiffre d’affaires, et
198
+ minimiser les coûts associés aux traitements tardifs.
199
+
200
+ ● Du point de vue scientifique, l’utilisation de cette application pourrait offrir un
201
+ support durable au recensement des espèces, renforcer l’échange de connaissances
202
+ entre chercheurs, en particulier sur le maintien de la bio-diversité, sensibiliser écoliers,
203
+ étudiants et grand public à la connaissance des espèces et leur conservation, être
204
+ élargi à la recherche des causes des maladies à l’aide de données additionnelles
205
+ (géographie, climat, …)
206
+
207
+ Objectifs
208
+
209
+ Description des macro-objectifs
210
+
211
+ Localiser et classifier l’espèce d’une plante dans une image
212
+
213
+ La photographie initiale prise par l’utilisateur sera analysée au regard de critères
214
+ d’acceptabilité comparables aux conditions d’entraînement de l’algorithme de classification
215
+ (niveau de flou, luminosité, contraste, etc). Elle sera ensuite retraitée (format JPEG, RGB,
216
+ redimensionnement et éventuellement retraitement du niveau de flou afin de faciliter le
217
+ diagnostic). Ce premier algorithme de classification, entraîné sur la base totale des images
218
+ décrite en page 14 et de méta-données pouvant y être rattachées aura été testé sur une base
219
+ constituée de 20% des images concernées avec un objectif d’accuracy de 95%. La base totale
220
+ des images aura été probablement corrigée afin de minimiser les déséquilibres entre classes.
221
+
222
+ Localiser et classifier la maladie éventuelle touchant la plante dans cette même image
223
+
224
+
225
+
226
+
227
+
228
+
229
+
230
+
231
+
232
+
233
+
234
+
235
+
236
+ La photographie retraitée, ou la photographie d’origine subissant de nouveaux filtres, sera
237
+ soumise à un second algorithme de classification, entraîné sur la base totale des images
238
+ décrite en page 14 et de méta-données pouvant y être rattachées (telles que le niveau de bleu
239
+ dans l’image qui est un premier prédicteur du caractère malade ou non de la plante) et testé
240
+ sur une base constituée de 20% des images concernées avec un objectif d’accuracy de 95%
241
+ des feuilles malades.
242
+
243
+ Bâtir une application renvoyant les informations de ces classifications à l’utilisateur sur la base
244
+ d’une photographie prise sur son smartphone.
245
+
246
+ L’application sera développée sur Streamlit conformément au schéma de l’application
247
+ présentée en Page 6 en veillant à des règles d’ergonomie de « base » (éviter les images de
248
+ fond, contraste des couleurs pour faciliter la lecture, usage des couleurs limité à une gamme
249
+ réduite, boutons de navigation explicites, etc.)
250
+ Jalons du projet
251
+
252
+ Schéma de fonctionnement de l’application
253
+
254
+
255
+
256
+
257
+
258
+
259
+
260
+
261
+
262
+
263
+
264
+ Niveaux d’expertise
265
+
266
+ Niveaux d’expertise interne
267
+
268
+ Nom
269
+
270
+ Algorithmie
271
+
272
+ Dév. Appli
273
+ mobile
274
+
275
+ Statistiques
276
+
277
+ Gestion
278
+ projet
279
+
280
+ Botanique
281
+
282
+ Ela CIMEN
283
+
284
+ Roland KONAN
285
+
286
+ Yacine MADI SAID
287
+
288
+ Nicolas RINCÉ
289
+
290
+ 2/5
291
+
292
+ 4/5
293
+
294
+ 3/5
295
+
296
+ 2/5
297
+
298
+ 0/5
299
+
300
+ 2/5
301
+
302
+ 5/5
303
+
304
+ 0/5
305
+
306
+ 3/5
307
+
308
+ 3/5
309
+
310
+ 2/5
311
+
312
+ 4/5
313
+
314
+ 4/5
315
+
316
+ 4/5
317
+
318
+ 4/5
319
+
320
+ 4/5
321
+
322
+ 3/5
323
+
324
+ 2/5
325
+
326
+ 1/5
327
+
328
+ 1/5
329
+
330
+ Recours à expertise externe
331
+
332
+ Nous n’avons pas eu recours à des experts externes à proprement parler (en-dehors de
333
+ Damien évidemment !) mais avons réalisé de nombreuses recherches afin de nous guider,
334
+ notamment sur les sujets suivants :
335
+
336
+ ● Taille des images standard utilisée dans les algorithmes de reconnaissance d’image ;
337
+ ● Détermination du niveau de flou d’une image et seuil d’acceptabilité pour la
338
+
339
+ reconnaissance d’images (150 de Laplacienne) ;
340
+
341
+ ● Retraitement des niveaux de flous ;
342
+ ● Déséquilibre acceptable entre classes sur le fichier d’entraînement (1 à 10) ;
343
+
344
+ Nombre minimal d’images à soumettre à l’algorithme par classe (1.000).
345
+
346
+ Partie 2 : Exploration et DataViz
347
+
348
+ Jeux de données
349
+ Soumis et exploités
350
+
351
+ https://www.kaggle.com/vbookshelf/v2-plant-seedlings-dataset
352
+
353
+ ● Arborescence de 12 dossiers pour 12 espèces de jeune pousse les plus répandue au
354
+
355
+ Danemark
356
+ Il n’y a qu’un seul dataset (non séparé en test/train) contenant 5539 images
357
+
358
+
359
+ ● Volumétries restreintes aux images d’espèces végétales : 100%
360
+
361
+ https://www.kaggle.com/vipoooool/new-plant-diseases-dataset
362
+
363
+ ● Fichier d’images de feuilles d’arbres fruitiers, de légumineuses et de céréales,
364
+
365
+ malades ou saines
366
+
367
+ ● Dataset d’entraînement de 70.295 images
368
+ ● Dataset de test de 17.572 images
369
+ ● Volumétries restreintes aux images d’espèces végétales : 100%
370
+
371
+ https://www.kaggle.com/saroz014/plant-disease
372
+
373
+
374
+
375
+
376
+
377
+
378
+
379
+
380
+
381
+ ● Fichier d’images de feuilles d’arbres fruitiers, de légumineuses et de céréales,
382
+
383
+ malades ou saines
384
+
385
+ ● Dataset d’entraînement de 43.456 images
386
+ ● Dataset de test de 10.849 images
387
+ ● Volumétries restreintes aux images d’espèces végétales : 100%
388
+
389
+ https://www.kaggle.com/abdallahalidev/plantvillage-dataset
390
+
391
+ ● Fichier d’images de feuilles d’arbres fruitiers, de légumineuses et de céréales,
392
+
393
+ malades ou saines
394
+
395
+ ● 3 Datasets de 54305 images chacun avec les mêmes images en couleur, niveau de
396
+
397
+ gris et prétraité.
398
+
399
+ ● Volumétries restreintes aux images d’espèces végétales : 100%
400
+
401
+ Soumis et non exploités
402
+
403
+ https://storage.googleapis.com/openimages/web/download.html et
404
+ https://cocodataset.org/#home
405
+
406
+ ● Non exploité car bases de données non spécifiquement axées sur les plantes, de
407
+ volumétrie limitée sur cette dernière catégorie, sans discrimination entre plantes
408
+ saines et plantes malades, dont le seul intérêt était la présence de masques qui ne
409
+ serviront pas dans les algorithmes choisis.
410
+
411
+ Constats
412
+
413
+ ● Les 3 dernières bases de données soumises et exploitées se sont révélées redondantes
414
+ et provenant d’un même set d’images initial. Nous n’avons donc conservé que la base
415
+ d’origine
416
+ test
417
+ d’entraînement
418
+ données
419
+ les
420
+ (https://www.kaggle.com/vipoooool/new-plant-diseases-dataset)
421
+
422
+ fusionnant
423
+
424
+ de
425
+
426
+ en
427
+
428
+ et
429
+
430
+ ● La première base nous est apparue trop limitée en nombre d’images (moins de 500
431
+ images par espèces), peu exploitable en raison de la part de l’image réservée au
432
+ végétal (il s’agit de jeunes pousses) et trop spécifique (12 espèces provenant du
433
+ Danemark). Nous l’avons donc abandonnée.
434
+
435
+ ● Compte tenu de la limitation du dataset à des arbres fruitiers et de céréales et de
436
+ légumineuses, nous avons recherché d’autres datasets permettant d’étendre la
437
+ reconnaissance à d’autres plantes (canne à sucre, maïs et vigne) comme exposé dans
438
+ le tableau ci-dessous. Comme pour le reste des datasets, ces images sont libres de
439
+ droits.
440
+
441
+ https://www.kaggle.com/datasets/nirmalsankalana/sugarcane-leaf-disease-dataset
442
+
443
+ ● Dataset d’images de feuilles de canne à sucre saine et malades
444
+ ● 2569 images, séparées en 5 répertoires (1 par maladie et 1 pour celles en bonne
445
+
446
+ santé)
447
+
448
+ ● Volumétries restreintes aux images d’espèces végétales : 100%
449
+
450
+ https://www.kaggle.com/datasets/nirmalsankalana/grape400-dataset
451
+
452
+
453
+
454
+
455
+
456
+
457
+
458
+
459
+
460
+
461
+ ● Datasets d’images de feuilles de vigne saines et malades
462
+ ● 1600 images séparées en 4 répertoires (1 par maladie et 1 pour celles en bonne
463
+
464
+ santé)
465
+
466
+ ● Volumétries restreintes aux images d’espèces végétales : 100%
467
+
468
+ https://www.kaggle.com/datasets/shuvokumarbasak4004/rose-leaf-disease-dataset
469
+
470
+ ● Datasets d’images de feuilles de rose saines et malades
471
+ ● 14,910 images séparées en 3 répertoires (test, train, validation)
472
+ ● Volumétries restreintes aux images d’espèces végétales : 100%
473
+
474
+ https://www.kaggle.com/datasets/nirmalsankalana/cassava-leaf-disease-classification
475
+
476
+ ● Datasets d’images de feuilles de cassave saines et malades
477
+ ● 21 397 images séparées en 5 répertoires (1 par maladie et 1 pour celles en bonne
478
+
479
+ santé)
480
+
481
+ ● Volumétries restreintes aux images d’espèces végétales : 100%
482
+
483
+ Pertinence
484
+ Variables
485
+
486
+ ● La reconnaissance des plantes, puis du caractère sain ou malade, va s’appuyer sur les
487
+ images sélectionnées. Le sujet de la pertinence des variables ne s’applique donc pas
488
+ de la même manière que sur un problème de classification basé sur un fichier de
489
+ données textuelles ou numériques. Les principales variables dans ce cadre seront les
490
+ pixels de chaque image.
491
+
492
+ ● Néanmoins, la sélection des images s’est appuyée dans une première phase
493
+ sur un fichier .csv répertoriant les principales caractéristiques des images (cf. section
494
+ suivante sur le pre-processing) : niveau de flou, luminosité, contraste, taille des
495
+ images, type de l’image (.jpeg, .png, …) .
496
+
497
+ ● C’est dans ce même fichier que nous avons logé les deux variables cibles : le nom de la
498
+
499
+ plante, d’une part, le caractère sain ou malade d’autre part.
500
+
501
+ ● Un troisième fichier de données devra être constitué pour abriter les données
502
+
503
+ descriptives à afficher sur l’application streamlit.
504
+
505
+
506
+
507
+
508
+
509
+
510
+
511
+
512
+ Description
513
+
514
+ Le dataframe global contient 126 668 images pour 19 espèces.
515
+
516
+ Limitation des données
517
+
518
+ ● Limitations liées au périmètre des données : la première limitation concerne le
519
+
520
+ périmètre des plantes et végétaux présents dans la base. Dès lors, l’application ne
521
+ pourra pas être utilisée pour reconnaître « toutes » les espèces de plantes. La
522
+ généralisation de l’application ne pourrait venir que de l’élargissement du périmètre
523
+ des plantes concernées.
524
+
525
+ ● Limitations liées à l’hétérogénéité des données : la seconde limitation concerne
526
+
527
+ l’hétérogénéité des données étudiées, qui a mené à l’exclusion des images de jeunes
528
+ pousses trop éloignées de la majorité de la base d’images que nous avons pu
529
+ constituer, et insuffisamment nombreuses pour les intégrer dans le jeu
530
+ d’entraînement. De même, cela limitera la portée de l’application.
531
+
532
+
533
+
534
+
535
+
536
+
537
+
538
+ ● Limitations liées au déséquilibre des classes : la troisième limitation concerne le
539
+
540
+ déséquilibre entre plantes avec une surreprésentation de certaines espèces dont en
541
+ particulier les tomates.
542
+
543
+ ● Limitations liées à la qualité des données : la quatrième limitation touche la qualité
544
+ des données parmi les images retenues, et notamment leur degré de flou qui est
545
+ primordial dans la reconnaissance des images
546
+
547
+ ● Limitations liées à la taille du dataset : la cinquième limitation concerne la taille de
548
+
549
+ l’ensemble des images ainsi constituées qui doit être limitée afin de tenir compte des
550
+ temps de traitement de l’algorithme.
551
+
552
+ Partie 3 : Pré-Processing et feature engineering
553
+
554
+ Création du dataframe des caractéristiques
555
+
556
+ Afin de faciliter la sélection des images nous avons créé un dataframe contenant les
557
+ caractéristiques de l’ensemble des images issues des dataset qui présente la structure
558
+ suivante :
559
+
560
+ ● FileName : nom du fichier,
561
+ ● FilePath : chemin vers le dataset initial,
562
+ ● Extension : extension de l’image
563
+ ● Species :espèce,
564
+ ● Disease : maladie,
565
+ ● FileSize : taille de l’image,
566
+ ● Width : largeur de l’image,
567
+ ● Height : hauteur de l’image,
568
+ ● Contrast : moyenne du contraste
569
+ ● Luminosity: moyenne de la luminosité
570
+ ● RedMean: moyenne de vert
571
+ ● GreenMean : moyenne de vert
572
+ ● BlueMean : moyenne de bleu
573
+ ● Blur : moyenne de flou
574
+
575
+ Nettoyage des données et étapes de traitement
576
+
577
+ Définition des critères de sélection :
578
+
579
+ ● Flou > 500
580
+ ● Contraste > 2
581
+ ● Luminosité < 200
582
+ ● Nombre maximum d’image =12500
583
+ ● nombre minimum d’image =1250
584
+
585
+
586
+
587
+
588
+
589
+
590
+
591
+
592
+
593
+
594
+ A partir du dataframe initial, on parcourt l’ensemble des images grâce au FilePath pour
595
+ appliquer nos critères de qualité et créer un dataframe (df_high_quality)
596
+ réunissant uniquement les images qui passent le test.
597
+
598
+ Ceux ne passant pas les critères de qualité vont être intégré à un dataframe différent
599
+ (df_low_quality) pour être traité.
600
+
601
+ Transformations des données
602
+
603
+ Traitement des images
604
+ Plusieurs traitements sont appliqués aux images dans le but d’améliorer leur qualité. Les
605
+ traitements incluent des ajustements sur la luminosité, le contraste, la netteté (flou et
606
+ netteté), ainsi que des redimensionnements.
607
+
608
+ Les étapes sont détaillées ci-dessous :
609
+
610
+ 1. Ajustement de la luminosité
611
+
612
+ La fonction `adjust_brightness(image)` permet de modifier la luminosité d'une image en
613
+ utilisant la méthode `ImageEnhance.Brightness` de la bibliothèque `PIL`. Le facteur de
614
+ luminosité, défini par `brightness_factor`, est appliqué à l'image. Après ajustement, la
615
+ luminosité moyenne de l'image (calculée sur une conversion en niveaux de gris) est
616
+ renvoyée pour référence.
617
+
618
+ 2. Augmentation du contraste
619
+
620
+ La fonction `process_contrast(image)` augmente le contraste de l'image à l'aide de
621
+ `ImageEnhance.Contrast`. Le facteur de contraste, défini par `contrast_factor`, est appliqué
622
+ pour rendre les différences entre les pixels plus marquées. Après traitement, la fonction
623
+ calcule et renvoie la variance de l'image en niveaux de gris (une mesure du contraste).
624
+
625
+ 3. Calcul du flou (Netteté)
626
+
627
+ La fonction `calculate_blurriness(image)` utilise la méthode du Laplacien pour calculer le flou
628
+ d’une image. Le flou est mesuré par la variance de la matrice du Laplacien sur l'image en
629
+ niveaux de gris. Une faible variance indique un flou plus élevé, tandis qu'une haute variance
630
+ indique une image plus nette.
631
+
632
+ 4. Augmentation de la netteté
633
+
634
+ La fonction `increase_sharpness(image)` est utilisée pour améliorer la netteté de l'image.
635
+ Cela se fait par l'application de la méthode `ImageEnhance.Sharpness`. Un facteur de
636
+ netteté, `sharpness_factor`, est défini pour contrôler l’intensité de l'amélioration. Après
637
+ avoir ajusté la netteté, la fonction calcule et renvoie également le niveau de flou après
638
+ traitement pour évaluer l’effet de la netteté appliquée.
639
+
640
+
641
+
642
+
643
+
644
+
645
+
646
+
647
+
648
+ 5. Redimensionnement de l’image
649
+
650
+ La fonction `resize_image(image, width, height)` redimensionne les images à une taille
651
+ spécifiée (ici, 256x256 pixels). Cette opération est réalisée avec la méthode `resize()` de PIL
652
+ en utilisant l'algorithme `LANCZOS`, qui permet de préserver la qualité de l'image lors du
653
+ redimensionnement.
654
+
655
+ 6. Configuration des paramètres globaux
656
+
657
+ Les facteurs de traitement sont définis avant le traitement :
658
+
659
+
660
+
661
+
662
+
663
+
664
+ `brightness_factor` : Ajuste la luminosité (ici fixé à 0.8 pour une légère réduction de
665
+ la luminosité).
666
+ `contrast_factor` : Augmente le contraste (ici fixé à 1.5 pour un contraste plus élevé).
667
+ `sharpness_factor` : Améliore la netteté (ici fixé à 4.0 pour une forte amélioration de
668
+ la netteté).
669
+
670
+ ● Taille de redimensionnement : Les images sont redimensionnées à 256x256 pixels
671
+
672
+ pour une normalisation de la taille.
673
+
674
+ 7. Exécution et enregistrement des résultats
675
+
676
+ Une fois les images traitées, le DataFrame Low_quality_processed contenant les
677
+ informations des images traitées est enregistré dans un fichier CSV. Ce fichier peut être
678
+ utilisé pour des analyses ultérieures ou pour vérifier les modifications apportées à chaque
679
+ image.
680
+
681
+ 8. Combinaison dans un dataframe global
682
+
683
+ Les dataframes High_quality et Low_quality_processed sont combinés dans un nouveau
684
+ dataframe df_recombined_quality.
685
+
686
+
687
+
688
+
689
+
690
+
691
+ Visualisations et Statistiques
692
+
693
+ Corrélation entre variables du dataframe
694
+
695
+ On constate que les variables de luminosité et de niveau de rouge, vert et bleu sont très bien
696
+ corrélées. En revanche, à l’exception du couple (“Blur”,”Filesize”), les autres variables sont
697
+ peu corrélées entre elles.
698
+
699
+ Relations avec les variables cibles
700
+
701
+ Nous n’avons pas identifié de relations entre la variable ‘species’ et le reste des variables. En
702
+ revanche, en première approche, nous avons noté une corrélation entre le niveau de
703
+ “jaune” des images et la variable saine ou malade sur une partie du jeu de données (cf.
704
+ Analyse statistiques).
705
+
706
+ Distribution des données
707
+
708
+ Distribution des espèces dans le dataframe “high quality”
709
+
710
+
711
+
712
+
713
+
714
+
715
+
716
+
717
+
718
+ Dans le dataframe des images de bonnes qualités, il y a 79 599 images, dont les trois
719
+ premières espèces représentent + 45% du total.
720
+
721
+ Distribution des espèces dans le dataframe “low quality”
722
+
723
+ Il y a 47 069 images, on peut remarquer que l’ensemble des images des espèces cassave, riz,
724
+ et sucre de canne ne sont présentes que sur le dataframe de mauvaise qualité.
725
+
726
+ Mesure d’amélioration de la qualité des images
727
+
728
+ Distribution du flou avant/après retraitements
729
+
730
+ D'après la visualisation, la densité des valeurs de flou a augmenté après traitement, ce qui
731
+ suggère une amélioration de la qualité des images. En effet, on peut observer que le pic de
732
+ l'histogramme a migré de 500 avant le traitement à 2000 après le traitement, ce qui indique
733
+
734
+
735
+
736
+
737
+
738
+
739
+
740
+
741
+
742
+ que les images sont devenues plus nettes et moins floues après avoir subi les ajustements
743
+ sur la netteté.
744
+
745
+ Analyse du contraste et de la luminosité avant et après retraitement
746
+
747
+ Les boîtes à moustaches montrent que le retraitement a amélioré la qualité des images en
748
+ réduisant les valeurs aberrantes. Pour le contraste, la médiane est restée stable, mais les
749
+ valeurs très faibles de contraste ont été corrigées, et la gamme des valeurs s'est élargie. De
750
+ même, pour la luminosité, la médiane est inchangée, mais les images trop lumineuses ont
751
+ été ajustées, créant une distribution plus homogène. En résumé, les traitements ont réduit
752
+ les extrêmes tout en maintenant une stabilité de la médiane.
753
+
754
+ Analyse du redimensionnement
755
+
756
+ Avant retraitement, les images avaient des dimensions très variées, ce qui compliquait leur
757
+ analyse et leur traitement uniforme. Cette hétérogénéité des tailles pouvait entraîner des
758
+ biais lors de l'application de modèles d'apprentissage automatique ou d'autres analyses
759
+ d'images, car les réseaux de neurones et les algorithmes de traitement d'images nécessitent
760
+ des entrées de taille uniforme. Après retraitement, toutes les images ont été
761
+ redimensionnées à une taille standard de 256x256 pixels, un format couramment utilisé
762
+ dans la datascience. Cette normalisation permet non seulement de faciliter l'analyse et
763
+ l'entraînement des modèles, mais elle garantit également que toutes les images sont
764
+ traitées de manière cohérente, améliorant ainsi la performance des modèles d'analyse et de
765
+ classification.
766
+
767
+
768
+
769
+
770
+
771
+ Analyses statistiques
772
+
773
+ Le niveau de bleu semble être le plus discriminant entre feuilles saines et feuilles malades,
774
+ probablement lié à la présence de tâches de couleur jaune (R+V) sur la plupart de ces
775
+ dernières.
776
+
777
+ Si on réalise un test de student pour tester l’hypothèse que les niveaux de bleu sont
778
+ significativement différents entre des feuilles saines et des feuilles malades, on trouve une
779
+ statistique t de 128 et une valeur p très proche de 0, ce qui prouve que ce niveau de bleu est
780
+ discriminant.
781
+
782
+ Ceci est confirmé par une première approche de classification via un premier modèle
783
+ Random Forest mené en prenant pour Target le statut (Sain/Malade) et en Data, la moyenne
784
+ de bleu, rouge, vert, le contraste et la luminosité donne un taux de bonne prédiction de
785
+ 88%.
786
+
787
+ Le graphique ci-contre montre l’importance des variables dans la contribution à la
788
+ classification et confirme en contributeur principal le niveau de bleu.
789
+
790
+ Le taux de bonne prédiction de la classe malade est de 93,5% mais le modèle ne fonctionne
791
+ pas correctement pour le classement des images saines (taux de prédiction de 74%)
792
+
793
+
794
+
795
+ Un premier modèle Random Forest ent
796
+
797
+ pour le classement des images saines (taux de prédiction de
798
+
799
+
800
+
801
+
802
+
803
+
804
+
805
+
806
+ Conclusions pré-modélisation
807
+
808
+ Nous disposons au terme de cette étape d’un fichier homogène en termes de qualité
809
+ d’images, d’une quantité a priori suffisante pour appliquer un algorithme de reconnaissance,
810
+ au déséquilibre entre classes moins marqué que sur les données d’origine, et qui affiche déjà
811
+ quelques variables discriminantes sur l’une des deux variables cibles.
812
+
813
+ Partie 4 : Modélisation
814
+
815
+ Classification du problème
816
+
817
+ Type de problème de machine learning
818
+
819
+ La cible du projet est d’offrir à un individu, ne bénéficiant pas de l’expertise pour reconnaître
820
+ une plante et sa maladie éventuelle, la capacité de l’identifier via l’appareil photo de son
821
+ smartphone. Il s’agit donc d’un problème de classification des espèces ainsi que des maladies
822
+ associées sur la base des images qui seront soumises par l’utilisateur.
823
+
824
+ Tâches de machine learning
825
+
826
+ La tâche associée est la reconnaissance d’images, spécifiquement de feuilles associées à 18
827
+ espèces végétales (fruits, légumineuses, céréales), dont les contours puis les détails sont
828
+ progressivement analysées à travers les couches du réseau de neurones modélisé.
829
+
830
+ Métriques de performance utilisées pour comparer les modèles
831
+
832
+ A ce stade nous avons choisi 2 métriques.
833
+
834
+ Métrique principale
835
+
836
+ Accuracy : Compte tenu de la limitation du déséquilibre entre classes obtenu après la phase
837
+ de pre-processing, nous avons choisi de retenir l’Accuracy comme métrique principale, définie
838
+ comme le rapport entre le nombre de bonnes prédictions et le nombre total de prédictions.
839
+
840
+ Métriques secondaires
841
+
842
+ Loss : Nous avons également jaugé la rapidité de la convergence du modèle en suivant la
843
+ notion de loss à chaque époque de l’apprentissage.
844
+
845
+ Selon les modèles et afin de nous assurer, malgré le faible déséquilibre de classes, que les
846
+ classes les moins représentées soient correctement traitées, nous avons observé dans certains
847
+ cas quelle était la k-ème Accuracy la plus faible parmi les classes proposées au modèle.
848
+
849
+
850
+
851
+
852
+
853
+
854
+
855
+
856
+
857
+
858
+
859
+
860
+
861
+
862
+
863
+
864
+
865
+
866
+ Choix du modèle et optimisation
867
+
868
+ Algorithmes testés
869
+ Nous avons retenu 6 algorithmes :
870
+
871
+ ● 3 algorithmes Keras avec les modèles ResNet50V2, EfficientNetB0 et
872
+
873
+ EfficientNetV2M;
874
+
875
+ ● 1 algorithme FastAI avec le modèle efficientnet_b0
876
+ ● 2 algorithmes Torch, l’un avec transfer learning (MobileNetV2, adapté pour une
877
+ application mobile comme c’est l’objectif ici) et l’autre sans transfer learning
878
+
879
+ ● 1 algorithme AlexNet
880
+
881
+ Résultats par modèle
882
+
883
+ 1- KERAS
884
+
885
+ Keras est une bibliothèque open-source de haut niveau pour la création et l'entraînement de
886
+ modèles d'apprentissage profond (deep learning). Elle a été développée par François Chollet
887
+ en 2015 et est maintenant intégrée directement dans TensorFlow, où elle sert d'interface
888
+ principale pour construire et entraîner des réseaux de neurones. Pour notre étude nous
889
+ avons décidé de comparer 3 modèles de réseau de neurones : ResNet50V2,EfficientNetB0 et
890
+ EfficientNetV2M en transfert learning et en fine tuning.
891
+
892
+ Description des modèles
893
+
894
+ ResNet50V2 :
895
+
896
+ ● Architecture : ResNet50V2 (Residual Networks) utilise des blocs résiduels, ce qui
897
+ permet de mieux entraîner des réseaux profonds en atténuant le problème de
898
+ dégradation de la performance.
899
+
900
+ ● Profundité : 50 couches.
901
+
902
+ ● Performance : Bon compromis entre précision et temps de calcul, particulièrement
903
+
904
+ efficace pour des tâches classiques de classification d'images (ImageNet).
905
+
906
+ ● Avantages : C'est un modèle classique très utilisé avec des performances solides sur
907
+
908
+ de nombreuses applications.
909
+
910
+
911
+
912
+ Inconvénients : Moins efficace en termes de computation par rapport aux
913
+ architectures récentes comme EfficientNet.
914
+
915
+ EfficientNetB0 :
916
+
917
+ ● Architecture : EfficientNet utilise une méthode d'optimisation appelée "compound
918
+ scaling", qui ajuste simultanément la profondeur, la largeur et la résolution de
919
+ l'image, offrant ainsi une meilleure efficacité énergétique et une précision
920
+
921
+
922
+
923
+
924
+
925
+
926
+
927
+
928
+
929
+
930
+
931
+
932
+
933
+
934
+ supérieure.
935
+
936
+ ● Profundité : Moins profond que ResNet50V2, mais beaucoup plus efficace pour les
937
+
938
+ mêmes performances.
939
+
940
+ ● Performance : Généralement plus rapide et plus efficace que ResNet50V2 pour la
941
+
942
+ même précision.
943
+
944
+ ● Avantages : Très efficace en termes de taille du modèle et d'utilisation des
945
+
946
+ ressources, il donne de bons résultats même avec des réseaux moins profonds.
947
+
948
+
949
+
950
+ Inconvénients : Moins éprouvé que ResNet50V2 dans certaines configurations.
951
+
952
+ EfficientNetV2M :
953
+
954
+ ● Architecture : Une amélioration de l'EfficientNet original, qui intègre des techniques
955
+
956
+ de fusion des convolutions et un meilleur équilibrage des ressources.
957
+
958
+ ● Profundité : Plus profond que EfficientNetB0, ce qui le rend potentiellement plus
959
+
960
+ puissant, mais aussi plus lourd en termes de calcul.
961
+
962
+ ● Performance : Très performant sur des tâches complexes et des jeux de données
963
+
964
+ volumineux, surpassant souvent EfficientNetB0 et ResNet50V2.
965
+
966
+ ● Avantages : Très performant tout en restant optimisé pour des ressources limitées.
967
+
968
+
969
+
970
+ Inconvénients : Modèle plus complexe et potentiellement plus long à entraîner
971
+ comparé à EfficientNetB0.
972
+
973
+ Résultats
974
+
975
+ L'entraînement a été effectué 55 classes qui résultent du croisement espèce et maladie. Pour
976
+ chaque modèle nous avons effectué un entraînement en transfert learning sur 10 époques
977
+ avec les couches du modèle freezées. Nous avons dans une seconde étape nous avons
978
+ effectué du fine tuning des modèles entraînés sur 30 époques avec les 30 dernières couches
979
+ non freezées.
980
+
981
+ Etape Transfer learning
982
+
983
+ Etape Fine tuning
984
+
985
+ Modèle
986
+
987
+ ResNet50V2
988
+
989
+ EfficientNetB0
990
+
991
+ EfficientNetV2M
992
+
993
+ ResNet50V2
994
+
995
+ EfficientNetB0
996
+
997
+ EfficientNetV2M
998
+
999
+ Accuracy
1000
+
1001
+ 0.92
1002
+
1003
+ 0.92
1004
+
1005
+ 0.91
1006
+
1007
+ 0.95
1008
+
1009
+ 0.95
1010
+
1011
+ 0.95
1012
+
1013
+
1014
+
1015
+
1016
+
1017
+
1018
+
1019
+
1020
+
1021
+
1022
+
1023
+
1024
+
1025
+
1026
+
1027
+
1028
+
1029
+ Les 3 modèles plafonnent à 0.95 après le fine tuning. En effet, les résultats de la classification
1030
+ des images de l’espèce cassava sont très mauvais sur les trois modèles. Il faudra dans une
1031
+ seconde étape étudier en détail ces images.
1032
+
1033
+ Exemple de classification report avec un zoom sur l'espèce cassava.
1034
+
1035
+ Graphe comparatif de l’évolutions de la précision et de la perte des trois modèles
1036
+
1037
+
1038
+
1039
+
1040
+
1041
+
1042
+
1043
+
1044
+
1045
+
1046
+ Comparaison du f1-score par classe et par modèles
1047
+
1048
+
1049
+
1050
+
1051
+
1052
+
1053
+ 2- FastAI
1054
+
1055
+ Fastai est une librairie open-source de haut niveau pour le deep learning.
1056
+ Construite sur PyTorch, elle a pour objectif de simplifier les entraînements de modèles,
1057
+ accélérer les déploiements de modèles tout en conservant la performance et les
1058
+ fonctionnalités avancées de Pytorch.
1059
+
1060
+ Le modèle sélectionné pour l'entraînement est efficientnet_b0. Proposé par Google, il est le
1061
+ plus petit des modèles de la famille EfficientNet, ce qui le rend pertinent pour son utilisation
1062
+ sur du matériel avec des ressources limitées (smartphone, tablette).
1063
+
1064
+ En analysant les résultats de performance à chaque itération, on constate que :
1065
+
1066
+ 1) La perte de validation suit une tendance à la baisse, passant de 0.3093 à 0.1281.
1067
+ Rejoignant la perte d'entraînement, ce qui suppose une bonne généralisation du
1068
+ modèle
1069
+
1070
+ 2) La précision croît jusqu'à atteindre 95% sur 5 epoch seulement, avec un taux d’erreur
1071
+
1072
+ à 4%, ce qui implique une très bonne performance du modèle.
1073
+
1074
+
1075
+
1076
+
1077
+
1078
+
1079
+ 3- Torch
1080
+
1081
+ Description des modèles
1082
+
1083
+ 2 modèles ont été testés sous Torch :
1084
+
1085
+ ● 1 modèle simple avec Transfer Learning, basé sur
1086
+
1087
+ le modèle pré-entraîné
1088
+ MobileNetV2, dont les couches intermédiaires sont neutralisées et seule la dernière
1089
+ couche est ajustée aux classes à prédire, puis ré-entrainée. Le choix s’est porté sur ce
1090
+ modèle car il est réputé être idéal pour des applications embarquées sur mobile,
1091
+ impliquant des contraintes de calcul (puissance limitée du matériel) ou nécessitant un
1092
+ fonctionnement en temps réel.
1093
+
1094
+ ● 1 modèle simple sans Transfer Learning, comprenant une première couche de
1095
+ convolution analysant le couleurs RGB (3 canaux) avec 32 filtres détectant les motifs
1096
+ simples et les contours, un deuxième bloc convolutif avec 64 filtres permettant de
1097
+ capter des motifs plus complexes (formes des feuilles, textures), une couche dense
1098
+ interprétant les motifs détectés et enfin la dernière couche de sortie donnant les
1099
+ probabilités par classe de plantes. La représentation du modèle est portée en Annexes.
1100
+
1101
+ ● Les 2 modèles ont été testés successivement sur 18 classes (espèces) et 58 classes
1102
+
1103
+ (croisements espèces x maladies)
1104
+
1105
+ Résultats
1106
+
1107
+ ● S’agissant de la précision globale des modèles :
1108
+
1109
+
1110
+
1111
+
1112
+
1113
+
1114
+
1115
+
1116
+
1117
+
1118
+
1119
+ Modèle
1120
+
1121
+ Accuracy
1122
+
1123
+ 18 classes
1124
+
1125
+ 58 classes
1126
+
1127
+ transfer
1128
+
1129
+ sans
1130
+ transfer
1131
+
1132
+ transfer
1133
+
1134
+ sans
1135
+ transfer
1136
+
1137
+ 99,38%
1138
+
1139
+ 99,59%
1140
+
1141
+ 94,79%
1142
+
1143
+ 98,38%
1144
+
1145
+ 3ème Accuracy la plus faible
1146
+
1147
+ 98,15%
1148
+
1149
+ 98,85%
1150
+
1151
+ 40,44%
1152
+
1153
+ 80,94%
1154
+
1155
+ Le modèle “simple” sans transfer learning apparaît plus précis avec des taux d’accuracy
1156
+ supérieur, a fortiori lorsque le nombre de classes augmentent.
1157
+ La reconnaissance des espèces est bonne et aucune d’entre elles ne montre une
1158
+ accuracy inférieure à 97%.
1159
+
1160
+ En revanche la reconnaissance des croisements espèces x maladies est plus
1161
+ problématique avec des précisions faibles sur les maladies touchant la vigne (avec des
1162
+ redondances de maladies ou des variantes de maladies qui semblent très proches qui
1163
+ seront traitées dans l’étape suivante) s’agissant du modèle sans transferlearning et de
1164
+ la cassava sur le modèle avec transferlearning.
1165
+
1166
+ ● Les matrices de confusion pour les modèles à 18 classes sont présentées ci-dessous,
1167
+
1168
+ en commençant par celle du modèle MobileNetV2.
1169
+
1170
+
1171
+
1172
+
1173
+
1174
+
1175
+
1176
+
1177
+ ● La convergence des modèles lors de l’apprentissage est plus rapide pour le modèle
1178
+ pré-entraîné mais ce dernier est dépassé dès la 4ème époque, la loss convergeant vers
1179
+ 2,65% pour le modèle sans transfer learning 18 classes (resp. 6,27% avec 58 classes)
1180
+ et vers 6,55% pour le premier modèle 18 classes (resp. 24,75% avec 58 classes).
1181
+
1182
+ 4- AlexNet
1183
+
1184
+
1185
+
1186
+
1187
+
1188
+
1189
+ AlexNet est intéressant pour la classification d'images car il a introduit une architecture de
1190
+ réseau de neurones convolutifs profonds, utilisant des couches convolutives et des unités de
1191
+ rectification linéaire (ReLU), qui a significativement amélioré la précision de la reconnaissance
1192
+ d'images sur des jeux de données complexes comme ImageNet.
1193
+
1194
+ Le modèle a été initialisé en suivant l’architecture suivante :
1195
+
1196
+ ● Couches convolutives et pooling : L'architecture commence par deux couches
1197
+ convolutives suivies de couches de max-pooling pour extraire et réduire les
1198
+ caractéristiques spatiales des images. Les tailles des filtres et des strides varient pour
1199
+ capturer différents niveaux de détails.
1200
+
1201
+ ● Couches convolutives supplémentaires : Trois couches convolutives supplémentaires
1202
+ sont ajoutées, suivies d'une couche de max-pooling, pour approfondir l'extraction des
1203
+ caractéristiques et capturer des motifs plus complexes dans les images.
1204
+
1205
+ ● Couches entièrement connectées et régularisation : Après l'aplatissement des
1206
+ caractéristiques, deux couches entièrement connectées avec des unités de dropout
1207
+ sont utilisées pour la classification. La sortie finale est une couche dense avec une
1208
+ activation softmax pour la classification multi-classes.
1209
+
1210
+ La précision est de 80,40 % sur les données d'entraînement et de 85,40 % sur les données de
1211
+ test.
1212
+
1213
+ La perte (loss) semble globalement correcte car elle diminue au fil des époques, indiquant une
1214
+ amélioration du modèle, bien que des fluctuations soient observées sur les données
1215
+ d’entraînement.
1216
+
1217
+ L'analyse des métriques de classification indique que le modèle ne performe pas bien, avec
1218
+ des scores F1 très faibles pour toutes les classes, une précision globale de seulement 0,03, et
1219
+ des valeurs moyennes macro et pondérées également très basses, ce qui suggère une
1220
+ mauvaise capacité de généralisation et de classification des différentes catégories,
1221
+ probablement due à un déséquilibre des classes dans les données.
1222
+
1223
+
1224
+
1225
+
1226
+
1227
+
1228
+
1229
+
1230
+ Optimisation
1231
+
1232
+ Nos modèles ont été optimisés en suivant 2 phases.
1233
+
1234
+ Phase 1
1235
+
1236
+ La première phase a reposé sur :
1237
+
1238
+ ● des corrections d’erreur : mesures de précision sur des images test et non les images
1239
+
1240
+ d’entraînement ;
1241
+
1242
+ ● des “élagages” rapides de modèles jugés non pertinents ;
1243
+
1244
+
1245
+ l’utilisation de techniques de fine-tuning : choix des “optimizers”, gel/dégel de
1246
+ couches des modèles pour l’apprentissage, technique d’augmentation de data,
1247
+ ajustement des learning rates et introduction de scheduler, modification des fonctions
1248
+ de “loss”, techniques de callback, application de poids aux classes pour corriger les
1249
+ déséquilibres ;
1250
+
1251
+ ● des ajustements techniques pour un apprentissage plus rapide : réorganisation du
1252
+
1253
+ code ;
1254
+
1255
+ ● des choix réalisés pour le traitement de classes dont la prédiction est plus complexe
1256
+ : il s’agit principalement de la classe “Cassava” avec la suppression pure et simple de
1257
+ ces classes ou bien focus sur la précision augmentée des modèles au fur et à mesure
1258
+ du fine-tuning.
1259
+
1260
+ Abandon de modèles non pertinents
1261
+
1262
+ 2 modèles testés ont été immédiatement abandonnés :
1263
+
1264
+ ● Le modèle entraîné sous Pytorch sans transfer learning, en raison de son taux de
1265
+ précision sur les images tests de 83%, très inférieur aux modèles pré-entraînés testés
1266
+ dans le chapitre précédent.
1267
+
1268
+ ● Le modèle AlexNet, qui affiche à la fois un temps d’entraînement trop important et un
1269
+
1270
+ taux de précision de 88%, également très en-deça des autres modèles testés.
1271
+
1272
+ Ajustements techniques pour rapidité d’apprentissage
1273
+
1274
+ Les modèles testés sous FastAI dans l’étape précédente (EfficientNetB0 et VGG12) ont été
1275
+ migrés vers TensorFlow pour les raisons suivantes :
1276
+
1277
+ ● TensorFlow est plus simple à intégrer sur Firebase ;
1278
+
1279
+
1280
+
1281
+ Il est optimisé pour la performance et la taille des modèles ;
1282
+ Il intègre un large écosystème avec support pour la quantification (réduction de la
1283
+ taille des modèles) ;
1284
+ Il est compatible avec les modèles pré-entraînés comme les réseaux convolutifs (CNN)
1285
+ pour les images.
1286
+
1287
+
1288
+
1289
+
1290
+
1291
+
1292
+
1293
+
1294
+
1295
+
1296
+
1297
+
1298
+
1299
+ Choix réalisés pour le traitement de la Cassave
1300
+
1301
+ Le traitement de la Cassave dans les opération de “fine-tuning” du modèle ont pris deux
1302
+ formes:
1303
+
1304
+ ● La suppression pure et simple de la cassave dans le cadre de l’apprentissage: c’est le
1305
+
1306
+ cas dans ce qui suit sur les entraînements de VGG12 et EfficientNetB0 sous
1307
+ TensorFlow ;
1308
+
1309
+ ● Le maintien de cette espèce dans la base d’apprentissage mais, avec une recherche
1310
+ spécifique d’amélioration de la prédiction: c’est ce qui a été fait sur MobileNetV2
1311
+ sous Pytorch, et VGG16, Vit16, EfficientNetV2M et ResNet50V2 sous Keras.
1312
+
1313
+ Résultats du fine-tuning
1314
+
1315
+ MobileNetV2 sous Pytorch
1316
+
1317
+ Le modèle a été calibré et testé comme suit :
1318
+
1319
+ ● # époques : 10
1320
+
1321
+ ○ # époques sur le classifier : 5
1322
+ ○ époques de fine tuning sur les autres couches : 5
1323
+
1324
+ ● Learning rate : 0.001 pour le classifier et 0.0001 pour le fine tuning
1325
+ ● Optimizer : Adam
1326
+
1327
+ L’accuracy globale est de 97,22% mais un F1-score de 65,21% seulement sur la Cassave
1328
+ Healthy
1329
+
1330
+ Le fine-tuning pour mieux prédire cette classe a consisté à:
1331
+
1332
+ ● Augmentation sur les classes spécifiées : Random Horizontal Flip, Rotation aléatoire
1333
+
1334
+ jusqu’à 30%
1335
+
1336
+ ● Augmentation du nombre d’époques à : 20
1337
+ ● Entrainement de la dernière couche seulement
1338
+ ● Learning rate : 0.0001
1339
+ ● Optimizer : Adam
1340
+
1341
+ L’accuracy globale s’est avérée dégradée à 86,85% avec un F1-score de 18,80% sur la Cassave
1342
+ Healthy, ce qui a mené à l’abandon du modèle.
1343
+
1344
+ EfficientNetB0 et VGG12 sous TensorFlow
1345
+
1346
+ Le fine-tuning a consisté à:
1347
+
1348
+ ● Organisation du code pour améliorer le temps d’apprentissage
1349
+ ● Augmentation de la data sur le modèle
1350
+ ● Ajouts des poids sur les classes pour lutter contre le déséquilibre
1351
+ ● Gel/Dégel du modèle de base
1352
+ ● Shuffle passé à False dans le dataset de test
1353
+
1354
+
1355
+
1356
+
1357
+
1358
+
1359
+
1360
+
1361
+
1362
+
1363
+
1364
+ Les métriques précision, recall et F1-score gagnent environ 1pt pour atteindre 95% et 98%
1365
+ pour respectivement EfficientNetB0 et VGG12. Ce dernier est donc plus performant, ce qui
1366
+ élimine le premier modèle.
1367
+ Bien que dans l’apprentissage de ces deux modèles, les classes “Cassava” aient été exclues,
1368
+ on note des classes de tomates moins bien prédites telles que celles atteintes des maladies
1369
+ “Mosaic Virus” et “Spider Mites” (Précision : 73%, Recall : 98%, F1-Score : 84%). On note
1370
+ d’ailleurs qu’à l’oeil nu la résolution de certaines images ne permet pas de détecter ces
1371
+ maladies.
1372
+
1373
+ Mosaic Virus
1374
+
1375
+ Spider Mites
1376
+
1377
+ VGG16 sous Keras
1378
+
1379
+ L’entraînement de ce modèle a donné globalement des résultats décevants.
1380
+
1381
+ Pour ce modèle, les mesures de fine-tuning ont consisté à:
1382
+
1383
+ ● Réduction de la taille des images pour améliorer la vitesse d’entraînement (128x128)
1384
+ ● Entraînement sur 10 époques avec freeze des paramètres
1385
+ ● Puis entraînement sur 10 epoches avec unfreeze des 5 dernières couches et ajout de
1386
+
1387
+ poids pour gérer le déséquilibre des classes
1388
+
1389
+ ● Learning rate (optimizer Adam) plus petit lors du dégel (0.00001 vs 0.0001 lors du
1390
+
1391
+ freeze) pour améliorer l’apprentissage
1392
+
1393
+ ● Callbacks :
1394
+
1395
+ ○ EarlyStopping pour arrêter l'entraînement si la perte de validation ne
1396
+
1397
+ s'améliore pas après 5 epochs
1398
+
1399
+ ○ ReduceLROnPlateau pour réduire le taux d'apprentissage de 20% après 3
1400
+
1401
+ époques sans amélioration de la perte de validation
1402
+
1403
+ ○ StopTrainingAtAccuracy pour arrêter l'entraînement dès que la précision
1404
+
1405
+ atteint 90%
1406
+
1407
+ On constate une baisse de l’Accuracy de 75,02% à 70,02% au terme du fine-tuning. La
1408
+ classification s’améliore sur l’ensemble des classes sauf sur la Tomate, la Cassave et la Canne
1409
+ à sucre. La faible Accuracy et la longueur de l’entraînement nous font conclure à l’abandon
1410
+ du modèle.
1411
+
1412
+
1413
+
1414
+
1415
+
1416
+
1417
+
1418
+
1419
+
1420
+
1421
+
1422
+
1423
+ ResNet50V2, EfficientNetV2M et Vit16 sous Keras
1424
+
1425
+ Pour ces 3 modèles, nous avons suivi le même plan d’entraînement suivant.
1426
+
1427
+ Phase
1428
+ d'Entraînement
1429
+
1430
+ Optimiseur
1431
+
1432
+ Scheduler de
1433
+ Learning Rate
1434
+
1435
+ Perte
1436
+
1437
+ Callbacks
1438
+
1439
+ Premier
1440
+ Entraînement
1441
+
1442
+ Adam
1443
+
1444
+ CosineDecayRestarts en
1445
+ Fine tuning
1446
+
1447
+ SparseFocalLoss
1448
+ (sans poids)
1449
+
1450
+ Deuxième
1451
+ Entraînement
1452
+ (Amélioration 1)
1453
+
1454
+ AdamW
1455
+
1456
+ CosineDecayRestarts
1457
+
1458
+ SparseFocalLoss
1459
+ (avec poids des
1460
+ classes)
1461
+
1462
+ earlystop,
1463
+ time_callback,
1464
+ printLR,
1465
+ model_checkpoint_
1466
+ callback
1467
+
1468
+ earlystop,
1469
+ time_callback,
1470
+ printLR,
1471
+ model_checkpoint_
1472
+ callback
1473
+
1474
+ Détails
1475
+ supplémentaires
1476
+
1477
+ 20 epochs max en
1478
+ transfert learning, 5
1479
+ epochs max en
1480
+ finetuning avec
1481
+ toutes les couches
1482
+ dégélées
1483
+ 20 epochs max de
1484
+ finetuning
1485
+
1486
+
1487
+
1488
+
1489
+
1490
+
1491
+
1492
+ Troisième
1493
+ Entraînement
1494
+ (Amélioration 2)
1495
+
1496
+ AdamW
1497
+
1498
+ CosineDecayRestarts
1499
+
1500
+ SparseFocalLoss
1501
+ (avec poids des
1502
+ classes)
1503
+
1504
+ earlystop,
1505
+ time_callback,
1506
+ printLR,
1507
+ model_checkpoint_
1508
+ callback
1509
+
1510
+ 20 epochs max de
1511
+ finetuning
1512
+ Augmentation
1513
+ manuelle des images
1514
+ des classes
1515
+ minoritaires sur
1516
+ Cassava +
1517
+ augmentation ciblée
1518
+ sur ces classes
1519
+
1520
+ La troisième étape s’est avérée la plus significative en matière de gain de performance, avec
1521
+ un traitement spécifique apportée à la classe “Cassava” en augmentant manuellement les
1522
+ images des classes minoritaires et en appliquant une augmentation algorithmique ciblée.
1523
+
1524
+ Les résultats du fine-tuning par modèle sont résumés dans le tableau ci-dessous, les
1525
+ deux modèles EfficientNetV2M et ViT16 se distinguant sur les classes déséquilibrées
1526
+ comme la Cassave.
1527
+
1528
+ Modèle
1529
+
1530
+ Accuracy
1531
+
1532
+ Macro F1-
1533
+ score
1534
+
1535
+ Weighted
1536
+ F1
1537
+
1538
+ Observations clés
1539
+
1540
+ ResNet50V2
1541
+
1542
+ 0.96
1543
+
1544
+ 0.96
1545
+
1546
+ 0.96
1547
+
1548
+ Bons résultats globaux, mais performance moyenne sur
1549
+ les classes Cassava
1550
+
1551
+ EfficientNetV2M
1552
+
1553
+ 0.99
1554
+
1555
+ 0.98
1556
+
1557
+ 0.99
1558
+
1559
+ Meilleure performance globale, bonne gestion des
1560
+ classes déséquilibrées comme Cassava
1561
+
1562
+ ViT16
1563
+
1564
+ 0.98
1565
+
1566
+ 0.97
1567
+
1568
+ 0.98
1569
+
1570
+ Meilleure performance globale, bonne gestion des
1571
+ classes déséquilibrées comme Cassava
1572
+
1573
+ Compte tenu du faible % de prédiction, la Cassave a fait l’objet d’un focus particulier.
1574
+ On constate que le finetuning réalisé a eu un effet spectaculaire sur la
1575
+ reconnaissance de ces classes (hausse du F1-score de 15pts environ chez
1576
+ EfficientNetV2M et ViT16) notamment sur la Cassave saine.
1577
+
1578
+
1579
+
1580
+
1581
+
1582
+
1583
+
1584
+
1585
+ S’agissant des autres classes, on relève les principaux enseignements suivants:
1586
+
1587
+ ● Raisins, cerises, agrumes, pommes, pêches, etc. (classes équilibrées) : les trois
1588
+
1589
+ modèles ont des scores F1 proches de 1.00 sur toutes ces classes : aucune distinction
1590
+ significative.
1591
+
1592
+ ● Sugarcane (classes mineures) : Bonne performance des trois modèles.
1593
+
1594
+ EfficientNetV2M excellent suivi de ViT16
1595
+
1596
+ ● Tomato (13 sous-classes, très représenté mais varié) : Bonne performance des trois
1597
+
1598
+ modèles. EfficientNetV2M excellent suivi de ViT16
1599
+
1600
+ En conclusion, suivant les critères liant métriques de précision, de temps d’apprentissage et
1601
+ de taille du modèle, EfficientNetV2M semble devoir être privilégié.
1602
+
1603
+ Critère
1604
+
1605
+ Gagnant
1606
+
1607
+ Commentaire
1608
+
1609
+ Précision globale
1610
+
1611
+ EfficientNetV2M
1612
+
1613
+ Excellent suivi de Vit16
1614
+
1615
+ Robustesse sur classes rares
1616
+
1617
+ EfficientNetV2M
1618
+
1619
+ Meilleur équilibre F1
1620
+
1621
+ Performances Cassava
1622
+
1623
+ EfficientNetV2M
1624
+
1625
+ Résiste mieux au déséquilibre
1626
+
1627
+ Simplicité et rapidité
1628
+ entraînement
1629
+
1630
+ ResNet50V2
1631
+
1632
+ Moins lourd, mais moins performant
1633
+
1634
+ Durée d’inférence
1635
+
1636
+ ResNet50V2
1637
+
1638
+ 4 fois plus rapide que EfficientNetV2M et 6 fois plus
1639
+ rapide que ViT16
1640
+
1641
+ Taille disque du modèle
1642
+
1643
+ ViT16
1644
+
1645
+ Le plus léger suivi de ResNet50V2 , EfficientNetV2M
1646
+ est deux fois plus lourd
1647
+
1648
+
1649
+
1650
+
1651
+
1652
+
1653
+ Vision Transformer pure
1654
+
1655
+ ViT16
1656
+
1657
+ Très Bon
1658
+
1659
+ Conclusion au terme de la Phase 1
1660
+
1661
+ Nous tirons de cette première phase deux enseignements:
1662
+
1663
+ ● La qualité de la précision semble souffrir de la classe Cassave : quel que soit le modèle
1664
+ employé, et malgré les efforts de fine-tuning, il semble qu’une difficulté de
1665
+ reconnaissance subsiste pour cette classe. Cette difficulté est selon intrinsèquement
1666
+ lié à la qualité des images et aux problèmes apparents de labellisation. Nous nous
1667
+ interrogeons donc sur l’abandon de cette classe dans le modèle final.
1668
+
1669
+ ● Les modèles affichent des tailles variables, certains sans doute incompatibles avec
1670
+ un usage mobile. En conséquence, nous décidons de retenir à ce stade deux modèles,
1671
+ l’un léger, embarqué sur mobile (VGG12), et l’autre plus puissant hébergé dans un
1672
+ cloud (EfficientNetV2M).
1673
+
1674
+ Phase 2
1675
+
1676
+ La deuxième phase a été consacrée à l’interprétation des modèles en utilisant des outils
1677
+ comme GradCam ou SHAP ainsi qu’à l’apprentissage, par lequel nous commençons cette
1678
+ phase, d’un modèle alternatif aux CNN et Transformer Standard : Swintransformer.
1679
+
1680
+ Swintransformer
1681
+
1682
+ Le modèle utilisé est un Swin Transformer pré-entraîné, adapté aux 55 classes du jeu de
1683
+ données incluant la Cassave:
1684
+
1685
+ ● L’entraînement a été réalisé avec un mécanisme d’early stopping qui interrompt
1686
+ l’apprentissage si la performance sur le jeu de validation ne s’améliore plus pendant
1687
+ trois époques consécutives.
1688
+
1689
+ ● L’optimiseur utilisé est AdamW, qui semble reconnu pour sa robustesse et son
1690
+
1691
+ efficacité pour ce modèle avec un learning rate de 0,0001.
1692
+
1693
+ ● Des poids de classe sont calculés en fonction de la fréquence de chaque catégorie dans
1694
+ le jeu d’entraînement. Le poids de la classe « Cassava_mosaic_disease » est
1695
+ volontairement réduit afin de limiter son influence lors de l’apprentissage. Il y a en
1696
+ effet 5 fois plus d’images de Cassaves atteintes de cette maladie que dans les autres
1697
+ classes de Cassaves.
1698
+
1699
+ ● À chaque époque, la fonction de coût utilisée est la CrossEntropyLoss pondérée par
1700
+
1701
+ ces poids de classe.
1702
+
1703
+ ● Nous retenons le modèle ayant obtenu la meilleure performance sur le jeu de
1704
+
1705
+ validation (les images du jeu de test).
1706
+
1707
+ Dans les faits, nous avons eu besoin de 6 époques pour atteindre l’optimum avec un taux
1708
+ d’accuracy de 97,72%, un macro F1-score de 96,63% et un weighted F1-score de 97,73%.
1709
+
1710
+
1711
+
1712
+
1713
+
1714
+
1715
+
1716
+
1717
+
1718
+
1719
+
1720
+ La classe Cassave reste néanmoins encore très moyennement prédite, rejoignant ainsi la
1721
+ conclusion générale que les images qui servent à l’apprentissage pour ces classes sont sans
1722
+ doute à l’origine de ce problème de classification (qualité, labellisation) : à titre d’exemple la
1723
+ classe “Cassava_healthy” affiche un F1-score de 66%.
1724
+
1725
+ Interprétation comparée MobileNetV2 et Swintranformer
1726
+
1727
+ Afin d’interpréter les modèles, nous avons utilisé GradCam pour visualiser les régions de
1728
+ l’image ayant le plus influencé la prédiction du modèle sur la base du dernier bloc du modèle.
1729
+
1730
+ Pour une image de vigne atteinte de “Black Measles”
1731
+
1732
+ Pour une image de Cassave saine (environnement végétal)
1733
+
1734
+ Pour une deuxième image de Cassave (environnement terre)
1735
+
1736
+ Sur un modèle CNN classique comme MobileNetV2, on voit clairement apparaître la plante
1737
+ sur laquelle se concentre l’algorithme, quel que soit l’environnement pour la Cassave, ou
1738
+ même une tâche révélatrice de la maladie (Black Measles) pour la feuille de vigne.
1739
+
1740
+
1741
+
1742
+
1743
+
1744
+
1745
+
1746
+
1747
+
1748
+
1749
+
1750
+
1751
+
1752
+
1753
+
1754
+
1755
+
1756
+
1757
+
1758
+
1759
+
1760
+
1761
+
1762
+
1763
+
1764
+
1765
+
1766
+
1767
+
1768
+
1769
+
1770
+
1771
+
1772
+
1773
+
1774
+ En revanche pour SwinTransformer, GradCam affiche des zones de chaleurs sous formes de
1775
+ traits verticaux plus difficile à interpréter.
1776
+
1777
+ Interprétation EfficientNetV2M
1778
+
1779
+ Le modèle EfficientNetV2M nous avait donné une accuracy globale à 0.95 après le fine
1780
+ tuning.Cependant, les résultats de la classification des images de l’espèce cassava sont très
1781
+ mauvais :
1782
+
1783
+ Nous avons donc tâché de comprendre pourquoi le modèle classifie mal en regardant plus
1784
+ en détail les images de Cassave.
1785
+
1786
+ Nous avons choisi d’utiliser la méthode de saillance native à TensorFlow, car elle est
1787
+ pleinement compatible avec notre environnement et ne présente pas de problèmes
1788
+ d’incompatibilité, ce qui facilite son intégration.
1789
+
1790
+ 1- Analyse d’un premier batch avec la carte de Saillance
1791
+
1792
+ ● Les cartes sont bien générées :
1793
+
1794
+ Les zones d’attention (en rouge/orange) sont visibles sur les images et indiquent les
1795
+ régions jugées importantes par le modèle.
1796
+
1797
+ ● Alignement avec les feuilles :
1798
+
1799
+ Les zones chaudes se trouvent souvent sur des parties pertinentes des feuilles
1800
+ (nervures, taches, contours), ce qui est encourageant.
1801
+
1802
+
1803
+
1804
+
1805
+
1806
+
1807
+
1808
+
1809
+
1810
+
1811
+
1812
+
1813
+ ● Présence de bruit parasite :
1814
+
1815
+ Dans certaines images, des zones d’attention sont visibles en dehors des feuilles,
1816
+ notamment sur l’arrière-plan ou sur d’autres objets. Cela suggère que le modèle peut
1817
+ être distrait par des éléments non pertinents.
1818
+
1819
+ ● Variabilité d’attention :
1820
+
1821
+ Le modèle ne focalise pas systématiquement sur les mêmes zones d’une image à
1822
+ l’autre, ce qui reflète à la fois une adaptation aux différences d’images et un possible
1823
+ manque de stabilité dans la reconnaissance.
1824
+
1825
+ ● Zones de saillance parfois trop petites :
1826
+
1827
+ Les régions influentes sont parfois très restreintes, ce qui peut refléter une faible
1828
+ confiance du modèle ou une difficulté à localiser les bonnes zones.
1829
+
1830
+ ● Présence de plusieurs feuilles :
1831
+
1832
+ Lorsqu’il y a plusieurs feuilles dans l’image, le modèle semble confus et a du mal à
1833
+ identifier la feuille centrale ou la plus pertinente pour la classification.
1834
+
1835
+ ● Analyse ciblée des classes mal prédites :
1836
+
1837
+ Une attention particulière sera portée sur les classes de cassave pour lesquelles le
1838
+ modèle obtient les moins bons résultats. Cela permettra d’identifier les causes des
1839
+ erreurs et d’améliorer la robustesse du modèle.
1840
+
1841
+ 2- Analyse d’un second batch sur les espèces de Cassave mal classifiées avec la carte de
1842
+ Saillance
1843
+
1844
+
1845
+
1846
+
1847
+
1848
+
1849
+
1850
+
1851
+
1852
+
1853
+
1854
+ Confirmation de l'analyse :
1855
+ L’observation globale sur les classes mal prédites confirme que le modèle ne distingue pas
1856
+ toujours correctement la feuille à analyser. Dans plusieurs cas, l’attention est
1857
+ partiellement portée sur l’arrière-plan ou sur d’autres feuilles, ce qui renforce l’idée d’une
1858
+ difficulté du modèle à isoler la feuille pertinente dans des scènes complexes.
1859
+ 3- Limites de l'interprétation avec SHAP et GradCam
1860
+
1861
+ -
1862
+
1863
+ -
1864
+
1865
+ L’utilisation de SHAP DeepExplainer a été écartée pour cette architecture, car cette
1866
+ méthode n’est pas encore compatible avec toutes les couches de TensorFlow 2,
1867
+ notamment celles présentes dans EfficientNet, comme DepthwiseConv2d et BiasAdd
1868
+ L’application de Grad-CAM a rencontré des problèmes lors de l’appel du modèle avec
1869
+ TensorFlow, qui refuse de traiter correctement les entrées. Nous suspectons une
1870
+ incompatibilité avec TensorFlow 2.19 ou un problème lié à la construction du
1871
+ modèle, rendant son utilisation impossible dans cette configuration.
1872
+
1873
+ Ces difficultés techniques rencontrées avec SHAP et Grad-CAM sont aussi intrinsèquement
1874
+ liées à la complexité et à la profondeur de notre modèle EfficientNetV2M, qui comporte des
1875
+ couches spécifiques (DepthwiseConv2d, BiasAdd) rendant son interprétation plus difficile
1876
+ avec certains outils standards.
1877
+
1878
+ Interprétation VGG16
1879
+
1880
+ Pour comprendre les décisions de notre modèle VGG16, nous allons utiliser 3 outils
1881
+ d’interprétation :
1882
+
1883
+ -
1884
+
1885
+ -
1886
+
1887
+ -
1888
+
1889
+ Saliency, qui permet de mettre en évidence les pixels les plus importants d’une
1890
+ image pour une prédiction donnée.
1891
+
1892
+ SHAP (SHapley Additive exPlanations), pour visualiser les caractéristiques qui
1893
+ permettent la prédictions d’une classe sur une image.
1894
+
1895
+ LIME (Local Interpretable Model-agnostic Explanations), qui donne les
1896
+ caractéristiques d’une image qui vont le plus influencer la décision du model.
1897
+
1898
+ Image source
1899
+
1900
+ Saliency
1901
+
1902
+ LIME
1903
+
1904
+ SHAP
1905
+
1906
+
1907
+
1908
+
1909
+
1910
+
1911
+
1912
+
1913
+
1914
+
1915
+ D’après nos outils d’interprétation, on remarque que les saillances désignent bien les parties
1916
+ des images importantes pour chacune des classes. Elle reconnaît les contours des plantes et
1917
+ les différences de couleurs issues des maladies.
1918
+
1919
+
1920
+
1921
+
1922
+
1923
+
1924
+
1925
+
1926
+
1927
+
1928
+
1929
+
1930
+
1931
+
1932
+
1933
+
1934
+
1935
+
1936
+
1937
+
1938
+
1939
+
1940
+ Sur la classe “Corn_Healthy”, on peut avoir un doute sur l’angle gauche de l’image qui est
1941
+ coloré : Est-ce que ce qui est mis en valeur est le fond noir ou le contour de la plante ? Cette
1942
+ surbrillance n’étant pas mise en valeur sur le coin bas à gauche, je pense qu’il s’agit bien du
1943
+ contour de la plante, permettant sa reconnaissance.
1944
+
1945
+ La colonne SHAP contient la classe pour laquelle l’image contient le plus de caractéristiques.
1946
+ Il confirme que notre modèle est capable de capturer les motifs et les éléments visuels
1947
+ pertinents pour effectuer des prédictions précises, étant donné qu’il s’agit à chaque fois de
1948
+ la bonne classe d’image sauf pour la classe 49 (Mosaic Virus). En analysant les graphiques sur
1949
+ cette classe, on confirme que le modèle a du mal à tirer ses caractéristiques spécifiques avec
1950
+ la classe 46.
1951
+
1952
+ Stratégies de traitement des images Cassava
1953
+
1954
+ Au vu des performances modestes obtenues par nos modèles sur le sous-ensemble Cassava,
1955
+ nous avons décidé de mettre en œuvre plusieurs stratégies d'amélioration. Ces approches
1956
+ visent à renforcer la qualité des données et à améliorer la capacité des modèles à
1957
+ discriminer les classes Cassava, souvent déséquilibrées et visuellement similaires.
1958
+
1959
+ 1. Augmentation massive des classes minoritaires
1960
+
1961
+ Une première approche a consisté à rééquilibrer le dataset Cassava par une augmentation
1962
+ ciblée.
1963
+
1964
+
1965
+
1966
+
1967
+
1968
+
1969
+
1970
+
1971
+
1972
+ Principe
1973
+
1974
+ • Les classes minoritaires (Healthy, Bacterial blight, Brown streak disease, Green mottle)
1975
+ ont été massivement augmentées.
1976
+
1977
+ • L’objectif était d’atteindre un volume comparable à la classe majoritaire (Cassava Mosaic
1978
+ Disease).
1979
+
1980
+ • Les techniques utilisées incluent : rotations, flips, changements de luminosité,
1981
+ contrastes, translations, etc.
1982
+
1983
+ Objectifs
1984
+
1985
+ • Apporter de la diversité visuelle aux classes sous-représentées.
1986
+
1987
+ • Réduire le biais induit par la classe majoritaire.
1988
+
1989
+ • Améliorer la généralisation du modèle sur les classes rares.
1990
+
1991
+ 2. Filtrage basé sur un score multi-critères
1992
+
1993
+ Une seconde approche a consisté à filtrer les images Cassava jugées peu fiables à l’aide d’un
1994
+ score multi-critères.
1995
+
1996
+ Définition du score
1997
+
1998
+ Le score est défini comme une combinaison pondérée de trois composantes :
1999
+
2000
+ • Précision locale du soft voting : probabilité que le soft voting des modèles prédit
2001
+ correctement cette image sur le dataset d'entraînement.
2002
+
2003
+ • Confiance du soft voting : probabilité moyenne attribuée à la classe majoritaire par le
2004
+ soft voting.
2005
+
2006
+ • Accord inter-modèles : mesuré par la divergence de Kullback-Leibler (KL) entre les
2007
+ distributions de sortie des différents modèles (plus la divergence est faible, plus les modèles
2008
+ sont en accord).
2009
+
2010
+ Formule du score :
2011
+
2012
+ Score = 0.5 × Précision Soft Voting + 0.3 × Confiance Soft Voting + 0.2 × (1 - Divergence KL)
2013
+
2014
+ Seuil de filtrage
2015
+ Les images sont considérées comme peu fiables lorsque leur score se situe dans le premier
2016
+ décile (les 10 % les plus faibles). Ces images ont été exclues du dataset d’entraînement.
2017
+
2018
+ 3. Relabellisation automatique basée sur le score
2019
+
2020
+ Enfin une troisième stratégie a consisté à ré-étiqueter automatiquement les images Cassava
2021
+ jugées peu fiables, plutôt que de les supprimer.
2022
+
2023
+
2024
+
2025
+
2026
+ Processus de re-labellisation
2027
+ • Les images du premier décile de score ont été re-labellisées automatiquement.
2028
+ • Le nouveau label correspond à la classe prédite par le soft voting, considérée comme
2029
+ plus fiable que le label d’origine.
2030
+ • Les autres images ont conservé leur annotation initiale.
2031
+ Objectifs
2032
+ • Corriger les labels potentiellement erronés.
2033
+ • Maintenir la taille du dataset en remplaçant les étiquettes douteuses.
2034
+ • Exploiter la confiance collective des modèles pour guider la correction.
2035
+ 4. Fine-tuning des modèles sur les nouveaux datasets
2036
+ Les datasets générés (filtré, relabellisé, augmenté) ont été utilisés pour affiner les modèles
2037
+ préalablement entraînés EfficientNetV2M, ResNet50V2 et Swintransformer. Le modèle
2038
+ Convnext étant relativement plus long à entraîner, nous avons décidé de l’exclure de cette
2039
+ étude d’amélioration.
2040
+
2041
+ Méthodologie
2042
+ • Une augmentation online (flip horizontal, variation de contraste, saturation, etc.) a été
2043
+ appliquée durant le fine-tuning.
2044
+ • Le scheduler CosineDecayRestarts a permis d’ajuster dynamiquement le taux
2045
+ d’apprentissage.
2046
+ • L’optimiseur utilisé est AdamW avec un weight decay de 1e-5.
2047
+ • La fonction de perte choisie est une SparseFocalLoss (γ = 2.0), pondérée par des poids de
2048
+ classes.
2049
+
2050
+ Objectifs
2051
+
2052
+ • Exploiter les datasets nettoyés et enrichis.
2053
+ • Adapter les modèles à une distribution de données plus fiable.
2054
+ • Mesurer directement l’impact des stratégies sur les performances, notamment sur les
2055
+ classes Cassava.
2056
+ 5. Résultats obtenus
2057
+ Les résultats suivants comparent les performances des modèles avant et après application
2058
+ des trois stratégies (filtrage, relabellisation, augmentation) sur l’ensemble des classes
2059
+ (global) et spécifiquement sur les classes Cassava.
2060
+
2061
+ Deux tableaux sont présentés :
2062
+ • Le premier montre l’évolution des performances globales.
2063
+ • Le second est centré sur les performances spécifiques aux classes Cassava.
2064
+
2065
+ Tableau 1 : Performances globales (Accuracy et F1-score)
2066
+
2067
+
2068
+
2069
+
2070
+
2071
+
2072
+ Tableau 2 : Performances sur le sous-ensemble Cassava
2073
+
2074
+ 6. Analyse des résultats
2075
+
2076
+
2077
+
2078
+
2079
+
2080
+ Stratégie 1 : Augmentation
2081
+
2082
+ • Performances globales : légère dégradation sur l’ensemble des modèles.
2083
+ • Cassava : amélioration significative du F1-score pour SwinTransformer (+8.4%) et ResNet
2084
+ (+4.3%), malgré une légère baisse d’accuracy.
2085
+
2086
+ Conclusion
2087
+
2088
+ Une stratégie efficace pour renforcer la reconnaissance des classes minoritaires avec un
2089
+ compromis acceptable sur les performances globales.
2090
+
2091
+ Stratégie 2 : Filtrage
2092
+
2093
+ • Performances globales : scores stables sur SwinTransformer et EfficientNetV2M, mais
2094
+ déclin marqué sur ResNet.
2095
+ • Cassava : amélioration du F1-score sur SwinTransformer (+5.8%), mais chute sévère sur
2096
+ ResNet (-15%).
2097
+
2098
+ Conclusion
2099
+ Une stratégie à impact variable selon les modèles ; bénéfique pour Swin, mais sensible sur
2100
+ ResNet.
2101
+
2102
+ Stratégie 3 : Relabeling
2103
+
2104
+ • Performances globales : systématiquement inférieures au baseline.
2105
+
2106
+ • Cassava : baisse significative sur tous les modèles, notamment ResNet (-
2107
+ 21.8%).
2108
+
2109
+ Conclusion
2110
+
2111
+ Une stratégie risquée sans vérification des relabels. Elle peut introduire davantage
2112
+ de bruit que de correction.
2113
+
2114
+ 7. Conclusion de l’étude d’amélioration sur Cassava
2115
+ Les différentes stratégies mises en place visaient à améliorer la classification des images du
2116
+ dataset Cassava, en ciblant notamment les classes déséquilibrées ou mal étiquetées.
2117
+ Cependant, les résultats montrent que ces méthodes ont globalement entraîné une
2118
+ dégradation des performances générales, quel que soit le modèle utilisé. La perte en
2119
+ accuracy et en F1-score est visible, particulièrement sur EfficientNetV2M, qui perd jusqu’à
2120
+ 2.3 % d’accuracy globale. Bien que certaines stratégies, comme l’augmentation massive,
2121
+ aient permis des gains localisés (notamment sur le F1-score des classes Cassava), ces
2122
+ améliorations ne compensent pas les pertes sur l’ensemble des classes. Nous décidons dans
2123
+ la suite de garder nos modèles baseline.
2124
+
2125
+
2126
+
2127
+
2128
+
2129
+
2130
+
2131
+
2132
+
2133
+
2134
+ Étude de l’ensemblage des modèles
2135
+
2136
+ Dans cette partie, nous étudions l’impact potentiel de l’ensemblage de modèles sur
2137
+ l’amélioration des performances de classification.
2138
+ Avant d’examiner les méthodes d’ensemblage, il est important de rappeler les performances
2139
+ des modèles pris individuellement dans leur configuration de base (sans stratégie
2140
+ d’amélioration) :
2141
+
2142
+ - EfficientNetV2M est le modèle ayant obtenu les meilleurs résultats globaux et sur
2143
+
2144
+ Cassava.
2145
+
2146
+ - Swin Transformer a montré de bonnes performances, notamment une meilleure
2147
+
2148
+ robustesse sur les classes minoritaires.
2149
+
2150
+ - ConvNext était le troisième meilleur modèle.
2151
+ - ResNet50V2, bien qu’un peu moins performant, a été retenu pour sa
2152
+
2153
+ complémentarité potentielle avec les autres modèles.
2154
+
2155
+ Ces performances individuelles servent de point de comparaison pour évaluer les gains
2156
+ apportés par l’ensemblage.
2157
+
2158
+ Complémentarité des modèles : corrélation des erreurs et divergence de Jensen-Shannon
2159
+
2160
+ L’ensemblage de modèles n’est pertinent que si les modèles présentent une certaine
2161
+ diversité d’erreurs. Pour cela, nous avons étudié :
2162
+
2163
+ -
2164
+
2165
+ -
2166
+
2167
+ -
2168
+
2169
+ La corrélation des erreurs de classification entre les modèles. Des erreurs faiblement
2170
+ corrélées indiquent une complémentarité exploitable.
2171
+ La divergence de Jensen-Shannon entre les distributions de probabilité prédites. Une
2172
+ divergence modérée à forte entre modèles indique une diversité de décisions,
2173
+ facteur clé pour améliorer les résultats via l’agrégation.
2174
+ La matrice de corrélation des erreurs ci-dessous illustre le degré de similarité dans les
2175
+ erreurs de prédiction commises par les différents modèles.
2176
+
2177
+ On observe que :
2178
+
2179
+ Les modèles ResNet50V2 et Swin Transformer ont une corrélation d’erreurs faible (0.31), ce
2180
+ qui indique une forte complémentarité.
2181
+
2182
+
2183
+
2184
+
2185
+
2186
+
2187
+
2188
+
2189
+
2190
+
2191
+ EfficientNetV2M et ConvNeXt présentent également une diversité modérée dans leurs
2192
+ erreurs vis-à-vis de ResNet50V2.
2193
+
2194
+ Le score le plus élevé entre deux modèles différents est celui entre Swin et ConvNeXt (0.51),
2195
+ ce qui reste suffisamment bas pour justifier un ensemblage.
2196
+
2197
+ Ces résultats confirment l’intérêt d’un ensemblage basé sur ces modèles, car la diversité des
2198
+ erreurs est un facteur favorable à l'amélioration globale des performances.
2199
+
2200
+ Pour compléter l’analyse, nous avons mesuré la divergence de Jensen-Shannon (JSD) entre
2201
+ les distributions de probabilités prédites par les différents modèles.
2202
+
2203
+ On constate que :
2204
+ Les modèles ResNet50V2 et Swin Transformer présentent la plus forte divergence (0.081),
2205
+ confirmant leur grande diversité de prédiction.
2206
+ EfficientNetV2M et Swin présentent également une divergence modérée (0.033), suggérant
2207
+ une complémentarité exploitable.
2208
+ À l’inverse, EfficientNetV2M et ConvNeXt sont plus proches (0.038), ce qui indique une
2209
+ certaine redondance dans leurs décisions.
2210
+ Ces résultats renforcent l’hypothèse selon laquelle un ensemblage de modèles hétérogènes
2211
+ (ResNet + Swin + EfficientNet) peut améliorer la robustesse des prédictions globales grâce à
2212
+ une diversité suffisante dans les sorties.
2213
+
2214
+
2215
+
2216
+
2217
+
2218
+
2219
+ Comparaison des performances des méthodes d’ensemblage
2220
+
2221
+ Nous avons exploré deux approches principales pour combiner les modèles :
2222
+ Soft Voting (vote pondéré par les probabilités) : chaque modèle contribue à la prédiction
2223
+ finale via sa distribution de probabilité. Nous avons initialement utilisé une pondération
2224
+ équivalente pour chaque modèle.
2225
+ Une étude systématique des coefficients de pondération n’a pas mis en évidence de
2226
+ combinaison significativement meilleure que l’équipondération.
2227
+ Cette méthode s’est avérée simple, stable, et a permis d’obtenir des résultats compétitifs.
2228
+ Stacking : cette approche consistait à utiliser un méta-modèle entraîné à partir des sorties
2229
+ des modèles de base.
2230
+
2231
+ Les performances obtenues avec le stacking n’ont pas surpassé celles du soft voting.En
2232
+ raison de la complexité de mise en œuvre et de l’absence de gain notable, nous avons
2233
+ décidé d’abandonner cette méthode au profit de l’agrégation simple.
2234
+
2235
+ Performances des ensembles
2236
+
2237
+
2238
+
2239
+
2240
+
2241
+
2242
+ Conclusion sur le choix des ensembles de modèles
2243
+
2244
+ Globalement, l’ensemble EfficientNetV2M + ResNet50V2 + SwinTransformer atteint les
2245
+ meilleures performances (accuracy = 0.9865, F1-score = 0.9856), surpassant tous les
2246
+ modèles individuels. Cela justifie pleinement l’intérêt du soft voting entre modèles
2247
+ complémentaires.
2248
+
2249
+ Pour les classes Cassava uniquement, l’ensemble EfficientNetV2M + ResNet50V2 se
2250
+ démarque légèrement, avec un F1-score de 0.8674. Il est suivi de très près par l’ensemble
2251
+ intégrant SwinTransformer (0.8658), puis par EfficientNetV2M seul (0.8655).
2252
+ Ces résultats montrent que :
2253
+ Ajouter SwinTransformer à l’ensemble améliore les performances globales sans dégrader la
2254
+ spécialisation sur Cassava.
2255
+
2256
+ EfficientNetV2M reste central dans tous les meilleurs ensembles : c’est le modèle le plus
2257
+ constant et performant, en global comme sur Cassava.
2258
+ ResNet50V2, bien que moins performant seul, apporte une complémentarité utile en
2259
+ ensemble, notamment sur les classes Cassava.
2260
+ Le stacking n’a pas permis d’amélioration notable par rapport au soft voting, tout en
2261
+ nécessitant une mise en œuvre plus complexe. Il a donc été écarté dans les configurations
2262
+ finales.
2263
+
2264
+ En tenant compte des contraintes pratiques de mise en œuvre de notre application
2265
+ (réduction des temps d'entraînement, coûts d'hébergement, vitesse d’inférence) nous
2266
+ avons décidé de sélectionner l’ensemble EfficientNetV2M + ResNet50V2.
2267
+
2268
+ Partie 5 : Conclusions tirées
2269
+ Difficultés rencontrées pendant le projet
2270
+
2271
+ Principal verrou scientifique rencontré
2272
+ Le principal verrou scientifique de ce projet s'est révélé être la qualité et la labellisation
2273
+ hétérogène des données d'images, particulièrement pour la classe Cassave, qui a
2274
+ systématiquement montré des performances de classification inférieures malgré les efforts
2275
+ de fine-tuning. Cette difficulté reflète un défi majeur en reconnaissance d'images agricoles :
2276
+ distinguer les symptômes subtils de maladies sur des images prises dans des conditions
2277
+ naturelles variables, avec des arrière-plans complexes et des variations d'éclairage.
2278
+ Difficultés détaillées par catégorie
2279
+
2280
+ Prévisionnel
2281
+
2282
+ • Temps de préprocessing sous-estimé : Le nettoyage et l'homogénéisation des
2283
+
2284
+ multiples datasets (fusion de bases redondantes, correction des déséquilibres entre
2285
+ classes) ont nécessité significativement plus de temps que prévu
2286
+
2287
+ • Complexité du fine-tuning : Les itérations successives d'optimisation des modèles,
2288
+
2289
+ particulièrement pour traiter les classes minoritaires comme la Cassave, ont multiplié
2290
+ les cycles de développement par 3
2291
+
2292
+
2293
+
2294
+
2295
+
2296
+
2297
+
2298
+ • Phase d'interprétation des modèles : L'utilisation d'outils comme GradCam et SHAP
2299
+ s'est révélée plus complexe techniquement qu'anticipé, avec des incompatibilités
2300
+ entre certaines architectures (EfficientNetV2M) et les outils d'explicabilité
2301
+
2302
+ Jeux de données
2303
+
2304
+ • Redondance non détectée initialement : Découverte tardive que 3 des 4 datasets
2305
+
2306
+ principaux provenaient de la même source originale, réduisant la diversité réelle des
2307
+ données
2308
+
2309
+ • Déséquilibre sévère : Surreprésentation massive des tomates (13 sous-classes)
2310
+
2311
+ créant un biais dans l'apprentissage
2312
+
2313
+ • Qualité hétérogène : Images de cassave systématiquement de qualité inférieure (flou
2314
+
2315
+ >500, contraste <2) nécessitant un pipeline de traitement spécifique
2316
+
2317
+ • Limitations de périmètre : Dataset limité à 19 espèces et 53 croisement espèces x
2318
+
2319
+ maladies alors que la flore mondiale compte 400 000 espèces, limitant l'applicabilité
2320
+ générale
2321
+
2322
+ Compétences techniques/théoriques
2323
+
2324
+ • Courbe d'apprentissage des architectures avancées : Maîtrise de modèles
2325
+
2326
+
2327
+
2328
+ complexes comme SwinTransformer et EfficientNetV2M plus longue qu'anticipé
2329
+ Interprétabilité des modèles : Compétences en explicabilité IA (SHAP, LIME,
2330
+ GradCam) acquises en cours de projet pour répondre aux exigences d'interprétation,
2331
+ parfois en avance de phase par rapport aux sprints du programme.
2332
+
2333
+ • Optimisation pour le déploiement mobile : Apprentissage des techniques de
2334
+ compression et quantification de modèles pour l'usage sur smartphone
2335
+
2336
+ Pertinence
2337
+
2338
+ ● Choix architecturaux : Nécessité de réviser l'approche initiale face aux performances
2339
+ insuffisantes sur certaines classes, menant à l'exploration de modèles alternatifs
2340
+ (SwinTransformer) ou l’utilisation de certaines images pré-retraitement (Cassave)
2341
+
2342
+ ● Métriques d'évaluation : Remise en question de l'accuracy comme métrique
2343
+
2344
+ principale face au déséquilibre des classes et utilisation du F1-score
2345
+
2346
+ ● Stratégie de données : Questionnement sur l'inclusion/exclusion de la classe Cassave
2347
+
2348
+ dans le modèle final
2349
+
2350
+ IT
2351
+
2352
+ ● Puissance computationnelle : Temps d'entraînement prohibitifs pour certains
2353
+
2354
+ modèles (EfficientNetV2M, VGG16) nécessitant l'optimisation du code et la réduction
2355
+ de la taille des images
2356
+
2357
+ ● Mémoire : Contraintes mémoire lors de l'entraînement de modèles profonds avec
2358
+
2359
+ des images haute résolution
2360
+
2361
+ ● Déploiement : Défis de compression des modèles pour un usage mobile tout en
2362
+
2363
+ préservant les performances
2364
+
2365
+
2366
+
2367
+ Autres
2368
+
2369
+
2370
+
2371
+ Incompatibilités techniques : Problèmes de compatibilité entre TensorFlow 2.19 et
2372
+ certains outils d'interprétation (SHAP DeepExplainer, GradCam)
2373
+
2374
+ ● Migration entre frameworks : Passage de FastAI vers TensorFlow pour faciliter
2375
+ l'intégration Firebase, nécessitant la ré-implémentation de certains modèles
2376
+
2377
+ Bilan
2378
+ Contribution principale dans l'atteinte des objectifs
2379
+ Notre contribution principale réside dans le développement d'une pipeline complète de
2380
+ traitement et de classification d'images de plantes intégrant :
2381
+
2382
+ 1. Système de tri et amélioration automatique de la qualité : Développement
2383
+ d'algorithmes de détection et correction du flou, luminosité et contraste
2384
+
2385
+ 2. Architecture hybride optimisée : Comparaison systématique de 6 architectures
2386
+
2387
+ différentes avec fine-tuning spécialisé
2388
+
2389
+ 3. Solution de déploiement adaptative : Proposition de deux modèles
2390
+
2391
+ complémentaires (VGG12 léger pour mobile, EfficientNetV2M puissant pour cloud)
2392
+
2393
+ Modifications depuis la dernière itération
2394
+
2395
+ Nous n’avons procédé à aucune modification. L’intégration du modèle SwinTransformer,
2396
+ atteignant 97,72% d'accuracy, a offert une alternative aux CNN traditionnels pour la
2397
+ reconnaissance de motifs complexes dans les images de plantes mais nous ne l’avons pas
2398
+ retenu compte tenu de la complexité d’interprétation avec l’outil testé (GradCam).
2399
+
2400
+ Nous avons en revanche maintenu le choix des deux modèles EfficientNetV2M et VGG12
2401
+ compte tenu de l’amélioration apportée par le fine-tuning de la classe Cassave grâce à la
2402
+ mise en place d'une augmentation de données ciblée et de pondération des classes
2403
+ permettant une amélioration de 15 points du F1-score.
2404
+
2405
+ Résultats obtenus et comparaison au benchmark
2406
+ Performances atteintes
2407
+
2408
+ ● EfficientNetV2M : 95% d'accuracy globale après fine-tuning
2409
+ ● SwinTransformer : 97,72% d'accuracy avec 96,63% de macro F1-score
2410
+ ● VGG12 : 98% d'accuracy (après exclusion de la classe Cassave)
2411
+
2412
+ Comparaison aux benchmarks de la littérature
2413
+ Bien que le nombre de classes testées soit relativement modeste, nos résultats se
2414
+ positionnent favorablement par rapport aux références que nous avons pu collecter :
2415
+
2416
+ ● PlantCLEF challenge : Evolution de 25% (2011) à 92% (2017) sur 10 000 espèces
2417
+ ● Études récentes : 96-98% d'accuracy sur datasets Plant Village
2418
+ ● Notre approche : 98% sur 19 espèces avec traitement de données hétérogènes et 53
2419
+
2420
+ classes en les croisant avec les maladies.
2421
+
2422
+
2423
+
2424
+
2425
+
2426
+ Atteinte des objectifs du projet
2427
+
2428
+ Objectif 1 : Classification des espèces (✅ Atteint)
2429
+ Accuracy de 98% pour la reconnaissance d'espèces avec VGG12 et SwinTransformer,
2430
+ dépassant l'objectif initial de 95%.
2431
+
2432
+ Objectif 2 : Détection des maladies (⚠ Partiellement atteint)
2433
+ 95% d'accuracy globale mais performances hétérogènes selon les espèces :
2434
+
2435
+ ● Excellentes : Tomates, raisins, agrumes (F1-score > 0.98)
2436
+ ● Moyennes : Cassave (F1-score : 66% pour classe saine)
2437
+ ● Limitation : Certaines maladies visuellement similaires (Mosaic Virus, Spider Mites)
2438
+
2439
+ Objectif 3 : Application Streamlit (✅ En cours)
2440
+ Développement d'une interface utilisateur fonctionnelle intégrant les modèles entraînés.
2441
+
2442
+ Processus métier d'inscription
2443
+ Notre modèle peut s'inscrire dans plusieurs processus métier :
2444
+
2445
+ Agriculture de précision
2446
+
2447
+ ● Diagnostic précoce : Détection automatisée des maladies pour intervention rapide
2448
+ ● Réduction des intrants : Ciblage précis des traitements phytosanitaires
2449
+ ● Optimisation des rendements : Prévention des pertes de récolte estimées à 20-40%
2450
+
2451
+ selon la FAO
2452
+
2453
+ Services aux professionnels
2454
+
2455
+ ● Conseil agricole : Outil d'aide au diagnostic pour conseillers et techniciens agricoles
2456
+ ● Formation : Support pédagogique pour l'apprentissage de la reconnaissance des
2457
+
2458
+ maladies
2459
+
2460
+ ● Certification : Contrôle qualité automatisé pour les filières agricoles
2461
+
2462
+ Applications grand public
2463
+
2464
+ ● Jardinage amateur : Identification et conseil pour jardiniers particuliers
2465
+ ● Éducation environnementale : Sensibilisation à la biodiversité végétale
2466
+ ● Surveillance phytosanitaire participative : Collecte de données citoyennes pour le
2467
+
2468
+ monitoring des maladies émergentes
2469
+
2470
+ Suite du projet
2471
+ Pistes d'amélioration des performances
2472
+
2473
+ Amélioration des données
2474
+
2475
+ ● Extension du dataset : Intégration de bases de données supplémentaires pour
2476
+
2477
+ couvrir plus d'espèces (objectif : passer de 19 à 100+ espèces)
2478
+
2479
+
2480
+ ● Augmentation ciblée : Techniques d'augmentation spécialisées par type de maladie
2481
+
2482
+ (GANs, style transfer)
2483
+
2484
+ ● Données multi-modales : Intégration d'informations contextuelles (géolocalisation,
2485
+
2486
+ saison, …)
2487
+
2488
+ Optimisations architecturales
2489
+
2490
+ ● Modèles hybrides : Combinaison CNN-RNN avec réseaux Liquid Time-Constant pour
2491
+
2492
+ traitement temporel
2493
+
2494
+ ● Attention mechanisms : Intégration de mécanismes d'attention pour focaliser sur les
2495
+
2496
+ zones pathologiques
2497
+
2498
+ ● Architecture adaptative : Modèles capables d'ajuster leur complexité selon la
2499
+
2500
+ puissance de calcul disponible
2501
+
2502
+ Techniques avancées
2503
+
2504
+ ● Apprentissage fédéré : Entraînement distribué préservant la confidentialité des
2505
+
2506
+ données agricoles
2507
+
2508
+ ● Few-shot learning : Reconnaissance de nouvelles maladies avec peu d'exemples
2509
+ ● Domain adaptation : Transfert de connaissances entre différentes conditions
2510
+
2511
+ climatiques et géographiques
2512
+
2513
+ Déploiement et optimisation
2514
+
2515
+ ● Quantification avancée : Techniques de compression préservant mieux les
2516
+
2517
+ performances
2518
+
2519
+ ● Edge computing : Optimisation pour calcul embarqué sur capteurs IoT agricoles
2520
+ ● Traitement en temps réel : Pipeline optimisé pour diagnostic instantané
2521
+
2522
+ Contribution à l'accroissement de la connaissance scientifique
2523
+
2524
+ Avancées méthodologiques
2525
+
2526
+ ● Pipeline de qualité d'images : Contribution à l'amélioration automatique d'images
2527
+
2528
+ agricoles en conditions naturelles
2529
+
2530
+ ● Comparaison architecturale : Étude comparative systématique de 6 architectures sur
2531
+
2532
+ données agricoles hétérogènes
2533
+
2534
+ ● Traitement des déséquilibres : Stratégies spécialisées pour classes minoritaires en
2535
+
2536
+ contexte agricole
2537
+
2538
+ Connaissances domaine-spécifiques
2539
+
2540
+ ● Variables discriminantes : Identification du niveau de bleu comme prédicteur
2541
+
2542
+ principal du caractère sain/malade (statistique t=128)
2543
+
2544
+ ● Seuils de qualité : Définition de critères quantitatifs pour la sélection d'images
2545
+
2546
+ agricoles (flou >500, contraste >2)
2547
+
2548
+ ● Analyse des échecs : Documentation des limites des approches CNN sur certaines
2549
+
2550
+ pathologies visuellement similaires
2551
+
2552
+
2553
+ Impact scientifique et sociétal
2554
+
2555
+ ● Démocratisation du diagnostic : Contribution à l'accessibilité de l'expertise
2556
+
2557
+ phytosanitaire
2558
+
2559
+ ● Recherche participative : Cadre pour l'intégration de données citoyennes dans la
2560
+
2561
+ surveillance phytosanitaire
2562
+
2563
+ Durabilité agricole : Support à la réduction de l'usage de pesticides par un diagnostic précis
2564
+
2565
+
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ streamlit
2
+ llama-cpp-python
3
+ faiss-cpu
4
+ sentence-transformers
5
+ PyMuPDF
step1_read_pdf.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import fitz
2
+ import sys
3
+ import os
4
+
5
+ def read_pdf(path):
6
+ if not os.path.exists(path):
7
+ print(f" Fichier non trouvé : {path}")
8
+ sys.exit(1)
9
+
10
+ doc = fitz.open(path)
11
+ all_text=""
12
+
13
+ for i,page in enumerate(doc):
14
+ text=page.get_text()
15
+ print(f"Page {i+1} - {len(text)} caractères")
16
+ print("-"*50)
17
+ print(text[:500]) # Affiche les 500 premiers caractères
18
+ print("\n")
19
+ all_text += text + "\n"
20
+ return all_text
21
+
22
+ if __name__ == "__main__":
23
+ if len(sys.argv) < 2:
24
+ print("❗ Utilisation : python step1_read_pdf.py chemin/vers/fichier.pdf")
25
+ sys.exit(1)
26
+
27
+ file_path = sys.argv[1]
28
+ text = read_pdf(file_path)
29
+ print(f"\n✅ Extraction terminée. {len(text)} caractères récupérés.")
step2_chunk.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+
3
+ def chunk_text(text,chunk_size=300,overlap=50):
4
+ words =text.split()
5
+ chunks=[]
6
+ i=0
7
+ while i<len(words):
8
+ chunk=words[i:i+chunk_size]
9
+ chunks.append(" ".join(chunk))
10
+ i+=chunk_size-overlap
11
+ return chunks
12
+
13
+ if __name__ =="__main__":
14
+ from step1_read_pdf import read_pdf
15
+
16
+ text=read_pdf("data/DST_Rapport_final_Reco_plant.pdf")
17
+
18
+ print(f"\n Longueur totale du texte : {len(text)} caractères")
19
+ chunks =chunk_text(text,chunk_size=300,overlap=50)
20
+ print(f"Nombre de chunks {len(chunks)}")
21
+
22
+ for i, chunk in enumerate(chunks[:3]):
23
+ print(f"\n Chunk {i+1} ({len(chunks)})")
24
+ print(chunk[:500], "..." if len(chunk)>500 else "")
step3_docling.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pickle
3
+ import faiss
4
+ import numpy as np
5
+ from pathlib import Path
6
+ from tqdm import tqdm
7
+
8
+ from docling.document_converter import DocumentConverter
9
+ from docling.chunking import HybridChunker
10
+
11
+ from llama_index.core.schema import TextNode
12
+ from llama_index.vector_stores.faiss import FaissVectorStore
13
+ from llama_index.embeddings.huggingface import HuggingFaceEmbedding
14
+ from llama_index.core import VectorStoreIndex
15
+
16
+ # 📁 Paramètres
17
+ DOCS_DIR = "data"
18
+ VECTOR_DIR = "vectordb_docling"
19
+ INDEX_FILE = os.path.join(VECTOR_DIR, "index.faiss")
20
+ CHUNKS_FILE = os.path.join(VECTOR_DIR, "chunks.pkl")
21
+ EMBEDDING_MODEL = "intfloat/multilingual-e5-base"
22
+
23
+ os.makedirs(VECTOR_DIR, exist_ok=True)
24
+
25
+ # 📥 Conversion avec Docling
26
+ print("📥 Conversion des documents avec Docling...")
27
+ converter = DocumentConverter()
28
+ dl_docs = []
29
+
30
+ for pdf_path in Path(DOCS_DIR).glob("*.pdf"):
31
+ print(f" - 📄 {pdf_path.name}")
32
+ docling_doc = converter.convert(str(pdf_path)).document
33
+ dl_docs.append(docling_doc)
34
+
35
+ # ✂️ Chunking sémantique via HybridChunker
36
+ print("✂️ Chunking intelligent avec HybridChunker (Docling)...")
37
+ chunker = HybridChunker()
38
+ text_nodes = []
39
+
40
+ for dl_doc in dl_docs:
41
+ chunks = chunker.chunk(dl_doc=dl_doc)
42
+ for chunk in chunks:
43
+ text_nodes.append(TextNode(text=chunk.text))
44
+
45
+ print(f"✅ {len(text_nodes)} chunks générés.")
46
+
47
+ # 🔢 Embedding + FAISS index
48
+ print("🔢 Génération des embeddings et indexation FAISS...")
49
+ embed_model = HuggingFaceEmbedding(model_name=EMBEDDING_MODEL)
50
+ embedding_dim = np.array(embed_model.get_query_embedding("test")).shape[0]
51
+ faiss_index = faiss.IndexFlatL2(embedding_dim)
52
+ vector_store = FaissVectorStore(faiss_index=faiss_index)
53
+
54
+ # 🧠 Construction de l’index vectoriel
55
+ index = VectorStoreIndex(text_nodes, embed_model=embed_model, vector_store=vector_store)
56
+
57
+ # 💾 Sauvegarde
58
+ print("💾 Sauvegarde de l’index et des chunks...")
59
+ faiss.write_index(faiss_index, INDEX_FILE)
60
+ chunks = [node.get_content() for node in text_nodes]
61
+
62
+ with open(CHUNKS_FILE, "wb") as f:
63
+ pickle.dump(chunks, f)
64
+
65
+ print(f"✅ {len(chunks)} chunks sauvegardés dans {CHUNKS_FILE}")
step3_embed.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sentence_transformers import SentenceTransformer
2
+ import numpy as np
3
+
4
+ EMBED_MODEL_NAME="sentence-transformers/all-MiniLM-L6-v2"
5
+ embedder=SentenceTransformer(EMBED_MODEL_NAME)
6
+
7
+ def embed_chunks(chunks):
8
+ embeddings=embedder.encode(chunks,convert_to_numpy=True,show_progress_bar=True)
9
+ return embeddings
10
+
11
+ if __name__=="__main__":
12
+ from step1_read_pdf import read_pdf
13
+ from step2_chunk import chunk_text
14
+ #Lecture du document
15
+ text=read_pdf("data/DST_Rapport_final_Reco_plant.pdf")
16
+ chunks =chunk_text(text,chunk_size=300,overlap=50)
17
+
18
+ #Embedding
19
+ embeddings=embed_chunks(chunks)
20
+
21
+ print(f"\n✅ Embeddings générés : {embeddings.shape[0]} vectors de {embeddings.shape[1]} dimensions")
22
+ print(f"Exemple (1er vecteur) :\n{embeddings[0][:5]}...")
23
+
step3_llamaindex.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pickle
3
+ import faiss
4
+ import numpy as np
5
+ from llama_index.core import SimpleDirectoryReader, VectorStoreIndex
6
+ from llama_index.core.node_parser import SentenceSplitter
7
+ from llama_index.vector_stores.faiss import FaissVectorStore
8
+ from llama_index.embeddings.huggingface import HuggingFaceEmbedding
9
+
10
+ # Paramètres
11
+ DOCS_DIR = "data"
12
+ VECTOR_DIR = "vectordb"
13
+ INDEX_FILE = os.path.join(VECTOR_DIR, "index.faiss")
14
+ CHUNKS_FILE = os.path.join(VECTOR_DIR, "chunks.pkl")
15
+ EMBEDDING_MODEL = "sentence-transformers/all-MiniLM-L6-v2"
16
+
17
+ os.makedirs(VECTOR_DIR, exist_ok=True)
18
+
19
+ # Étape 1 — Lecture
20
+ print("📥 Chargement des documents...")
21
+ documents = SimpleDirectoryReader(input_dir=DOCS_DIR).load_data()
22
+
23
+ # Étape 2 — Chunking avec overlap (512 tokens, 64 d'overlap)
24
+ print("✂️ Découpage structuré avec overlap...")
25
+
26
+ parser = SentenceSplitter(
27
+ chunk_size=512,
28
+ chunk_overlap=64,
29
+ break_on_newlines=True # 👈 Important ici
30
+ )
31
+ #parser = SentenceSplitter(chunk_size=512, chunk_overlap=64)
32
+ nodes = parser.get_nodes_from_documents(documents)
33
+
34
+ # Étape 3 — Embedding + FAISS
35
+ print("🔢 Génération des embeddings et indexation FAISS...")
36
+ embed_model = HuggingFaceEmbedding(model_name=EMBEDDING_MODEL)
37
+
38
+ # Créer un index brut FAISS
39
+ #dimension = embed_model.get_query_embedding("test").shape[0]
40
+ embedding_dim = np.array(embed_model.get_query_embedding("test")).shape[0]
41
+ faiss_index = faiss.IndexFlatL2(embedding_dim)
42
+ vector_store = FaissVectorStore(faiss_index=faiss_index)
43
+
44
+ # Création de l’index LlamaIndex avec FAISS
45
+ index = VectorStoreIndex(nodes, embed_model=embed_model, vector_store=vector_store)
46
+
47
+ # Étape 4 — Sauvegarde
48
+ print("💾 Sauvegarde de l’index et des chunks...")
49
+ #vector_store.save(INDEX_FILE)
50
+ faiss.write_index(faiss_index, INDEX_FILE)
51
+ chunks = [node.get_content() for node in nodes]
52
+ with open(CHUNKS_FILE, "wb") as f:
53
+ pickle.dump(chunks, f)
54
+
55
+ print(f"✅ {len(chunks)} chunks sauvegardés dans {CHUNKS_FILE}")
step3_llamaindex_evol.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pickle
3
+ import faiss
4
+ import numpy as np
5
+ from pathlib import Path
6
+ from tqdm import tqdm
7
+ import textwrap
8
+
9
+ from llama_index.readers.file import PDFReader
10
+ from llama_index.core.node_parser import SentenceSplitter
11
+ from llama_index.vector_stores.faiss import FaissVectorStore
12
+ from llama_index.embeddings.huggingface import HuggingFaceEmbedding
13
+ from llama_index.core import VectorStoreIndex
14
+
15
+ # 📁 Paramètres
16
+ DOCS_DIR = "data"
17
+ VECTOR_DIR = "vectordb"
18
+ INDEX_FILE = os.path.join(VECTOR_DIR, "index.faiss")
19
+ CHUNKS_FILE = os.path.join(VECTOR_DIR, "chunks.pkl")
20
+ EMBEDDING_MODEL = "dangvantuan/french-document-embedding"
21
+
22
+ os.makedirs(VECTOR_DIR, exist_ok=True)
23
+
24
+ # 📥 Chargement manuel des PDF
25
+ print("📥 Lecture des fichiers PDF...")
26
+ reader = PDFReader()
27
+ documents = []
28
+
29
+ for pdf_path in Path(DOCS_DIR).glob("*.pdf"):
30
+ print(f" - 📄 {pdf_path.name}")
31
+ docs = reader.load_data(pdf_path) # ✅ CORRECTION : path au lieu de file
32
+ documents.extend(docs)
33
+
34
+ print(f"✅ {len(documents)} documents PDF chargés.")
35
+
36
+ # ✂️ Chunking par taille de tokens (plus stable que par phrases)
37
+ print("✂️ Chunking avec SentenceSplitter (512 tokens, overlap 64)...")
38
+ parser = SentenceSplitter(chunk_size=512, chunk_overlap=64)
39
+ nodes = parser.get_nodes_from_documents(documents)
40
+
41
+ print(f"✅ {len(nodes)} chunks générés.")
42
+
43
+ # 🔍 Aperçu des 5 premiers chunks
44
+ print("\n🧩 Aperçu des 5 premiers chunks :\n")
45
+ for i, node in enumerate(nodes[:5]):
46
+ preview = textwrap.shorten(node.get_content().replace("\n", " "), width=200)
47
+ print(f"Chunk {i+1:>2}: {preview}")
48
+
49
+ # 🔢 Embedding + FAISS
50
+ print("\n🔢 Génération des embeddings et indexation FAISS...")
51
+ embed_model = HuggingFaceEmbedding(model_name=EMBEDDING_MODEL, trust_remote_code=True)
52
+ embedding_dim = np.array(embed_model.get_query_embedding("test")).shape[0]
53
+ faiss_index = faiss.IndexFlatL2(embedding_dim)
54
+ vector_store = FaissVectorStore(faiss_index=faiss_index)
55
+
56
+ # 🧠 Construction de l’index vectoriel
57
+ index = VectorStoreIndex(nodes, embed_model=embed_model, vector_store=vector_store)
58
+
59
+ # 💾 Sauvegarde
60
+ print("💾 Sauvegarde de l’index et des chunks...")
61
+ faiss.write_index(faiss_index, INDEX_FILE)
62
+ chunks = [node.get_content() for node in nodes]
63
+ with open(CHUNKS_FILE, "wb") as f:
64
+ pickle.dump(chunks, f)
65
+
66
+ print(f"\n✅ {len(chunks)} chunks sauvegardés dans {CHUNKS_FILE}")
step4_faiss.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pickle
3
+ import faiss
4
+ import numpy as np
5
+ from step3_embed import embedder
6
+
7
+ # === Chemins par défaut ===
8
+ INDEX_PATH = "vectordb/index.faiss"
9
+ CHUNKS_PATH = "vectordb/chunks.pkl"
10
+
11
+ # === Création de l'index FAISS depuis des chunks de texte ===
12
+ def create_faiss_index(chunks, index_path=INDEX_PATH, chunks_path=CHUNKS_PATH):
13
+ print("🔍 Génération des embeddings...")
14
+ embeddings = embedder.encode(chunks, convert_to_numpy=True)
15
+
16
+ print("🧠 Création de l'index FAISS...")
17
+ dimension = embeddings.shape[1]
18
+ index = faiss.IndexFlatL2(dimension)
19
+ index.add(embeddings)
20
+
21
+ print("💾 Sauvegarde de l'index et des chunks...")
22
+ faiss.write_index(index, index_path)
23
+ with open(chunks_path, "wb") as f:
24
+ pickle.dump(chunks, f)
25
+
26
+ print("✅ Index créé avec succès.")
27
+
28
+ # === Chargement de l'index FAISS + chunks ===
29
+ def load_index(index_path=INDEX_PATH, chunks_path=CHUNKS_PATH):
30
+ if not os.path.exists(index_path) or not os.path.exists(chunks_path):
31
+ raise FileNotFoundError("Index ou chunks non trouvés. Veuillez d'abord exécuter la création.")
32
+
33
+ index = faiss.read_index(index_path)
34
+ with open(chunks_path, "rb") as f:
35
+ chunks = pickle.load(f)
36
+ return index, chunks
37
+
38
+ # === Recherche dans l'index ===
39
+ def search_index(index, query_embedding, top_k=3):
40
+ D, I = index.search(query_embedding, top_k)
41
+ return I[0], D[0]
42
+
43
+
44
+ if __name__ =="__main__":
45
+ from step1_read_pdf import read_pdf
46
+ from step2_chunk import chunk_text
47
+ from step3_embed import embed_chunks
48
+ #Lecture du document
49
+ text=read_pdf("data/DST_Rapport_final_Reco_plant.pdf")
50
+ chunks =chunk_text(text,chunk_size=300,overlap=50)
51
+
52
+ #Embedding
53
+ embeddings=embed_chunks(chunks)
54
+ create_faiss_index(chunks)
step4_llamaindex.py ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import signal
3
+ import sys
4
+ import pickle
5
+ import faiss
6
+ import numpy as np
7
+ import textwrap
8
+
9
+ from llama_cpp import Llama
10
+ from llama_index.core import VectorStoreIndex
11
+ from llama_index.core.schema import TextNode
12
+ from llama_index.vector_stores.faiss import FaissVectorStore
13
+ from llama_index.embeddings.huggingface import HuggingFaceEmbedding
14
+ from sentence_transformers.util import cos_sim
15
+
16
+
17
+
18
+ MAX_TOKENS=512
19
+ mode_type=[ "docling"]
20
+ #mode_type=["sentence", "docling"]
21
+ def reformulate_question(llm, question: str) -> str:
22
+ prompt = f"""Tu es un assistant expert chargé de clarifier des questions floues.
23
+
24
+ Transforme la question suivante en une question claire, explicite et complète, sans ajouter d'informations extérieures.
25
+
26
+ Question floue : {question}
27
+ Question reformulée :"""
28
+
29
+ output = llm(prompt, max_tokens=128, stop=["\n"], stream=False)
30
+ return output["choices"][0]["text"].strip()
31
+
32
+
33
+ def reformulate_with_context_v0(llm, question: str, context_sample: str) -> str:
34
+ prompt = f"""Tu es un assistant expert qui reformule les questions utilisateur en tenant compte du contexte d'un document.
35
+
36
+ Ton objectif est de transformer une question floue, vague ou incomplète en une question claire, explicite et pertinente par rapport au contexte ci-dessous.
37
+
38
+ Contexte :
39
+ {context_sample}
40
+
41
+ Question initiale : {question}
42
+ Question reformulée :"""
43
+
44
+ output = llm(prompt, max_tokens=128, stop=["\n"], stream=False)
45
+ return output["choices"][0]["text"].strip()
46
+
47
+
48
+
49
+ def reformulate_with_context(llm, question: str, context_sample: str) -> str:
50
+ prompt = f"""Tu es un assistant expert en machine learning. Ton rôle est de reformuler les questions utilisateur en tenant compte du contexte ci-dessous, extrait d’un rapport technique sur un projet de reconnaissance de maladies de plantes.
51
+
52
+ Ta mission est de transformer une question vague ou floue en une question précise et adaptée au contenu du rapport. Ne donne pas une interprétation hors sujet. Ne reformule pas en termes de produits commerciaux.
53
+
54
+ Contexte :
55
+ {context_sample}
56
+
57
+ Question initiale : {question}
58
+ Question reformulée :"""
59
+
60
+ output = llm(prompt, max_tokens=128, stop=["\n"], stream=False)
61
+ return output["choices"][0]["text"].strip()
62
+
63
+
64
+
65
+ # 🔁 top_k adaptatif
66
+ def get_adaptive_top_k(question: str) -> int:
67
+ q = question.lower()
68
+ if len(q.split()) <= 7:
69
+ return 8
70
+ elif any(w in q for w in ["liste", "résume", "quels sont", "explique", "comment"]):
71
+ return 10
72
+ else:
73
+ return 8
74
+
75
+ def rerank_nodes(question, retrieved_nodes, embed_model, top_k=3):
76
+ print(f"\n🔍 Re-ranking des {len(retrieved_nodes)} chunks pour la question : « {question} »\n")
77
+ q_emb = embed_model.get_query_embedding(question)
78
+ scored_nodes = []
79
+
80
+ for node in retrieved_nodes:
81
+ chunk_text = node.get_content()
82
+ chunk_emb = embed_model.get_text_embedding(chunk_text)
83
+ score = cos_sim(q_emb, chunk_emb).item()
84
+ scored_nodes.append((score, node))
85
+
86
+ ranked_nodes = sorted(scored_nodes, key=lambda x: x[0], reverse=True)
87
+ print(f"📊 Top {top_k} chunks les plus pertinents :\n")
88
+ for rank, (score, node) in enumerate(ranked_nodes[:top_k], start=1):
89
+ chunk_preview = textwrap.shorten(node.get_content().replace("\n", " "), width=150)
90
+ print(f"#{rank:>2} | Score: {score:.4f} | {chunk_preview}")
91
+
92
+ return [n for _, n in ranked_nodes[:top_k]]
93
+
94
+
95
+ def ask_llm(question: str, retriever, embed_model, top_k=3) -> str:
96
+ retrieved_nodes = retriever.retrieve(question)
97
+ top_nodes = rerank_nodes(question, retrieved_nodes, embed_model, top_k)
98
+ context = "\n\n".join(n.get_content()[:500] for n in top_nodes)
99
+
100
+ prompt = f"""### Instruction: En te basant uniquement sur le contexte ci-dessous, réponds à la question de manière précise et en français.
101
+
102
+ Si la réponse ne peut pas être déduite du contexte, indique : "Information non présente dans le contexte."
103
+
104
+ Contexte :
105
+ {context}
106
+
107
+ Question : {question}
108
+ ### Réponse:"""
109
+
110
+ output = llm(prompt, max_tokens=MAX_TOKENS, stop=["### Instruction:"], stream=False)
111
+ return output["choices"][0]["text"].strip().split("###")[0]
112
+
113
+
114
+
115
+ def ask_llm_stream(question: str, retriever, embed_model, top_k=3) :
116
+ retrieved_nodes = retriever.retrieve(question)
117
+ top_nodes = rerank_nodes(question, retrieved_nodes, embed_model, top_k)
118
+ context = "\n\n".join(n.get_content()[:500] for n in top_nodes)
119
+
120
+ prompt = f"""### Instruction: En te basant uniquement sur le contexte ci-dessous, réponds à la question de manière précise et en français.
121
+
122
+ Si la réponse ne peut pas être déduite du contexte, indique : "Information non présente dans le contexte."
123
+
124
+ Contexte :
125
+ {context}
126
+
127
+ Question : {question}
128
+ ### Réponse:"""
129
+
130
+ stream = llm(prompt, max_tokens=MAX_TOKENS, stop=["### Instruction:"], stream=True)
131
+
132
+ for chunk in stream:
133
+ print(chunk["choices"][0]["text"], end="", flush=True)
134
+
135
+ return
136
+
137
+ # 📦 Chargement global une seule fois
138
+
139
+ MODEL_PATH = "models/Nous-Hermes-2-Mistral-7B-DPO.Q4_K_M.gguf"
140
+ llm = Llama(model_path=MODEL_PATH, n_ctx=2048, n_threads=4)
141
+
142
+ embed_model = HuggingFaceEmbedding(model_name="sentence-transformers/all-MiniLM-L6-v2")
143
+
144
+ INDEXES = {}
145
+
146
+ for mode in mode_type:
147
+ vectordir = f"vectordb_{mode}" if mode != "sentence" else "vectordb"
148
+ index_file = os.path.join(vectordir, "index.faiss")
149
+ chunks_file = os.path.join(vectordir, "chunks.pkl")
150
+
151
+ print(f"📂 Chargement {mode} depuis {vectordir}...")
152
+ with open(chunks_file, "rb") as f:
153
+ chunk_texts = pickle.load(f)
154
+ nodes = [TextNode(text=chunk) for chunk in chunk_texts]
155
+
156
+ faiss_index = faiss.read_index(index_file)
157
+ vector_store = FaissVectorStore(faiss_index=faiss_index)
158
+ index = VectorStoreIndex(nodes=nodes, embed_model=embed_model, vector_store=vector_store)
159
+
160
+ INDEXES[mode] = {
161
+ "nodes": nodes,
162
+ "index": index,
163
+ }
164
+
165
+
166
+ # 🧠 Interface CLI
167
+ def exit_gracefully(sig, frame):
168
+ print("\n👋 Au revoir !")
169
+ sys.exit(0)
170
+
171
+ signal.signal(signal.SIGINT, exit_gracefully)
172
+
173
+ print("🧠 RAG CLI interactif avec LlamaIndex (CTRL+C pour quitter)")
174
+
175
+ while True:
176
+ question_raw = input("\n❓> ").strip()
177
+ if not question_raw:
178
+ continue
179
+
180
+
181
+
182
+
183
+
184
+ docling_mode = input("\n⚙️ Utiliser Docling ? (o/n) : ").strip().lower()
185
+ mode = "docling" if docling_mode in ["o", "oui", "y", "yes"] else "sentence"
186
+
187
+ print(f"\n📂 Mode sélectionné : {mode}")
188
+
189
+ index_obj = INDEXES[mode]["index"]
190
+
191
+
192
+ if len(question_raw.split()) <= 3:
193
+ retriever= index_obj.as_retriever(similarity_top_k=3)
194
+ retrieved_nodes = retriever.retrieve(question_raw)
195
+ context_sample = "\n\n".join(n.get_content()[:500] for n in retrieved_nodes[:3])
196
+ reformulated = reformulate_with_context(llm, question_raw, context_sample)
197
+ else:
198
+ reformulated = reformulate_question(llm, question_raw)
199
+
200
+ print(f"📝 Question reformulée : {reformulated}")
201
+ question = reformulated
202
+
203
+ top_k = get_adaptive_top_k(question)
204
+ print(f"🔍 top_k = {top_k} adapté à la question")
205
+
206
+
207
+ retriever = index_obj.as_retriever(similarity_top_k=top_k)
208
+
209
+ # response = ask_llm(question, retriever, embed_model, top_k=top_k)
210
+ # print(f"\n💬 Réponse : {response}")
211
+
212
+ ask_llm_stream(question, retriever, embed_model, top_k=top_k)
step4b_shell.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import signal
3
+ import sys
4
+
5
+ from step4_faiss import load_index, search_index
6
+ from step3_embed import embedder
7
+ from llama_cpp import Llama
8
+
9
+ MODEL_PATH = "models/Nous-Hermes-2-Mistral-7B-DPO.Q4_K_M.gguf"
10
+ INDEX_PATH = "vectordb/index.faiss"
11
+ CHUNKS_PATH = "vectordb/chunks.pkl"
12
+
13
+ # Initialisation LLM
14
+ llm = Llama(model_path=MODEL_PATH, n_ctx=2048, n_threads=4)
15
+
16
+ # Chargement index et chunks
17
+ index, chunks = load_index(INDEX_PATH, CHUNKS_PATH)
18
+
19
+ if any("nicolas" in chunk.lower() for chunk in chunks):
20
+ print ("Nicolas est dans les chunks")
21
+ # Interruption propre
22
+ def exit_gracefully(sig, frame):
23
+ print("\n👋 Au revoir !")
24
+ sys.exit(0)
25
+
26
+ signal.signal(signal.SIGINT, exit_gracefully)
27
+
28
+ print("🧠 RAG CLI interactif (CTRL+C pour quitter)")
29
+ print("Pose ta question :")
30
+ while True:
31
+ question = input("\n❓> ").strip()
32
+ if not question:
33
+ continue
34
+ query_embedding = embedder.encode([question], convert_to_numpy=True)
35
+ indices, _ = search_index(index, query_embedding, top_k=3)
36
+ for i in indices:
37
+ print(f"\n--- Chunk {i} ---\n{chunks[i]}")
38
+ context = "\n\n".join([chunks[i] for i in indices])
39
+ MAX_CONTEXT_CHARS = 3000
40
+ truncated_context = context[:MAX_CONTEXT_CHARS]
41
+ prompt = f"""### Instruction: En te basant uniquement sur le contexte ci-dessous, réponds à la question de manière précise et en français.
42
+ Contexte :
43
+ {truncated_context}
44
+ Question : {question}
45
+ ### Réponse:"""
46
+ # output = llm(prompt, max_tokens=128, stop=["### Instruction:"])
47
+ # response = output["choices"][0]["text"].strip().split("###")[0]
48
+ # print(f"\n💬 Réponse : {response}")
tester.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ from pdfminer.high_level import extract_text
3
+
4
+ PDF_DIR = "data"
5
+ OUT_DIR = "converted_txt"
6
+ Path(OUT_DIR).mkdir(exist_ok=True)
7
+
8
+ for pdf_path in Path(PDF_DIR).glob("*.pdf"):
9
+ text = extract_text(str(pdf_path))
10
+ output_file = Path(OUT_DIR) / (pdf_path.stem + ".txt")
11
+ output_file.write_text(text, encoding="utf-8")
12
+ print(f"✅ {pdf_path.name} → {output_file.name}")