CoolFace
Apppublic

FlorianSC/agritech-interface

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
README.md1145 linesDownload Raw Back to root
1---2title: Agritech Interface3emoji: 🌾4colorFrom: green5colorTo: yellow6sdk: docker7app_port: 78608pinned: false9---10 11# Système de recommandation agricole 12## Sommaire13 141. [Présentation](#présentation)152. [Organisation](#organisation)163. [Fonctionnalités](#fonctionnalités)173. [Prérequis](#prérequis)184. [Installation](#installation)195. [Analyse exploratoire des fichiers sources](#analyse-exploratoire-des-fichiers-sources)206. [Enrichissement du dataset](#enrichissement-du-dataset)217. [Feature engineering sur le dataset enrichi](#feature-engineering-sur-le-dataset-enrichi)228. [Feature engineering sur le dataset brut](#feature-engineering-sur-le-dataset-brut)239. [Modélisation](#modélisation)2410. [Interprétabilité du modèle feature importance et SHAP values](#interprétabilité-du-modèle-feature-importance-et-shap-values)2511. [Pipeline CI CD](#pipeline-ci-cd)2612. [Tests et validation des données](#tests-et-validation-des-données)2713. [Conclusion](#conclusion)2814. [Perspectives](#perspectives)29 30## Présentation31 32Ce projet a pour but de réaliser une application web simple et intuitive pour aider les agriculteurs à prendre de meilleurs décisions.33L'application aura deux fonctions au sein de la même interface :34 351. Fonction de prédiction : Permettre à un utilisateur de sélectionner une culture spécifique, de renseigner les conditions de sa parcelle (température, usage de pesticides, etc.) et d'obtenir une estimation chiffrée du rendement attendu.36 372. Fonction de recommandation : L'utilisateur renseigne uniquement les conditions de sa parcelle, et l'application lui recommande la culture la plus rentable en simulant le rendement pour toutes les cultures possibles et en affichant un classement.38 39Nous avons eu à disposition deux datasets :40- Agriculture Crop Yield.zip41    - Fichier crop_yield.csv42- Crop Yield Prediction Dataset.zip43    - pesticides.csv44    - rainfall.csv45    - temp.csv46    - yield_df.csv47    - yield.csv48 49 50## Organisation51```52├── .github/workflows/                         # Configuration de la CI/CD53│   ├──cicd.yaml54├── data/                                      # Dossier contenant nos fichiers csv bruts et transformés55│   └── processed/                             # Création des nouveaux fichiers csv 56│       ├──yield_df_final.csv57│       ├──yield_df_enriched.csv                  58│   └── raw/                                   # Les éléments de base du projet59│       ├──crop_yield.csv60│       ├──FAOSTAT_data_en_4-6-2026.csv        # Fichier pour récupérer les régions                 61│       ├──pesticides.csv                      62│       ├──rainfall.csv                   63│       ├──temp.csv 64│       ├──UNSD — Methodology.csv              # Fichier pour récupérer les prix par type de culture65│       ├──yield.csv   66├── model/                                     # Dossier contenant le meilleur modèle retenu67├── notebooks/                                 # Notebook & dossier graph68│   ├──notebook_analyse_exploratoire.ipynb69│   ├──notebook_feature_engineering.ipynb70│   ├──notebook_feature_modelisation.ipynb71│   ├──graph72├── scripts/                                   # Scripts généraux73│   ├──config.py                         74│   ├──data_cleaning.py 75│   ├──preprocessing_pipeline.py76├── tests/                                     # Tests unitaires et fonctionnels77│   ├──test_endpoint.py                         78│   ├──test_logic.py 79│   test_simple.py80├── .env                                       # Code secret HF pas versionné 81├── .gitignore                                 # Permet de ne pas afficher les éléments sélectionnés sur GitHub82├── app.py                                     # L'application FastAPI83├── Dockerfile                                 # Description étape pour création d'une image de conteneur84├── poetry.lock                                # Pas versionné sur Git85├── pyproject.toml                             # Gestion des dépendances Poetry86├── README.md                                  # Documentation du projet87├── streamlit.py                               # Interface du projet88```89## Fonctionnalités90 91- Pipeline ML de bout en bout92- Tracking des expérimentations avec MLFlow93- API en local avec FastAPI94- Déploiement de l'interface sur Hugging Face Spaces95- Hebergement du model de ML sous Hugging Face Models96- Interface avec streamlit97- 1 fonction de prédiction et 1 fonction de recommandation98 99## Prérequis100 101- Python 3.12+102- Avoir un compte sur Hugging Face103- Token Hugging Face (se diriger vers https://huggingface.co/settings)104- Avoir le token HF sur Github et Hugging Face afin de créer le lien entre eux105 106## Installation107 1081. **Cloner le dépôt**109 110```111git clone git@github.com:SCFlorian/Systeme_recommandation_agricole.git112cd Systeme_recommandation_agricole113```114 1152. **Installez les dépendances : Le projet utilise pyproject.toml pour la gestion des dépendances :**116```117poetry install --no-root118```1193. **Ouvrir le projet dans VS Code :**120```121code .122```1234. **Configurez l’environnement Python dans VS Code**124    1.	Installez l’extension Python (si ce n’est pas déjà fait).125    2.	Appuyez sur Ctrl+Shift+P (Windows/Linux) ou Cmd+Shift+P (Mac).126    4.	Recherchez “Python: Select Interpreter”.127    5.	Sélectionnez l’environnement créé par Poetry ou celui dans lequel tu as installé le projet.128 1295. **Configurez le token Hugging Face**130 131Créez un fichier `.env` à la racine du projet avec le contenu suivant :132 133```134HF_TOKEN=votre_token_hf135```136 1376. Génération d'un modèle depuis le notebook de modélisation138    1. Enregistrement du modèle retenu avec joblib139    2. Déposez le modèle dans votre compte HF dans models140    3. Deux options pour la récupération du modèle :141        - Vous gardez le chemin de notre HF pour prendre notre meilleur modèle (chemin dans l'app)142        - Vous effectuez vos propres expérimentations dans le notebook modélisation et vous le mettez dans votre propre HF Models.143        - Vous pouvez également déployer sur votre propre HF Spaces si vous modifez le nom du Spaces pour le mettre dans votre propre compte. 1447. Génération de l'interface145    - Push sur main et le déploiement s'effectue146 147## Analyse exploratoire des fichiers sources148 149Nous avons eu à disposition deux datasets :150- Agriculture Crop Yield.zip151    - Fichier crop_yield.csv152- Crop Yield Prediction Dataset.zip153    - pesticides.csv154    - rainfall.csv155    - temp.csv156    - yield_df.csv157    - yield.csv158 159La première chose réalisée a été l'analyse exploratoire de l'ensemble des fichiers.160 161### Fichier crop_yield.csv162 163#### Description164 165On retrouve des informations importantes :166- Type de culture : riz, coton etc167- Grande région : west, south etc168- Conditions climatiques :169    - précipitation170    - température171    - nombre de jours de récolte172    - conditions météorologiques (cloudy, rainy etc)173- Type d'utilisation agricole :174    - utilisation de fertilisant175    - utilisation d'irrigation176- **Variable cible** : le rendement en tonne par hectare -> variable cible177- On retrouve 10 colonnes pour 1 million de lignes178- Le fichier semble avoir des données synthétiques179- Valeur unique par variable catégorielle :180```181Nombre de valeur unique : Soil_Type: 6182Nombre de valeur unique : Crop: 6183Nombre de valeur unique : Fertilizer_Used: 2184Nombre de valeur unique : Irrigation_Used: 2185Nombre de valeur unique : Weather_Condition: 3186```187 188La distibution de notre variable cible :189 190<img width="800" height="400" alt="Image" src="https://github.com/user-attachments/assets/cdc01b6a-ac60-4681-9b00-60ebe629978d" />191 192Notre distribution ressemble à une cloche, donc à une distribution normale même si on ne peut pas la considérer comme telle car on voit quelques petits dépassements.193 194 195#### Nettoyage196 197- Boxplot pour analyser le type de culture par rapport au rendement.198 199<img width="640" height="480" alt="Image" src="https://github.com/user-attachments/assets/b9390456-6099-4587-88f3-6fd2dcbf7d60" />200 201- On retrouve quelques valeurs aberrantes sur notre variable cible. On peut voir des rendements négatifs donc nous avons décidé de les supprimer car cela concerne uniquement 231 lignes sur les 1 million.202- Les valeurs "extrêmes" supérieures ne constituent pas d'anomalies statistiques mais une réalité du dataset.203- Afin de préparer le fichier pour l'ACP, on décide de mettre les variables **Fertilizer_Used** et **Irrigation_Used** en numérique (0 ou 1 car les valeurs étaient True or False).204 205#### Analyse des composantes principales206 207Étant donnée que nous avons beaucoup de données dans ce fichier, nous allons utiliser la méthode ACP pour nous permettre d'aller un peu plus loin dans l'analyse exploratoire.208 209- Réduction des dimensions :210 211Nos variables sont indépendantes, ce qui nous ne permet pas de réaliser une bonne réduction des dimensions. Nous avons étudié avec 5 composantes principales, elles sont autour des 20% pour chaque.212 213- Identification des variables clés :214    - **Même si l’ACP ne réduit pas beaucoup la dimension, elle reste très utile pour comprendre les relations.**215    - PC1 :216        - conditions/intensité de croissance plus fortes” vs “cycle plus long217    - PC2 :218        - PC2 est surtout un axe lié à la pluie, opposé à un bloc de variables agricoles/cycle219    - PC3 :220        - irrigation vs température221    - PC4 :222        - fertilisation et autres conditions de croissance223    - PC5 : 224        - cycle plus long et environnement plus humide225 226- Cercle de corrélation :227 228<img width="800" height="800" alt="Image" src="https://github.com/user-attachments/assets/c5fc4b07-70b3-44d4-8106-71a2384e9c99" />229 230- Les variables alignées, elles pointent dans la même direction :231    - Fertilizer_Used232    - Temperature_Celsius233    - Irrigation_Used234- Variable opposée : Days_to_Harvest est négativement correlée avec celles du dessus235    - plus d’engrais / température / irrigation = moins de jours jusqu’à récolte236- Variable isolée :237    - Rainfall : Rainfall est faiblement corrélée aux autres variables238 239- 3 dimensions réelles : intensité agricole / durée de culture / conditions climatiques240 241### Proxy242 243Un proxy est une variable qui remplace quelque chose qu'il ne peut pas être mesuré directement.244 245Variable, proxy de :246- Irrigation_Used : gestion de l’eau247- Fertilizer_Used : fertilité du sol248 249Les variables utilisées dans le modèle sont des proxies permettant d’approcher des phénomènes agronomiques complexes, tels que la disponibilité en eau ou la fertilité du sol.250 251On réalise alors que nous allons se servir des éléments que nous avons ici pour enrichir notre futur fichier pour la modélisation. Voici les éléments que nous chercherons à ajouter :252 253- Irrigation_Used254- Fertilizer_Used255- Weather_Condition256- Soil_Type257 2582. Fichiers présents dans Crop Yield Prediction Dataset259 260### Fichier pesticides.csv261 262On retrouve dans ce fichier l'utilisation en tonne de pestice par pays et par année.263 264Après analyse du fichier :265- Pas de doublons266- Pas de valeurs manquantes267- Présence de valeurs extrêmes268 269La présence de valeur extrême est expliquée par un gros écart entre les gros utilisateurs de pesticide et les petits utilisateurs.270**Le top 5 des plus gros utilisateurs de pesticide représente 66% de la valeur globale.**271 272On a analysé les pays en "écart", rien ne semble anormal, ce sont des pays qui peuvent être des gros utilisateurs.273 274**Évolution de l'utilisation des pesticides dans le temps**275 276<img width="1000" height="600" alt="Image" src="https://github.com/user-attachments/assets/e0fcb6ba-2ec4-4d83-8c8f-7b63686f2621" />277 278- Depuis les années 2000 jusqu'en 2006, on remarque une croissance de l'utilisation des pesticides de manière globale.279- Une petite en chute en 2009 avec une légère progression ensuite mais depuis 2011, l'utilisation reste constante.280 281### Fichier rainfall.csv282 283On retrouve dans ce fichier les précipitations en mm par pays et par année.284 285Après analyse du fichier :286- Pas de doublons287- Plus de 11% de valeurs manquantes dans la variable des précipitations.288- Identification de 25 pays sans valeur, sans aucune valeur par année.289```290Liste des pays avec des valeurs nulles : 291<StringArray>292[           'American Samoa',                     'Aruba',293                   'Bermuda',    'British Virgin Islands',294            'Cayman Islands',           'Channel Islands',295                   'Curacao',             'Faroe Islands',296          'French Polynesia',                 'Gibraltar',297                 'Greenland',                      'Guam',298      'Hong Kong SAR, China',               'Isle of Man',299                    'Kosovo',          'Macao SAR, China',300                    'Monaco',             'New Caledonia',301  'Northern Mariana Islands',                'San Marino',302 'Sint Maarten (Dutch part)',  'St. Martin (French part)',303                     'Tonga',  'Turks and Caicos Islands',304     'Virgin Islands (U.S.)']305Length: 25, dtype: str306 307============================308 309Liste des pays avec au moins une valeur non nulle : 310        Area  Year average_rain_fall_mm_per_year3114061  Monaco  1985                            ..312```313 314### Fichier temp.csv315 316On retrouve dans ce fichier les températures moyennes par pays et par année.317 318Après analyse du fichier :319- Doublons trouvés : il y a une répétition de plusieurs années par pays.320- 3% de données manquantes pour la variable température.321- On retrouve des dates très anciennes, à partir de 1743.322- Les valeurs de la température vont de -14 à 30 degrès.323 324### Fichier yield.csv325 326On retouve dans ce fichier un dataset central par pays, par année, par type de culture ainsi que les valeurs de rendement.327Ce fichier est central et sera donc le fichier à consolider avec les fichiers des conditions climatiques.328 329**Distribution de la variable de rendement :**330 331<img width="800" height="400" alt="Image" src="https://github.com/user-attachments/assets/2c793cd5-abe9-4cad-8d37-4197ea4ac319" />332 333On voit un étalement vers la gauche. Les données se suivent pas une distribution quasi normale comme le premier dataset. Le fichier est + déséquilibré.334 335**Boxplot par type de culture et rendement :**336 337<img width="1400" height="700" alt="Image" src="https://github.com/user-attachments/assets/e651fc71-b238-4fac-959c-d243b3d31f22" />338 339- On peut voir quelques valeurs à 0. Difficile de savoir si on les supprime ou non car théoriquement un rendement à 0 est possible si les conditions ne sont pas réunies pour une production. Mais certaines valeurs ressemblantes ont des données de rendement. Nous avons seulement 8 valeurs à 0 alors on peut les supprimer.340- On voit une valeur énorme pour Plaintains and more341    - La valeur extrême date de 1964, nous irons pas dans des dates aussi antérieures donc elle sera enlevée par défaut par la suite.342- On voit un fort déséquilibre entre les types de culture. On peut noter que la catégorie Potatoes semble avoir avoir des rendements plus élevés que les autres. Ce sont des valeurs extrêmes mais pas aberrantes car elles sont réelles alors nous devons les laisser. 343 344### Fichier yield_df.csv345 346On retouve dans ce fichier un dataset déjà consolidé entre yield et les 3 fichiers concernant les conditions météos.347 348Après analyse du fichier :349- Difficulté de savoir comment a été traité le fichier350- Pas de valeurs manquantes351- Doublons trouvés sur les températures notamment.352 353Pour une meilleure analyse, nous allons consolider un nouveau fichier yield_df car nous ne savons pas comment ce fichier a été construit.354 355### Nouveau fichier consolidé :356 357Avant de pouvoir étudier correctement les relations entre les différentes conditions météorologiques, nous devons consolider les fichiers suivants :358- yield.csv359- pesticides.csv360- rainfall.csv361- temp.csv362 363Le fichier central est yield, nous allons donc faire des jointures sur ce fichier.364Il y a plusieurs problématiques :365- Pas exactement les mêmes noms pour tous les pays366- Un nombre d'année différent entre les fichiers367- Impact potentiel, un nombre de NaN conséquent pour certains pays et certaines années.368 369Choix méthodologiques :370 371- Harmonisation des noms de pays pour assurer la compatibilité entre les différentes sources372- Restriction à la période commune (1990–2016) afin d’éviter des valeurs manquantes excessives, notamment sur les données de température et avoir des années récentes373- Fusion progressive des datasets en conservant yield.csv comme base principale374- Ajout de la région par pays afin d'avoir un détail plus fin.375- Création de variables indicatrices (région/item/condition climatique) de valeurs manquantes pour conserver l’information liée à l’absence de données --> utilisation des quartiles376- Imputation des valeurs manquantes en fonction des "bins" afin de ne pas imputer des valeurs globales qui pourraient fausser les données377- Cela va nous permettre de limiter la suppression des données378 3791. Harmonisation du nom des pays380 381- Extraction de chaque pays uniques dans les 4 fichiers.382- Envoie des pays à un LLM pour lui demander plusieurs noms possibles par pays383- Mapping des fichiers avec un nom de pays standardisé384- Identification d'un doublon supplémentaire grâce à l'harmonisation385- **TOTAL : 44 pays uniques ont été harmonisés sur l'ensemble du projet. Exemple pour un fichier :**386```387--- Rapport pour Yield ---388Nombre total de pays uniques : 212389Nombre de pays modifiés : 28390Exemples de modifications :391  - The former Yugoslav Republic of Macedonia -> North Macedonia392  - Occupied Palestinian Territory -> Palestine393  - Saint Lucia -> St. Lucia394  - China, Taiwan Province of -> Taiwan395  - Cabo Verde -> Cape Verde396  ```397 3982. Harmonisation du nom des variables et restriction de la temporalité399- Ajout de nom de variable cohérent400- Temporalité commune : 1990 -> 2016401    - Avoir en tête que le fichier temp s'arrêtait en 2013402 4033. Gestion des doublons sur le fichier temp404 405- Regroupement des pays par année et par pays en effectuant la médiane de la température406 4074. Fusion des datasets à partir de yield408- Merge des fichiers un à un409- Passage à 7 colonnes et 29 151 lignes avec des valeurs manquantes pour les conditions climatiques. Valeurs manquantes :410    - avg_temp -> 0.363521411    - pesticides_tonnes -> 0.171452412    - rainfall_mm -> 0.102261413 4145. Imputation sur les valeurs manquantes415- Ensuite nous voulons améliorer la distinction des pays alors nous avons sélectionné un dataset afin d'ajouter les grandes régions par pays416    - https://unstats.un.org/unsd/methodology/m49/overview/ : dataset sélectionné417    - Pour cela nous devons faire matcher encore une fois le noms des pays avec le dataset, nous devons modifier "à la main" 37 pays qui ne correspondaient pas418    - Exemple de région :419 420```421    Sub-region Name                  area                           422Australia and New Zealand        Australia                          189423                                 New Zealand                        108424Central Asia                     Kazakhstan                         150425                                 Kyrgyzstan                         150426                                 Tajikistan                         149427                                 Turkmenistan                       100428                                 Uzbekistan                         125429Eastern Asia                     China                              216430                                 Hong Kong                           47431                                 Japan                              189432                                 Mongolia                            54433                                 North Korea                        189434                                 South Korea                        189435                                 Taiwan                             216436```437 438- Création de groupe climatique :439    - les variables climatiques divisées en quartiles440    - puis création d'une nouvelle variable avec la région, le type de culture et le numéro de catégorie de chaque variable climatique, exemple : **Central Asia_Wheat_3_2_3**441- Imputation des NaN en fonction de la nouvelle variable442 4436. Fichier consolidé444 445**Tableau final**446```447area	     region	        year	item   avg_temp  rainfall_mm  pesticides_tonnes	 yield448Afghanistan	 Southern Asia	1990	Maize  15.45	 327.0	      1594.5	         17582449Afghanistan	 Southern Asia	1991	Maize  14.57	 327.0	      1594.5	         16800450Afghanistan	 Southern Asia	1992	Maize  14.35	 327.0	      1594.5	         15000451Afghanistan	 Southern Asia	1993	Maize  14.96	 327.0	      1594.5	         16786452Afghanistan	 Southern Asia	1994	Maize  14.94	 327.0	      1594.5	         16667453 454```455 456Cet exemple est pertinent :457 458- On voit des données de température différente par année pour un même pays : les données étaient ainsi dans le fichier temp459- La région est bien rajoutée460- Pour rainfall les données de base sont répetées par année461- Pour ce pays en particulier il n'y avait pas d'informations pour les pesticides, ces données ont été imputé462- On observe bien un rendement différent par année pour un même pays463 464**Matrice corrélation**465 466<img width="800" height="600" alt="Image" src="https://github.com/user-attachments/assets/e2b81dff-484e-46b6-94be-60a312ba165f" />467 468- On note une corrélation assez forte entre les températures moyennes et les précipitations469- Avec la valeur cible c'est la valeur des pesticides qui a un lien + fort que les autres470- Relation négative entre les températures et les pesticides ainsi qu'entre les rendements et les températures471 472### Comparaison ACP vs dataset prediction473 474L’ACP montre que la variance est répartie de manière homogène entre les composantes, ce qui indique l’absence de structure dominante et de fortes corrélations entre les variables explicatives.475La matrice de corrélation confirme ce constat, avec des coefficients globalement faibles, traduisant des relations linéaires limitées entre variable, ainsi qu’avec la variable cible.476 477## Enrichissement du dataset478 479Il n'y a de relation directe entre notre premier dataset (celui pour l'ACP) et les autres datasets.480- Le premier fichier est par grande région et culture481- Le deuxième fichier est par pays, par année puis par culture482- Le rapprochement des données serait très bancal.483 484**Mais nous avons identifié des variables proxy qui pourraient enrichir notre dataset :**485- Irrigation_Used486- Fertilizer_Used487- Weather_Condition488- Soil_Type489 490Le fichier crop_yield semble être un fichier synthétique :491- Pas de corrélation entre les variables explicatives492- Répartition à quasi 50/50 des valeurs pour chaque variable493 494Plusieurs méthodes d'enrichissement ont été effectué :495- Modèle de régression logistique afin de prédire les différentes variables sur le nouveau fichier496    - Variables explicative : précipitation et température497    - Après un test, le modèle n'arrive pas à généraliser, les variables explicatives sont indépendantes entre elles. Les données sont "plates" (sans corrélations fortes), le modèle de ML essayait de trouver une règle là où il n'y en a pas498    - Par exemple, la balanced_accuracy était à 0,50 pour le fertilisant et l'irrigation499```500============================================================501RÉSUMÉ GLOBAL502============================================================503target             accuracy   balanced_accuracy   f1_macro   log_loss504Fertilizer_Used    0.501995   0.501995            0.501987   0.693143505Irrigation_Used    0.499895   0.499747            0.489134   0.693148506Weather_Condition  0.334300   0.334245            0.333182   1.098607507Soil_Type          0.166765   0.166608            0.142119   1.791780508```509 510- Méthode de stratification par catégorie afin de faire le rapprochement sur le nouveau fichier en utilisation la valeur la plus fréquente (mode())511    - La mise en place de la stratification était simple (en quartiles)512    - Le problème est l'utilisation de la valeur fréquente. Quand il y a une valeur qui se démarque, cela fonctionne bien. Cependant sur une égalité, le mode choisit aléatoirement513- Méthode de sampling conditionnel afin d'attribuer la distribution de crop_yield par culture/clé climatique puis choix statistique de la valeur avec une fonction random514    - Méthode retenue515 516### Méthode du sampling conditionnel517 518- Standardisation des noms des types de culture entre les fichiers519- Autre problématique : nous avons uniquement 4 cultures en communs entre les 2 fichiers520 521**Méthode**522 5231. Construction des groupes524 525Les données sont segmentées selon :526- climate_key (quantiles température + pluie)527- crop (type de culture)528 5292. Calcul des distributions530 531Pour chaque variable cible et chaque groupe :532```533P(valeur | climate_key, crop)534```535 536Exemple :537```538Maize + T2_R4 → Fertilizer_Used :539True  = 70%540False = 30%541```542 5433. Imputation par sampling544 545Pour chaque valeur manquante :546- Récupération de la distribution du groupe547- Tirage aléatoire pondéré :548```549np.random.choice(values, p=probabilities)550```551 5524. Gestion des cas manquants553- crop554- climate_key555- global556 5575. Conclusion 558 559Les avantages ici sont :560- le respoect des distributions réelles561- évite les biais562- conserve la variabilité des données563 564Les limites sont :565- que c'est non déterministe566- que la cohérence individuelle n'est pas garantie567 568La méthode est validée par :569- une comapraison des distributions avant / après enrichissement570- faible écart global571- absence de biais sur les catégories572 573Exemple de comparaison par nouvelle variable :574```575=== Fertilizer_Used ===576Source (crop_yield):577Fertilizer_Used578False    0.50006579True     0.49994580Name: proportion, dtype: float64581 582Final (yield_df_final):583Fertilizer_Used584False    0.501252585True     0.498748586Name: proportion, dtype: float64587 588=== Irrigation_Used ===589Source (crop_yield):590Irrigation_Used591False    0.500509592True     0.499491593Name: proportion, dtype: float64594 595Final (yield_df_final):596Irrigation_Used597True     0.503482598False    0.496518599Name: proportion, dtype: float64600```601Exemple de comparaison par type de culture :602 603```604=== Fertilizer_Used par crop ===605                                        source     final606                     Fertilizer_Used                    607Barley               False            0.500741       NaN608                     True             0.499259       NaN609Cotton               True             0.500609       NaN610                     False            0.499391       NaN611Maize                False            0.501547  0.497063612                     True             0.498453  0.502937613Rice                 True             0.500384  0.500473614                     False            0.499616  0.499527615Soybean              False            0.500219  0.502883616                     True             0.499781  0.497117617Wheat                True             0.501155  0.501368618                     False            0.498845  0.498632619Cassava              False                 NaN  0.508120620                     True                  NaN  0.491880621Plantains and others False                 NaN  0.506292622                     True                  NaN  0.493708623Potatoes             True                  NaN  0.511170624                     False                 NaN  0.488830625Sorghum              False                 NaN  0.519462626                     True                  NaN  0.480538627```628 629## Feature engineering sur le dataset enrichi630 631Nous avons désormais consolidé notre dataset :632- Une première fois avec 3 variables climatiques puis imputer de manière rigoureuse pour les données manquantes.633- Une deuxième fois en enrichissant le dataset avec des variables approximatives qui devraient aider notre modèle à mieux généraliser634 635Nous devons maintenant continuer l'amélioration de nos données en ajoutant des données si possible,et en transformant nos données pour être compréhensible pour un modèle.636 637**Nouvelles variables**638 639```640Ratio climatique - indice d'irrigation critique :641yield_df_enriched['irrigation_impact'] = yield_df_enriched['Irrigation_Used'].astype(int) / (yield_df_enriched['rainfall_mm'] + 1)642 643Flag de sécheresse (Binaire) :644yield_df_enriched['is_drought'] = (yield_df_enriched['rainfall_mm'] < 200).astype(float)645 646Déséquilibre intrants/eau (Ecart log) :647yield_df_enriched['input_imbalance'] = np.abs(np.log1p(yield_df_enriched['pesticides_tonnes']) - np.log1p(yield_df_enriched['rainfall_mm']))648 649Stress thermique simple :650yield_df_enriched['thermal_stress'] = np.abs(yield_df_enriched['avg_temp'] - 20)651 652On fixe l'année de référence 2016 pour l'interface future :653year_ref = 2016654 655On crée un score de maturité technologique. Plus l'écart est grand, plus les semences et machines sont supposées performantes :656yield_df_enriched['years_from_now'] = year_ref - yield_df_enriched['year']657```658- Pas relation forte entre nos variables mais on voit que l'ajout des nouvelles variables ne sont pas redondantes avec les features d'origine.659 660## Feature engineering sur le dataset brut661 662**Petit rappel de la problématique sur les fichiers de ce projet. L'entreprise nous a donné 2 datasets dont un qui présente selon nous des données synthétiques (le fichier crop_yield).**663 664**Nous avons essayé de les rapprocher de la manière la plus propre possible statistiquement mais n'ayant pas la possibilité de les joindre de manière "directe" nous avons utilisé la méthode de sampling conditionnel pour rajouter les éléments qui manquaient dans notre fichier de base.**665 666**C'est pour cela que nous avons décidé de tester également le fichier brut sans les éléments rajoutés (nommés ici enrichissement) afin d'utiliser le meilleur dataset possible pour notre projet. Nous les comparerons avec des métriques ML pour choisir.**667 668Pour réaliser cela, nous devons effectuer le même feature engineering sur le fichier brut.669 670**Nouvelles variables**671 672```673Flag de sécheresse (Binaire) :674yield_df_final_conso['is_drought'] = (yield_df_final_conso['rainfall_mm'] < 200).astype(float)675 676Déséquilibre intrants/eau (Ecart log) :677yield_df_final_conso['input_imbalance'] = np.abs(np.log1p(yield_df_final_conso['pesticides_tonnes']) - np.log1p(yield_df_final_conso['rainfall_mm']))678 679Stress thermique simple :680yield_df_final_conso['thermal_stress'] = np.abs(yield_df_final_conso['avg_temp'] - 20)681 682On fixe l'année de référence 2016 pour l'interface future :683year_ref = 2016684 685On crée un score de maturité technologique. Plus l'écart est grand, plus les semences et machines sont supposées performantes :686yield_df_final_conso['years_from_now'] = year_ref - yield_df_final_conso['year']687```688 689Sans avoir enrichi notre fichier, on ne peut pas ajouter la variable irrigation_impact qui dépend de Irrigation_Used.690 691**Matrice des corrélations**692 693<img width="2277" height="1772" alt="Image" src="https://github.com/user-attachments/assets/dff6af55-5ed6-4d2f-9c80-a65fd5ed0faf" />694 695Nous n'avons pas ici des variables trop corrélées ensemble, nous n'avons pas à enlever d'autres feature.696 697 698## Modélisation699 700Nous allons passer à l'évaluation de nos 2 fichiers afin de choisir le plus pertinent pour notre modèle. Afin d'être le plus clair possible, nous nommerons les fichiers ainsi :701- **dataset brut - c'est le fichier consolidé après nettoyage & fusion des conditions climatiques**702- **dataset enrichi - c'est le fichier consolidé après nettoyage & fusion des conditions climatiques avec en + les features rajoutées lors de l'enrichissement des données**703 704Pour le suivi de la modélisation avec des pratiques de MLOps, nous utilisons **MLFlow** pour suivre les expérimentations. L'ensemble des tests ont été réalisé dans le notebook dédié à la modélisation. À l'intérieur on va retrouver plusieurs blocs :705- un suivi MLFlow de 5 modèles sur le dataset brut706- un suivi MLFlow de 5 modèles sur le dataset enrichi707- un suivi MLFlow pour l'optimisation des hyperparamètres du modèle retenu708 709### Schéma MLOPs710 711<img width="1028" height="523" alt="Image" src="https://github.com/user-attachments/assets/6ed0d34a-02ec-4e66-8bb8-ea0f8cb1d1af" />712 713### Choix des modèles714 715On a testé 5 modèles différents :716- DummyRegressor717- LinearRegression718- RandomForestRegressor719- XGBRegressor720- LGBMRegressor721 722**Pourquoi ces modèles ?**723 724- D’abord, une baseline minimale avec DummyRegressor. Le but était d’avoir un point de comparaison naïf. Ça permet de vérifier que le pipeline apprend réellement quelque chose et qu’on ne se satisfait pas d’un score “bon en apparence”.725- Ensuite, une baseline linéaire avec LinearRegression. Utilisation pour tester l’hypothèse la plus simple, si le rendement s’explique surtout par des relations linéaires entre climat, intrants et culture.726- Ensuite on a testé 3 trois familles d'arbres car le problème mélange :727    - des variables numériques comme avg_temp, rainfall_mm, pesticides_tonnes, thermal_stress etc728    - des variables catégorielles comme region, item, is_drought729    - et potentiellement des relations non linéaires et des interactions fortes entre climat, zone géographique et type de culture.730 731**Choix du pipeline**732 733- Pipeline scikit-learn : le préprocessing et le modèle sont encapsulés ensemble, donc on évite les écarts entre train et test.734- Cross-validation : les scores ne reposent pas sur un seul split.735- random_state=42 sur les modèles et le KFold : les résultats sont reproductibles.736- MLflow : chaque run conserve paramètres, métriques et version du modèle.737- Le meilleur pipeline est sauvegardé avec joblib, ce qui facilite la réutilisation et l’audit.738- Les analyses SHAP et feature importance renforcent l’explicabilité en plus de la feature importance.739- Schéma du pipeline :740 741<img width="399" height="177" alt="Image" src="https://github.com/user-attachments/assets/0a7cc810-5cae-4773-aa07-e965ed55b0e0" />742 743**Robustesse du pipeline**744- GridSearchCV(..., error_score="raise") : si un entraînement échoue, l’erreur remonte immédiatement.745- si MLflow n’est pas disponible, le tracking peut échouer.746- si un fichier CSV ou un artefact .joblib manque, le notebook s’arrête.747- les cellules SHAP dépendent du pipeline sauvegardé, donc si le modèle n’est pas exporté avant, cette partie casse.748 749**Métriques des performance des modèles**750- Coefficient de détermination (R2) : mesure la part de variance expliquée par le modèle.751- Erreur quadratique moyenne (RMSE) : mesure l'erreur moyenne en donnant plus de poids aux grosses erreurs.752- Erreur absolue moyenne (MAE) : moyenne des erreurs en valeur absolue753- Erreur relative (MAPE) : erreur en pourcentage754- Erreur économique (economic_error_usd_ha) : c'est une métrique métier personnalisée, elle convertit l'erreur de prédiction en perte financière par hectare755    - Nous avons récupéré les prix par tonne au niveau mondial pour chaque type de culture pour l'année de 2016 (dernière année de notre dataset)756 757### Résultats des performances sur le dataset brut758 759**Résumé de la première étape de modélisation**760 761Les expérimentations montrent que les modèles d’arbres surpassent nettement les baselines simples.  762Le **RandomForestRegressor** obtient les meilleures performances globales sur le dataset brut, avec un **R² test de 0,9436**.  763 764Le dataset enrichi n’a pas permis d’améliorer les performances de manière significative. Le choix final s’est donc porté sur le **dataset brut**, plus simple, plus lisible et tout aussi performant.765 766#### **Dans le détail, voici ce que nous avons fait** 767 768**Sur les 2 modèles "simples"**769- Sur le DummyRegressor et le LinearRegression les résultats ne sont pas bons, c'était attendu. Le Dummy nous sert comme base pour comparer et nous ne sommes pas face à une distribution linéaire alors LinearRegression ne généralise pas bien. Les modèles linéaires montrent leurs limites sur ce problème, ce qui confirme la présence de relations non linéaires entre les variables explicatives et le rendement.770 771- DummyRegressor :772```773=== Résultats métriques ===774CV RMSE : 7604.3730 (± 187.80)775CV MAPE  : 2.6730 (± 0.1885)776CV R2   : -0.0002 (± 0.0002)777Test RMSE : 7216.6343778Test R2   : -0.0013779Test MAPE  : 2.4448780Test economic_error_usd_ha : 1680.7060781```782- LinearRegression :783```784=== Résultats métriques ===785CV RMSE : 4840.4290 (± 55.16)786CV MAPE  : 0.9546 (± 0.0388)787CV R2   : 0.5943 (± 0.0143)788Test RMSE : 4805.9227789Test R2   : 0.5559790Test MAPE  : 0.9859791Test economic_error_usd_ha : 1033.3629792```793**Comparaison sur tous les modèles**794- Résultats des tests du R2795 796<img width="1310" height="832" alt="Image" src="https://github.com/user-attachments/assets/3033d68d-546d-49fe-9587-ca8ab035efe6" />797 798- Résultats des tests du MAPE 799 800<img width="1341" height="826" alt="Image" src="https://github.com/user-attachments/assets/519b4169-7d35-4503-bd7f-fedca414a06f" />801 802 803Les modèles d’arbres obtiennent des performances nettement supérieures aux modèles de référence.804 805Par exemple le RandomForest a "seulement" 17% d'erreur en valeur absolue, en comparaison d'une erreur sur 2 pour le LGBMRegressor.806 807 808**Petit focus sur ces 2 modèles**809 810**RandomForestRegressor**811```812=== Résultats métriques ===813CV RMSE : 1893.0226 (± 45.34)814CV MAPE  : 0.2091 (± 0.0098)815CV R2   : 0.9378 (± 0.0051)816Test RMSE : 1729.6763817Test R2   : 0.9425818Test MAPE  : 0.1739819Test economic_error_usd_ha : 273.6834820```821- Sur la validation croisée on voit que l'écart-type entre les différents folds est petit, les résultats restent stables.822- 17% d'erreur (MAPE) sur le test. Cela peut sembler haut mais il faut prendre en compte le contexte métier ici où on sait que les rendements dépendent de beaucoup de facteurs et que les prédictions sont à ajuster avec sa connsaissance terrain.823 824 825**XGBRegressor**826```827=== Résultats métriques ===828CV RMSE : 2152.0037 (± 71.11)829CV MAPE  : 0.3938 (± 0.0186)830CV R2   : 0.9195 (± 0.0082)831Test RMSE : 2040.8158832Test R2   : 0.9199833Test MAPE  : 0.3603834Test economic_error_usd_ha : 406.6547835```836- Même si les résultats ne sont pas mauvais ils restent bien en-dessous sur toutes les métriques.837 838**Analyse du MAPE par type de culture et du economic_error_usd_ha sur notre meilleur modèle**839 840- MAPE841 842<img width="349" height="400" alt="Image" src="https://github.com/user-attachments/assets/5bf7099f-2349-442f-9500-78a8a30ec41a" />843 844Le RandomForest affiche une excellente précision globale, mais l'analyse granulaire par culture via MLflow révèle des disparités intéressantes. Par exemple, le riz atteint une erreur de seulement 13%, tandis que l'igname monte à 29%. Cette différence s'explique par la plus grande variabilité biologique de certaines racines et potentiellement par un volume de données plus restreint sur ces catégories.845 846 847- Au-delà des métriques de modélisation classiques, une métrique métier a été introduite : `economic_error_usd_ha`.848 849**Calcul de cette métrique** :850 851- Calcul de l'erreur physique :852    - On calcule d'abord l'écart absolu entre la réalité et la prédiction en hectogrammes.853- Conversion en tonnes :854    - Comme les prix du marché mondial sont fixés à la tonne, on convertit l'erreur855- Valorisation monétaire :856    - On multiplie cette erreur par le prix spécifique de la culture fourni par la FAO (en USD/tonne)857 858<img width="1319" height="833" alt="Image" src="https://github.com/user-attachments/assets/65a37c5e-c33c-4e12-943b-cd97e86b97b0" />859 860Passer d'une estimation 'au doigt mouillé' (Dummy) au meilleur modèle permet de sécuriser en moyenne plus de 1000 USD par hectare en précision de trésorerie.861 862- Pour le meilleur modèle, cette erreur est estimée à **273,7 USD/ha**. Le coût n'est pas négligeable selon la taille des champs mais cela reste une estimation et elle est la plus optimisée pour le moment. 863- C’est très utile pour un exploitant agricole, parce qu’on traduit l’erreur de prédiction en impact financier moyen par hectare. Donc on peut répondre non seulement à “le modèle est-il précis ?”, mais surtout à :864    - combien coûte une mauvaise estimation de rendement865    - si une recommandation est économiquement exploitable866 867- Le Random Forest présente le meilleur compromis entre précision, stabilité et interprétabilité.868 869### Comparaison des performances des modèles sur le dataset brut et le datatset enrichi870 871 872<img width="888" height="756" alt="Image" src="https://github.com/user-attachments/assets/a977f529-68fe-459c-8c83-9cc8f20d8a60" />873 874L’objectif était d’évaluer si cet enrichissement permettait d’améliorer la capacité de généralisation des modèles.875 876Les résultats obtenus montrent toutefois que cet enrichissement n’apporte pas de gain mesurable sur les performances, et peut même légèrement dégrader certaines métriques.  877 878Ce résultat suggère que :879- soit les variables ajoutées ne contiennent pas d’information suffisamment discriminante,880- soit leur caractère indirect / approximatif limite leur contribution au modèle.881 882Le choix final s’est donc porté sur le **dataset brut**, afin de privilégier un pipeline plus simple et plus robuste.883 884### Optimisation des hyperparamètres885 886Le **RandomForestRegressor** a été retenu comme modèle final pour trois raisons principales :887 8881. Il obtient les meilleures performances globales sur le dataset consolidé.8892. Il présente une bonne stabilité en validation croisée, avec une faible variabilité entre les folds.8903. Il offre un bon niveau d’interprétabilité via les analyses de feature importance et SHAP.891 892Ce choix répond donc à un compromis équilibré entre **performance prédictive**, **robustesse** et **lisibilité métier**.893 894Une phase d’optimisation par `GridSearchCV` a été menée sur ce dernier.  895 896Les meilleurs hyperparamètres retenus sont les suivants (en comparaison avec la baseline):897 898<img width="719" height="216" alt="Image" src="https://github.com/user-attachments/assets/8a0690dd-aa8a-4216-855a-d9c1aad1a4f8" />899 900Les gains observés après optimisation restent toutefois limités.  901Ce comportement suggère que le modèle se situe déjà proche de son optimum sur les données disponibles. En conséquence, les marges de progression futures semblent davantage liées à l’enrichissement des données qu’à une optimisation algorithmique supplémentaire.902 903**Analyse du R2 et de la métrique économique pour ce modèle par type de culture :**904 905- R2 :906 907<img width="478" height="368" alt="Image" src="https://github.com/user-attachments/assets/faa95966-7fcd-43b3-b795-ca43a3208c01" />908 909-  Résultats :910    - Le modèle RandomForest s'impose comme une solution robuste avec un R2 global de 0.94, capturant une bonne partie des données.911    - Cependant, l'analyse par culture révèle une logique métier profonde, les cultures à haut rendement industriel, comme la pomme de terre ou le blé, affichent des scores d'excellence (R2>0.92 et MAPE basse), car elles répondent de manière prévisible aux intrants et au climat.912    - À l'inverse, des cultures comme l'igname présentent une complexité supérieure (R2 de 0.66 et MAPE de 0.29), soulignant une sensibilité à des facteurs non capturés. 913 914- Métrique économique :915 916<img width="480" height="361" alt="Image" src="https://github.com/user-attachments/assets/76b9fd01-e8fe-4db8-b5e5-f5510d4716a2" />917 918 919- Cultures à fort volume (ex: Potatoes) : Même si l'erreur en kg est élevée, le prix à la tonne est modéré (330 USD). L'impact financier est stable.920- Cultures à forte valeur (ex: igname) : À 890 USD/tonne, la moindre petite erreur de prédiction coûte très cher.921- L'introduction de l'Economic Error permet de traduire ces écarts en enjeux financiers réels.922- Prenons l'exemple de l'igname :923- Il est un point de vigilance économique. C'est la culture où l'erreur coûte le plus cher. Comme le prix à la tonne est très élevé, chaque tonne mal prédite par le modèle représente une perte de visibilité financière énorme (890 USD/t). C'est pour cela que même si le modèle est globalement bon, c'est sur ce genre de valeur que nous devons concentrer nos efforts pour minimiser cette 'Economic Error' et sécuriser le revenu des producteurs.924 925 926## Interprétabilité du modèle feature importance et SHAP values927 928Afin de mieux comprendre les mécanismes de prédiction du modèle retenu, deux approches complémentaires d’interprétabilité ont été utilisées :929- la feature importance native du Random Forest930- les SHAP values, qui permettent d’analyser la contribution réelle de chaque variable aux prédictions.931 932Ces deux lectures ne mesurent pas exactement la même chose :933 934- la feature importance indique quelles variables sont le plus utilisées par le modèle pour réduire l’erreur lors des splits935- les SHAP values montrent dans quel sens et avec quelle intensité chaque variable fait varier une prédiction.936 937L’intérêt de croiser les deux approches est de distinguer :938- les variables structurellement importantes pour le modèle 939- les variables qui ont l’impact le plus fort sur les prédictions individuelles.940 9411. **Feature importance globale du Random Forest**942 943- Top 15 des variables les plus importantes :944 945<img width="989" height="590" alt="Image" src="https://github.com/user-attachments/assets/df37d172-29c8-4773-9b59-95fc6276fc54" />946 947La variable la plus importante est de très loin item_Potatoes, avec un poids supérieur à 31 %. Cela signifie que le fait d’être sur la culture Potatoes structure fortement les décisions du modèle. Ce résultat est cohérent avec l’analyse exploratoire, qui montrait déjà que certaines cultures, notamment les pommes de terre, présentaient des niveaux de rendement beaucoup plus élevés que les autres.948 949On observe ensuite un second bloc de variables très influentes :950- pesticides_tonnes951- rainfall_mm952- input_imbalance953 954Ce groupe montre que le modèle ne repose pas uniquement sur le type de culture : il intègre aussi fortement les conditions agro-climatiques, les intrants.955 956Enfin, plusieurs variables de région apparaissent dans le top 15, ce qui confirme que le contexte géographique joue un rôle significatif dans l’estimation des rendements.957 9582. Importance par familles de variables959 960Pour rendre l’analyse plus lisible métier, les variables ont été regroupées en grandes familles.961 962<img width="1990" height="590" alt="Image" src="https://github.com/user-attachments/assets/21a44866-c034-463d-a03b-78c9414c1ede" />963 964- Le modèle s’appuie d’abord sur le type de culture, qui représente près de 49,4 % de l’importance totale. C’est le signal principal.965- La région pèse environ 16,6 %, ce qui confirme qu’un même type de culture ne se comporte pas de la même manière selon le contexte géographique.966- Les variables climatiques et techniques représentent également une grande importance. Cela montre que la prédiction ne dépend pas uniquement du choix de culture, mais aussi des conditions de production : pluie, température, pression d’intrants et déséquilibres entre eau et pesticides.967- Cette répartition est cohérente d’un point de vue métier :968    - la culture fixe un potentiel de rendement de base969    - le climat et les intrants modulent ce potentiel970    - la zone géographique ajoute un effet structurel supplémentaire.971 9723. Analyse des SHAP values973 974L’analyse SHAP affine cette lecture en montrant non seulement quelles variables comptent le plus, mais aussi dans quel sens elles influencent la prédiction.975 976**Variables les plus influentes selon SHAP**977Les variables ressortant le plus fortement en contribution moyenne absolue sont :978 979<img width="802" height="940" alt="Image" src="https://github.com/user-attachments/assets/e412900e-3749-4c24-b816-df77a2793923" />980 981- Les SHAP values confirment que certaines cultures déplacent fortement la prédiction :982    - item_Potatoes a l’effet positif le plus fort du modèle983    - item_Sweet potatoes, item_Cassava, item_Yams et item_Plantains and others ont également des contributions positives marquées 984    - à l’inverse, des cultures comme item_Soybean, item_Sorghum ou item_Wheat apparaissent davantage associées à des contributions négatives ou plus faibles.985    - Le modèle apprend qu’à conditions comparables, certaines cultures sont associées à des niveaux de rendement structurellement plus élevés que d’autres.986 987- Les SHAP values montrent aussi des effets géographiques différenciés :988    - region_Sub-Saharan Africa contribue fréquemment négativement aux prédictions989    - region_Western Europe, region_Western Asia, region_Northern Europe et region_Eastern Asia ont plutôt des contributions positives.990 991- Effet du climat et de l'intrant. Plusieurs variables numériques ont un rôle important :992    - pesticides_tonnes : résultat plus contrasté avec les contribuions positives et négatives plus concentrées993    - rainfall_mm : son effet est important mais dépend du contexte également994    - avg_temp : la température moyenne influence bien la prédiction, mais avec une intensité plus modérée que la pluie ou les pesticides995    - thermal_stress : un stress thermique élevé a plutôt un effet négatif996    - years_from_now : les valeurs élevées de cette variable, correspondant aux années les plus anciennes, ont tendance à tirer la prédiction vers le bas, tandis que les années plus récentes contribuent davantage positivement.997        Le modèle capte une tendance dans le temps avec l’idée d’une amélioration progressive des rendements au fil du temps, possiblement liée à l’évolution des pratiques, des intrants, des techniques ou des variétés.998 999**Regardons la contribution des SHAP Values par grande catégorie**1000- Sur nos variables numériques :1001 1002<img width="765" height="380" alt="Image" src="https://github.com/user-attachments/assets/e2b5afb8-1a51-4894-b68c-75022ada8d12" />1003 1004- Résultats :1005    - Ce graphique montre par exemple que plus la valeur des pesticides ou des précipitations augmente (points roses), plus la prédiction de rendement est poussée vers le haut. Il permet de valider que le modèle réagit de manière logique aux variations environnementales et techniques.1006    - Mais on voit une forte concentration pour ces variables vers le milieu, le contexte joue beaucoup sur la contribution de ces variables1007 1008- Sur les régions et les types de culture1009 1010**Région** 1011 1012<img width="801" height="820" alt="Image" src="https://github.com/user-attachments/assets/a7e5a95d-2ca1-4412-9f08-85a7a11a0d8f" />1013 1014**Type de culture**1015 1016<img width="778" height="540" alt="Image" src="https://github.com/user-attachments/assets/32ffade9-d66c-4423-9e9d-36791200d563" />1017 1018- Résultats :1019    - En isolant les régions ou les cultures, les graphiques prouvent que le modèle a appris des spécificités géographiques (comme l'avantage structurel de certaines régions).1020    - On voit sur le type de culture que certaines valeurs poussent largement le modèle vers le haut et d'autres clairement vers le bas.1021        - Vers le haut : pomme de terre / igname / cassava / banane / patate douce1022        - Vers le bas : soja / sorghum / blé1023    - Cela montre que le modèle sait s'adapter au contexte local plutôt que d'appliquer une règle générique à toute la planète.1024 10254. Analyse d'une prédiction avec waterfall plot1026 1027Cela part d'une prédiction moyenne du modèle sur le dataset d'entraînement, ensuite selon les contributions de certaines variables, le modèle va pousser la prédiction vers le haut ou vers le bas.1028 1029<img width="1154" height="600" alt="Image" src="https://github.com/user-attachments/assets/25a3bda6-3ae1-4ec8-9394-2b56a6633d8b" />1030 1031Dans ce cas précis on voit qu'une large partie de la contribution positive du model vient de la catégorie cassava et dans une moindre mesure la région sud-est asiatique.1032 1033## Pipeline CI CD1034 1035Ce workflow GitHub Actions automatise les tests et le déploiement de l'application AgriTech Interface vers les Hugging Face Spaces.1036 1037<img width="1166" height="462" alt="Image" src="https://github.com/user-attachments/assets/b96728bb-bc51-4593-b2df-a9e7d8ad9d0e" />1038 1039**Objectifs du workflow**1040 1041Le but est de garantir que chaque modification poussée sur la branche principale est testée et immédiatement mise en ligne, assurant ainsi une intégration et un déploiement continus (CI/CD).1042 1043**Déclencheurs (Triggers)**1044 1045Le workflow s'active automatiquement selon deux scénarios :1046- Push sur main : toute fusion ou push direct sur la branche principale.1047- Manuel : peut être lancé manuellement depuis l'onglet "Actions" de GitHub.1048 1049**Étapes du Job (build-and-deploy)**1050 1051Le job s'exécute sur un environnement ubuntu-latest et suit les étapes suivantes :1052 10531. Préparation de l'environnement1054 1055- Checkout : récupère le code source du dépôt. L'option fetch-depth: 0 est utilisée pour obtenir tout l'historique (nécessaire pour certains outils de versioning ou déploiements git spécifiques).1056 1057- Setup Python : installe Python 3.12.1058 1059- Install Poetry : installe le gestionnaire de dépendances Poetry, configure le PATH et désactive la création de venv pour utiliser l'environnement global du runner.1060 10612. Gestion des dépendances & Tests1062 1063- Install dependencies : installe les bibliothèques définies dans pyproject.toml.1064 1065- Run Unit Tests :1066    - Installe pytest et httpx.1067    - Définit le PYTHONPATH pour inclure le répertoire racine.1068    - Exécute les tests situés dans le dossier tests/. Si les tests échouent, le déploiement est annulé.1069 10703. Déploiement (Hugging Face Spaces)1071 1072Push to Hugging Face :1073 1074- Ajoute le dépôt distant Hugging Face via HTTPS en utilisant un token d'authentification.1075- Force le push de la branche main locale vers le Space Hugging Face.1076 1077Détection automatique du docker par Hugging Face Spaces :1078- il voit le Dockerfile1079- il va lire et reconstruite chaque ligne du Dockerfile1080- Une fois l'image construite -> interface Streamlit dans le Space1081 1082**Configuration Requise (Secrets)**1083 1084Pour que ce workflow fonctionne, vous devez configurer le secret suivant dans les paramètres de votre dépôt GitHub (Settings > Secrets and variables > Actions)1085 1086**Notes Techniques**1087 1088- Hébergement cible : huggingface.co/spaces/FLORIANSC/agritech-interface1089 1090- Forçage du Push : le workflow utilise git push --force. Cela signifie que l'historique sur Hugging Face sera écrasé par celui de GitHub à chaque déploiement.1091 1092- Optimisation : les dépendances sont installées sans interaction (--no-interaction) pour éviter que le runner ne reste bloqué sur une question.1093 1094## Tests et validation des données1095 1096La fiabilité du système repose sur deux piliers : la validation stricte des entrées avec Pydantic et une suite de tests automatisés intégrée au cycle CI/CD.1097 10981. Validation de données avec Pydantic1099 1100- Pour garantir l'intégrité des prédictions, l'API utilise des schémas Pydantic (InputPrediction et InputRecommendation).1101- Validation d'entrée : Chaque requête est vérifiée en temps réel. Si un utilisateur envoie une chaîne de caractères au lieu d'un nombre pour la température, l'API rejette la requête proprement avec une erreur 422 Unprocessable Entity.1102- Documentation auto-générée : Grâce aux Field et json_schema_extra.1103 11042. Suite de tests (Pytest)1105 1106Le projet inclut une batterie de tests unitaires et d'intégration pour assurer la stabilité du code :1107 1108- Tests d'API (Integration Tests) :1109    - test_predict_endpoint & test_recommend_ok : vérifient que les prédictions et recommandations renvoient des résultats cohérents et un code HTTP 200.1110    - test_404_handler & test_predict_validation_error : assurent que l'API gère les erreurs1111 1112- Tests de nettoyage (Unit Tests) :1113 1114    - test_preparation_inference_columns : Vérifie que le script de nettoyage transforme correctement les données brutes et génère bien les colonnes calculées. Pour que le pipeline de données est identique entre l'entraînement et l'inférence.1115    - Intégrité CI/CD : un test de base (test_ci_cd_pipeline) valide le bon fonctionnement du moteur de test dans le pipeline GitHub Actions.1116 11173. Couverture de code (Pytest-Cov)1118 1119- Le projet intègre pytest-cov dans le pipeline CI/CD. À chaque mise à jour :1120    - Les tests sont exécutés.1121    - Un rapport de couverture (term-missing) est généré, identifiant précisément les lignes de code non testées.1122    - Le déploiement vers Hugging Face est bloqué si les tests échouent, garantissant une version de production toujours fonctionnelle.1123 1124## Conclusion 1125 1126Ce projet démontre qu’un pipeline MLOps structuré permet de transformer des données agricoles disparates en un outil d’aide à la décision performant. Le modèle Random Forest, avec un R2 global de 0.94, ne se contente pas de prédire des rendements, il capture les dynamiques complexes entre climat, géographie et techniques agricoles.1127 1128En traduisant l’erreur statistique en un risque financier en USD/ha, nous sortons du cadre purement mathématique pour parler le langage de l'agriculteur. Le projet prouve ainsi sa valeur ajoutée :1129- réduire l’incertitude de trésorerie de plus de 75 % par rapport à une approche statistique classique (Baseline)1130- sécurisant particulièrement les cultures à haute valeur ajoutée comme l'igname, où l'enjeu financier par tonne est le plus critique.1131- grâce à l’interprétabilité SHAP, on est capable de justifier chaque prédiction.1132 1133## Perspectives1134 1135Pour aller plus loin nous aurons besoin de pouvoir enrichir nos données de manière plus précise. Actuellement le dataset enrichi n'est pas utilisé car les variables rajoutées n'apportent rien au modèle. Nous avons donc besoin :1136 1137- Enrichissement du feature engineering :1138    - Intégrer la composition des sols (pH, nutriments) pour affiner les prédictions certaines cultures qui affichent actuellement une variance plus complexe à expliquer.1139    - Coupler l'API avec des données de télédétection pour monitorer l'état des cultures en temps réel et ajuster les prédictions en cours de saison.1140    - Coupler également avec une API pour avoir des données de pluviométrie en direct1141- Optimisation de l'infrastructure MLOps :1142    - Mettre en place des "Model Drift Alarms" dans MLflow pour déclencher un réentraînement automatique du modèle dès que les conditions climatiques mondiales dérivent trop des données historiques.1143- Expansion de la valeur métier :1144    - Intégration des prix locaux : connecter l'API à des flux de prix régionaux en temps réel pour affiner la métrique économique en fonction des marchés locaux plutôt que des moyennes mondiales de la FAO.1145