Extraction des données de formation de l’ODC#
Produits utilisés : gm_s2_annual
Mots clés données utilisées ; sentinel-2 geomedian, index:données utilisées ; MADs, méthodes de données ; apprentissage automatique
Aperçu#
Les données d’entraînement constituent la partie la plus importante de tout flux de travail d’apprentissage automatique supervisé. La qualité des données d’entraînement a un impact plus important sur la classification que l’algorithme utilisé. Il est préférable d’avoir des ensembles de données d’entraînement volumineux et précis : l’augmentation de la taille de l’échantillon d’entraînement entraîne une précision de classification accrue (Maxell et al 2018). Une revue des méthodes de données d’entraînement dans le contexte de l’observation de la Terre est disponible ici
Lors de la création d’étiquettes d’apprentissage, veillez à capturer la variabilité spectrale de la classe et à utiliser des images de la période que vous souhaitez classer (plutôt que de vous fier aux composites de la carte de base). Un autre problème courant avec les données d’apprentissage est le déséquilibre des classes. Cela peut se produire lorsqu’une de vos classes est relativement rare et que, par conséquent, la classe rare constituera une plus petite proportion de l’ensemble d’apprentissage. Lorsque des données déséquilibrées sont utilisées, il est courant que la classification finale sous-estime les classes moins abondantes par rapport à leur proportion réelle.
Il existe de nombreuses plateformes permettant de collecter des étiquettes d’apprentissage. La meilleure à utiliser dépend de votre application. Les plateformes SIG sont idéales pour la collecte de données d’apprentissage car ce sont des plateformes très flexibles et matures ; Geo-Wiki et Collect Earth Online sont deux sites Web open source qui peuvent également être utiles en fonction de la stratégie de données de référence employée. Alternativement, il existe de nombreux ensembles de données d’apprentissage préexistants sur le Web qui peuvent être utiles, par exemple Radiant Earth gère un nombre croissant d’ensembles de données de référence pouvant être utilisés par tous.
Description#
Ce bloc-notes va extraire les données d’entraînement (couches d’entités) du « open-data-cube » en utilisant des géométries dans un geojson. L’exemple par défaut utilisera les étiquettes crop/non-crop dans le fichier « data/crop_training_egypt.geojson ».
Pour ce faire, nous nous appuyons sur une fonction personnalisée deafrica-sandbox-notebooks appelée collect_training_data, contenue dans le script deafrica_tools.classification. L’objectif principal de ce bloc-notes est de familiariser les utilisateurs avec cette fonction afin qu’ils puissent extraire les données appropriées à leur cas d’utilisation. L’exemple par défaut met également en évidence l’extraction d’un ensemble de couches d’entités utiles pour générer un masque de terres cultivées pour l’Égypte.
Prévisualisez les polygones de nos données d’entraînement en les traçant sur une carte de base
Définir une fonction de couche d’entités à transmettre à « collect_training_data »
Extraire les données de formation du datacube à l’aide de « collect_training_data »
Exporter les données de formation sur le disque pour les utiliser dans les scripts ultérieurs
Commencer#
Pour exécuter cette analyse, exécutez toutes les cellules du bloc-notes, en commençant par la cellule « Charger les packages ».
Charger des paquets#
[1]:
%matplotlib inline
import os
import datacube
import numpy as np
import xarray as xr
import subprocess as sp
import geopandas as gpd
from odc.io.cgroups import get_cpu_quota
from odc.geo.xr import assign_crs
from deafrica_tools.plotting import map_shapefile
from deafrica_tools.bandindices import calculate_indices
from deafrica_tools.classification import collect_training_data
Paramètres d’analyse#
path: le chemin d’accès au fichier vectoriel d’entrée à partir duquel nous allons extraire les données d’entraînement. Un geojson par défaut est fourni.field: Il s’agit du nom de la colonne dans votre table d’attributs de shapefile qui contient les étiquettes de classe. Les étiquettes de classe doivent être des entiers
[2]:
path = 'data/crop_training_egypt.geojson'
field = 'class'
Trouver le nombre de CPU#
[3]:
quota = get_cpu_quota()
ncpus = int(quota) if quota is not None else os.cpu_count() or 1
print('ncpus = '+str(ncpus))
ncpus = 4
Aperçu des données d’entrée#
Nous pouvons charger et prévisualiser notre fichier de formes de données d’entrée en utilisant « geopandas ». Le fichier de formes doit contenir une colonne avec des étiquettes de classe (par exemple, « classe »). Ces étiquettes seront utilisées pour entraîner notre modèle.
N’oubliez pas que les étiquettes de classe doivent être représentées par des « entiers ».
[4]:
# Load input data shapefile
input_data = gpd.read_file(path)
# Transform the class column datatype to int.
input_data[field] = input_data[field].astype(int)
# Plot first five rows
input_data.head()
[4]:
| class | geometry | |
|---|---|---|
| 0 | 0 | POLYGON ((26.19189 22.06193, 26.1923 22.06193,... |
| 1 | 0 | POLYGON ((32.24947 22.07338, 32.24989 22.07338... |
| 2 | 0 | POLYGON ((32.62301 22.15862, 32.62342 22.15862... |
| 3 | 0 | POLYGON ((28.35345 22.29337, 28.35386 22.29337... |
| 4 | 0 | POLYGON ((27.72311 22.83994, 27.72352 22.83994... |
[5]:
# Plot training data in an interactive map
map_shapefile(input_data, attribute=field)
Extraction des données de formation#
La fonction « collect_training_data » prend notre geojson contenant des étiquettes de classe et extrait les données d’entraînement (fonctionnalités) du datacube sur les emplacements spécifiés par les géométries d’entrée. La fonction prétraitera également nos données d’entraînement en empilant les tableaux dans un format utile et en supprimant toutes les valeurs « NaN » ou « inf ».
Les variables ci-dessous peuvent être définies dans la fonction « collect_training_data » :
zonal_stats: une chaîne facultative donnant les noms des statistiques zonales à calculer sur chaque polygone (si les géométries dans le fichier vectoriel sont des polygones et non des points). La valeur par défaut est None (toutes les valeurs de pixels sont renvoyées). Les valeurs prises en charge sont « mean », « median », « max » et « min ».
En plus du paramètre « zonal_stats », nous devons également configurer un dictionnaire de requêtes Datacube pour la requête Open Data Cube, comme « mesures » (les bandes à charger à partir du satellite), la « résolution » (la taille de la cellule) et « output_crs » (la projection de sortie). Ces options seront ajoutées à un dictionnaire « query » qui sera transmis à « collect_training_data » à l’aide du paramètre « collect_training_data(dc_query=query, …) ». Le dictionnaire de requêtes sera le seul argument de la fonction de couche d’entités que nous définirons et décrirons dans un instant.
Remarque : « collect_training_data » comporte également un certain nombre de paramètres supplémentaires pour gérer les échecs de lecture d’E/S ODC, où les polygones qui renvoient un nombre excessif de valeurs nulles peuvent être renvoyés à la file d’attente de multitraitement. Consultez les « docs <digitalearthafrica/deafrica-sandbox-notebooks> »__ pour en savoir plus.
[6]:
#set up our inputs to collect_training_data
zonal_stats = 'mean'
# Set up the inputs for the ODC query
time = ('2019')
measurements = ['blue','green','red','nir','swir_1','swir_2','red_edge_1',
'red_edge_2', 'red_edge_3', 'BCMAD', 'EMAD', 'SMAD']
resolution = (-20,20)
output_crs='epsg:6933'
Générez un objet de requête Datacube à partir des paramètres ci-dessus :
[7]:
query = {
'time': time,
'measurements': measurements,
'resolution': resolution,
'output_crs': output_crs
}
Définition des couches d’entités#
Pour créer les couches d’entités souhaitées, nous transmettons des instructions à « collect_training_data » via le paramètre « feature_func ».
feature_func: une fonction permettant de générer des couches d’entités qui est appliquée aux données dans les limites de la géométrie d’entrée.feature_funcdoit accepter un dictionnairedc_queryet renvoyer un seulxarray.Datasetouxarray.DataArraycontenant des coordonnées 2D (c’est-à-dire x, y - aucune dimension temporelle). p.ex.def feature_function(query): dc = datacube.Datacube(app='feature_layers') ds = dc.load(**query) ds = ds.mean('time') return ds
Ci-dessous, nous allons définir une fonction de couche d’entités plus complexe que le bref exemple présenté ci-dessus. Nous allons calculer certains indices de bande sur le Sentinel-2 geoMAD et ajouter un ensemble de données de pente.
[8]:
from datacube.testutils.io import rio_slurp_xarray
def feature_layers(query):
#connect to the datacube
dc = datacube.Datacube(app='feature_layers')
#load s2 annual geomedian
ds = dc.load(product='gm_s2_annual',
**query)
#calculate some band indices
da = calculate_indices(ds,
index=['NDVI', 'LAI', 'MNDWI'],
drop=False,
satellite_mission='s2')
#add slope dataset
url_slope = "https://deafrica-input-datasets.s3.af-south-1.amazonaws.com/srtm_dem/srtm_africa_slope.tif"
slope = rio_slurp_xarray(url_slope, geobox=ds.odc.geobox)
slope = slope.to_dataset(name='slope')
#merge results into single dataset
result = xr.merge([da, slope],compat='override')
return result.squeeze()
Exécutons maintenant la fonction « collect_training_data ».
Remarque : avec la classification supervisée, il est courant d’avoir de très nombreuses géométries étiquetées dans les données d’entraînement.
collect_training_datapeut paralléliser les géométries afin d’accélérer l’extraction des données d’entraînement. Le réglage dencpus>1déclenchera automatiquement la parallélisation. Cependant, il est préférable de définirncpus=1pour commencer afin de faciliter le débogage avant de déclencher la parallélisation. Vous pouvez également limiter le nombre de polygones à exécuter lors de la vérification du code. Par exemple, le passage degdf=input_data[0:5]exécutera uniquement le code sur les 5 premiers polygones.
[9]:
column_names, model_input = collect_training_data(
gdf=input_data,
dc_query=query,
ncpus=ncpus,
field=field,
zonal_stats=zonal_stats,
feature_func=feature_layers
)
Taking zonal statistic: mean
Collecting training data in parallel mode
Percentage of possible fails after run 1 = 0.0 %
Removed 0 rows wth NaNs &/or Infs
Output shape: (156, 17)
La fonction renvoie une liste (column_names) contenant une liste des noms des couches d’entités que nous avons calculées :
[10]:
print(column_names)
['class', 'blue', 'green', 'red', 'nir', 'swir_1', 'swir_2', 'red_edge_1', 'red_edge_2', 'red_edge_3', 'BCMAD', 'EMAD', 'SMAD', 'NDVI', 'LAI', 'MNDWI', 'slope']
Le deuxième objet renvoyé par la fonction est un numpy.array (model_input) et contient les données de nos géométries étiquetées. Le premier élément du tableau est l’entier de classe (par exemple, dans l’exemple par défaut, 1. “crop” ou 0. “noncrop”), le deuxième ensemble d’éléments correspond aux valeurs de chaque couche d’entités que nous avons calculées :
[11]:
print(np.array_str(model_input, precision=2, suppress_small=True))
[[ 0. 1945.75 3164.75 ... 0.13 -0.38 3.59]
[ 0. 921. 1304.5 ... 0.06 -0.45 21.76]
[ 0. 1274.25 2244. ... 0.1 -0.47 8.8 ]
...
[ 1. 619.25 914.75 ... 1.47 -0.36 2.79]
[ 1. 494.5 791.25 ... 1.52 -0.4 2.94]
[ 1. 457.5 752.5 ... 2.04 -0.38 1.84]]
Exporter les données de formation#
Une fois que nous avons collecté toutes les données de formation dont nous avons besoin, nous pouvons écrire les données sur le disque. Cela nous permettra d’importer les données dans les étapes suivantes du flux de travail.
[12]:
#set the name and location of the output file
output_file = "results/test_training_data.txt"
[13]:
#grab all columns
model_col_indices = [column_names.index(var_name) for var_name in column_names]
#Export files to disk
np.savetxt(output_file, model_input[:, model_col_indices], header=" ".join(column_names), fmt="%4f")
Étapes suivantes recommandées#
Pour continuer à travailler sur les blocs-notes de ce flux de travail « Scalable Machine Learning sur l’ODC », accédez au bloc-notes suivant « 2_Inspect_training_data.ipynb ».
Extraction_des_données_de_formation (ce bloc-notes)
Informations Complémentaires#
Licence Le code de ce notebook est sous licence Apache, version 2.0 <https://www.apache.org/licenses/LICENSE-2.0>`__.
Les données de Digital Earth Africa sont sous licence Creative Commons Attribution 4.0 <https://creativecommons.org/licenses/by/4.0/>.
Contact Si vous avez besoin d’aide, veuillez poster une question sur le canal Slack DE Africa <https://digitalearthafrica.slack.com/> ou sur le GIS Stack Exchange <https://gis.stackexchange.com/questions/ask?tags=open-data-cube> en utilisant la balise open-data-cube (vous pouvez consulter les questions posées précédemment `ici <https://gis.stackexchange.com/questions/tagged/open-data-
Si vous souhaitez signaler un problème avec ce notebook, vous pouvez en déposer un sur Github.
Version de Datacube compatible
[14]:
print(datacube.__version__)
1.9.13
Dernier test :
[15]:
from datetime import datetime
datetime.today().strftime('%Y-%m-%d')
[15]:
'2026-04-09'