Entraînez des transformateurs de vision auto-encodés sur des images aériennes avec Amazon SageMaker

Entraînez des transformateurs de vision auto-encodés sur des images aériennes avec Amazon SageMaker' can be condensed to Entraînez des transformateurs de vision auto-encodés avec Amazon SageMaker

Ceci est un billet d’invité co-écrit avec Ben Veasey, Jeremy Anderson, Jordan Knight et June Li de Travelers.

Les images satellites et aériennes fournissent des informations sur une large gamme de problèmes, notamment l’agriculture de précision, l’évaluation des risques d’assurance, le développement urbain et la réponse aux catastrophes. Cependant, la formation de modèles d’apprentissage automatique (ML) pour interpréter ces données est entravée par des efforts coûteux et chronophages d’annotation humaine. Une façon de surmonter ce défi est l’apprentissage auto-supervisé (SSL). En s’entraînant sur de grandes quantités de données d’images non étiquetées, les modèles auto-supervisés apprennent des représentations d’images qui peuvent être transférées à des tâches ultérieures, telles que la classification ou la segmentation d’images. Cette approche produit des représentations d’images qui généralisent bien aux données invisibles et réduit la quantité de données étiquetées nécessaires pour construire des modèles ultérieurs performants.

Dans ce billet, nous démontrons comment entraîner des transformateurs de vision auto-supervisés sur des images aériennes à l’aide d’Amazon SageMaker. Travelers a collaboré avec le Laboratoire d’IA de Machine Learning Solutions d’Amazon (aujourd’hui connu sous le nom de Centre d’Innovation en IA Générative) pour développer ce cadre afin de prendre en charge et d’améliorer les cas d’utilisation des modèles d’imagerie aérienne. Notre solution est basée sur l’algorithme DINO et utilise la bibliothèque parallèle de données distribuées de SageMaker (SMDDP) pour répartir les données sur plusieurs instances de GPU. Lorsque la pré-formation est terminée, les représentations d’images DINO peuvent être transférées à diverses tâches ultérieures. Cette initiative a conduit à une amélioration des performances des modèles dans l’espace des données et de l’analyse de Travelers.

Aperçu de la solution

Le processus en deux étapes de pré-formation des transformateurs de vision et de leur transfert vers des tâches ultérieures supervisées est représenté dans le diagramme suivant.

Dans les sections suivantes, nous fournissons un guide étape par étape de la solution en utilisant des images satellites provenant de l’ensemble de données BigEarthNet-S2. Nous nous appuyons sur le code fourni dans le référentiel DINO.

Prérequis

Avant de commencer, vous avez besoin d’un accès à une instance de bloc-notes SageMaker et à un compartiment Amazon Simple Storage Service (Amazon S3).

Préparation de l’ensemble de données BigEarthNet-S2

BigEarthNet-S2 est une archive de référence contenant 590 325 images multispectrales collectées par le satellite Sentinel-2. Les images documentent la couverture terrestre, ou les caractéristiques physiques de surface, de dix pays européens entre juin 2017 et mai 2018. Les types de couverture terrestre dans chaque image, tels que les pâturages ou les forêts, sont annotés selon 19 étiquettes. Voici quelques exemples d’images RVB et de leurs étiquettes.

La première étape de notre flux de travail consiste à préparer l’ensemble de données BigEarthNet-S2 pour la formation et l’évaluation de DINO. Nous commençons par télécharger l’ensemble de données à partir du terminal de notre instance de bloc-notes SageMaker :

wget https://bigearth.net/downloads/BigEarthNet-S2-v1.0.tar.gz
tar -xvf BigEarthNet-S2-v1.0.tar.gz

L’ensemble de données a une taille d’environ 109 Go. Chaque image est stockée dans son propre dossier et contient 12 canaux spectraux. Trois bandes avec une résolution spatiale de 60 mètres sont conçues pour identifier les aérosols (B01), la vapeur d’eau (B09) et les nuages (B10). Six bandes avec une résolution spatiale de 20 mètres sont utilisées pour identifier la végétation (B05, B06, B07, B8A) et distinguer entre la neige, la glace et les nuages (B11, B12). Trois bandes avec une résolution spatiale de 10 mètres aident à capturer la lumière visible et proche infrarouge (B02, B03, B04, B8/B8A). De plus, chaque dossier contient un fichier JSON avec les métadonnées de l’image. Une description détaillée des données est fournie dans le guide BigEarthNet.

Pour effectuer des analyses statistiques des données et charger les images lors de la formation de DINO, nous traitons les fichiers de métadonnées individuels en un fichier Parquet geopandas commun. Cela peut être fait en utilisant les packages BigEarthNet Common et BigEarthNet GDF Builder :

python -m bigearthnet_gdf_builder.builder build-recommended-s2-parquet BigEarthNet-v1.0/

Le fichier de métadonnées résultant contient l’ensemble d’images recommandé, qui exclut 71,042 images entièrement recouvertes de neige saisonnière, de nuages et d’ombres de nuages. Il contient également des informations sur la date d’acquisition, l’emplacement, la couverture terrestre et la répartition des images d’entraînement, de validation et de test.

Nous stockons les images BigEarthNet-S2 et le fichier de métadonnées dans un compartiment S3. Parce que nous utilisons des images en vraies couleurs pendant l’entraînement DINO, nous ne téléchargeons que les bandes rouge (B04), verte (B03) et bleue (B02) :

aws s3 cp final_ben_s2.parquet s3://bigearthnet-s2-dataset/metadata/
aws s3 cp BigEarthNet-v1.0/ s3://bigearthnet-s2-dataset/data_rgb/ \
    --recursive \
    --exclude "*" \
    --include "_B02.tif" \
    --include "_B03.tif" \ 
    --include "_B04.tif"

L’ensemble de données a une taille d’environ 48 Go et a la structure suivante :

bigearthnet-s2-dataset/                                    Compartiment Amazon S3
├── metadata/
│ └── final_ben_s2.parquet 
└── dataset_rgb/
  ├── S2A_MSIL2A_20170613T101031_0_45/
  │ └── S2A_MSIL2A_20170613T101031_0_45_B02.tif            Canal Bleu
  │ └── S2A_MSIL2A_20170613T101031_0_45_B03.tif            Canal Vert
  │ └── S2A_MSIL2A_20170613T101031_0_45_B04.tif            Canal Rouge

Entraîner des modèles DINO avec SageMaker

Maintenant que notre ensemble de données a été téléchargé sur Amazon S3, nous passons à l’entraînement des modèles DINO sur BigEarthNet-S2. Comme le montre la figure suivante, l’algorithme DINO transmet différentes cultures globales et locales d’une image d’entrée aux réseaux étudiant et enseignant. Le réseau étudiant est enseigné à faire correspondre la sortie du réseau enseignant en minimisant la perte de cross-entropy. Les poids de l’étudiant et de l’enseignant sont connectés par une moyenne mobile exponentielle (EMA).

Nous apportons deux modifications au code DINO d’origine. Premièrement, nous créons une classe de dataset PyTorch personnalisée pour charger les images BigEarthNet-S2. Le code a été initialement écrit pour traiter les données ImageNet et s’attend à ce que les images soient stockées par classe. Cependant, BigEarthNet-S2 est un ensemble de données multi-étiquettes où chaque image réside dans son propre sous-dossier. Notre classe de dataset charge chaque image en utilisant le chemin d’accès au fichier stocké dans les métadonnées :

import pandas as pd
import rasterio
from PIL import Image
import torch
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms, utils
 
OPTICAL_MAX_VALUE = 2000

LAND_COVER_LABELS = [
    "Tissu urbain",
    "Unités industrielles ou commerciales",
    "Terres labourables",
    "Cultures permanentes",
    "Pâturages",
    "Modèles de culture complexes",
    "Terres principalement occupées par l'agriculture, avec des zones significatives de végétation naturelle",
    "Zones agroforestières",
    "Forêt feuillue",
    "Forêt de conifères",
    "Forêt mixte",
    "Prairies naturelles et zones peu végétalisées",
    "Tourbières, landes et végétation sclérophylle",
    "Boisement de transition, arbuste",
    "Plages, dunes, sables",
    "Milieux humides intérieurs",
    "Milieux humides côtiers",
    "Eaux intérieures",
    "Eaux marines",
]
 
class BigEarthNetDataset(Dataset):
     """
     Classe de dataset PyTorch qui charge les images BigEarthNet-S2 à partir d'un fichier de métadonnées.

     Args: 
          metadata_file: chemin vers le fichier de métadonnées 
          data_dir: répertoire où se trouvent les données BigEarthNet-S2  
          split: répartition d'entraînement, de validation ou de test
          transform: transformations appliquées à l'image d'entrée
     """
     def __init__(self, metadata_file, data_dir, split="train", transform=None):
        # chemins d'accès aux fichiers d'images à partir des métadonnées
        metadata = pd.read_parquet(metadata_file)
        self.metadata_split = metadata[metadata["original_split"] == split]
        self.data_dir = data_dir
        self.patch_names = self.metadata_split["name"].tolist()
 
        # one-hot-encode des étiquettes de couverture terrestre 
        multiclass_labels = self.metadata_split.new_labels.tolist()
        self.labels = self.get_multi_onehot_labels(multiclass_labels)

        # transformations        
        self.transform = transform
 
    def __len__(self):
        """Retourne la longueur du dataset."""
        return len(self.metadata_split)
 
    def __getitem__(self, index):
        """Retourne l'image et l'étiquette pour un index donné."""
        patch_name = self.patch_names[index]
        file_path = os.path.join(self.data_dir, patch_name)
    
    # générer l'image RGB
        r_channel = rasterio.open(os.path.join(file_path, patch_name + "_B04.tif")).read(1)
        g_channel = rasterio.open(os.path.join(file_path, patch_name + "_B03.tif")).read(1)
        b_channel = rasterio.open(os.path.join(file_path, patch_name + "_B02.tif")).read(1)
 
        image = np.stack([r_channel, g_channel, b_channel], axis=2)
        image = image / OPTICAL_MAX_VALUE * 255
        image = np.clip(image, 0, 225).astype(np.uint8)
    
        # appliquer les transformations d'image
        image = Image.fromarray(image, mode="RGB")
        if self.transform is not None:
            image = self.transform(image)
 
        # charger l'étiquette
        label = self.labels[index]
 
        return image, label
  
    def get_multi_onehot_labels(self, multiclass_labels):
        """Convertir les étiquettes BEN-19 en vecteur one-hot encodé."""
        targets = torch.zeros([len(multiclass_labels), len(LAND_COVER_LABELS)])
        for index, img_labels in enumerate(multiclass_labels):
            for label in img_labels:
                index_hot = LAND_COVER_LABELS.index(label)
                targets[index, index_hot] = 1.
        return targets

Cette classe de jeu de données est appelée dans main_dino.py pendant l’entraînement. Bien que le code inclue une fonction pour encoder en one-hot les étiquettes de couverture terrestre, ces étiquettes ne sont pas utilisées par l’algorithme DINO.

La deuxième modification que nous apportons au code DINO est d’ajouter la prise en charge de SMDDP. Nous ajoutons le code suivant à la fonction init_distributed_mode dans le fichier util.py:

fonction init_distributed_mode dans le fichier util.py:

def init_distributed_mode(args):
     if json.loads(
          os.environ.get('SM_FRAMEWORK_PARAMS', '{}'))
         .get('sagemaker_distributed_dataparallel_enabled', False)
     ): 
          # lancer l'entraînement avec SMDDP 
          dist.init_process_group(backend='smddp')
          args.word_size = dist.get_world_size() 
          args.gpu = int(os.environ['LOCAL_RANK'])

Avec ces ajustements, nous sommes prêts à entraîner des modèles DINO sur BigEarthNet-S2 en utilisant SageMaker. Pour entraîner sur plusieurs GPU ou instances, nous créons un estimateur SageMaker PyTorch qui prend en compte le script d’entraînement DINO, les chemins des fichiers d’image et de métadonnées, ainsi que les hyperparamètres d’entraînement:

import time
from sagemaker.pytorch import PyTorch

# bucket de sortie où les artefacts finaux du modèle sont téléchargés 
DINO_OUTPUT_BUCKET = 'dino-models'

# chemins sur l'instance d'entraînement  
sm_metadata_path = '/opt/ml/input/data/metadata'              
sm_data_path = '/opt/ml/input/data/train'                     
sm_output_path = '/opt/ml/output/data'                        
sm_checkpoint_path = '/opt/ml/checkpoints'                

# nom du travail d'entraînement
dino_base_job_name = f'dino-model-{int(time.time())}'

# créer un estimateur SageMaker
estimator = PyTorch(
    base_job_name=dino_base_job_name,
    source_dir='chemin/vers/aerial_featurizer',
    entry_point='main_dino.py',
    role=role,
    framework_version="1.12",
    py_version="py38",
    instance_count=1,
    instance_type="ml.p3.16xlarge",    
    distribution = {'smdistributed':{'dataparallel':{'enabled': True}}},        
    volume_size=100,
    sagemaker_session=sagemaker_session,
    hyperparameters = {
        # hyperparamètres transmis au script de point d'entrée
        'arch': 'vit_small',
        'patch_size': 16,
        'metadata_dir': sm_metadata_path,
        'data_dir': sm_data_path,
        'output_dir': sm_output_path,
        'checkpoint_dir': sm_checkpoint_path,
        'epochs': 100,
        'saveckp_freq': 20,
    },
    max_run=24*60*60,               
    checkpoint_local_path = sm_checkpoint_path,
    checkpoint_s3_uri =f's3://{DINO_OUTPUT_BUCKET}/checkpoints/{base_job_name}', 
    debugger_hook_config=False,                           
)

Ce code spécifie que nous allons entraîner un petit modèle de vision transformer (21 millions de paramètres) avec une taille de patch de 16 pour 100 époques. Il est conseillé de créer un nouveau checkpoint_s3_uri pour chaque travail d’entraînement afin de réduire le temps de téléchargement initial des données. Étant donné que nous utilisons SMDDP, nous devons entraîner sur une instance ml.p3.16xlarge, ml.p3dn.24xlarge ou ml.p4d.24xlarge. Cela s’explique par le fait que SMDDP n’est activé que pour les plus grandes instances multi-GPU. Pour entraîner sur des types d’instances plus petits sans SMDDP, vous devrez supprimer les arguments distribution et debugger_hook_config de l’estimateur.

Une fois que nous avons créé l’estimateur SageMaker PyTorch, nous lançons le travail d’entraînement en appelant la méthode fit. Nous spécifions les données d’entraînement en utilisant les URIs Amazon S3 pour les métadonnées et les images BigEarthNet-S2:

# appeler fit pour commencer l'entraînement
estimator.fit(
    inputs={
        'metadata': 's3://bigearthnet-s2-dataset/metadata/',
        'train': 's3://bigearthnet-s2-dataset/data_rgb/',
    },
    wait=False
)

SageMaker lance l’instance, copie le script d’entraînement et les dépendances, et commence l’entraînement DINO. Nous pouvons suivre la progression du travail d’entraînement depuis notre notebook Jupyter en utilisant les commandes suivantes:

# surveiller l'entraînement
training_job_name = estimator.latest_training_job.name 
attached_estimator = PyTorch.attach(training_job_name)
attached_estimator.logs()

Nous pouvons également surveiller les métriques d’instance et afficher les fichiers journaux sur la console SageMaker sous Jobs de formation. Dans les figures suivantes, nous traçons l’utilisation du GPU et la fonction de perte pour un modèle DINO entraîné sur une instance ml.p3.16xlarge avec une taille de lot de 128.

Pendant la formation, l’utilisation du GPU est de 83% de la capacité de l’instance ml.p3.16xlarge (8 GPU NVIDIA Tesla V100) et l’utilisation de la VRAM est de 85%. La fonction de perte diminue régulièrement à chaque époque, ce qui indique que les sorties des réseaux étudiant et enseignant deviennent de plus en plus similaires. Au total, la formation prend environ 11 heures.

Transfert d’apprentissage vers des tâches aval

Notre modèle DINO entraîné peut être transféré à des tâches aval telles que la classification d’images ou la segmentation. Dans cette section, nous utilisons les caractéristiques DINO pré-entraînées pour prédire les classes de couverture terrestre pour les images de l’ensemble de données BigEarthNet-S2. Comme le montre le diagramme suivant, nous entraînons un classificateur linéaire multi-étiquettes sur les caractéristiques DINO figées. Dans cet exemple, l’image d’entrée est associée aux couvertures de terres arables et de pâturages.

La plupart du code pour le classificateur linéaire est déjà en place dans le référentiel DINO d’origine. Nous apportons quelques ajustements pour notre tâche spécifique. Comme précédemment, nous utilisons l’ensemble de données BigEarthNet personnalisé pour charger les images lors de l’entraînement et de l’évaluation. Les étiquettes des images sont encodées en une seule dimension sous forme de vecteurs binaires à 19 dimensions. Nous utilisons l’entropie croisée binaire comme fonction de perte et calculons la précision moyenne pour évaluer les performances du modèle.

Pour entraîner le classificateur, nous créons un estimateur PyTorch SageMaker qui exécute le script d’entraînement, eval_linear.py. Les hyperparamètres d’entraînement incluent les détails de l’architecture du modèle DINO et le chemin d’accès du fichier pour le point de contrôle du modèle :

# bucket de sortie où les artefacts du modèle final sont téléchargés
CLASSIFIER_OUTPUT_BUCKET = 'classification-de-couverture-terrestre'

# nom du point de contrôle DINO
checkpoint = 'checkpoint.pth'

# chemins sur l'instance d'entraînement
sm_dino_path = f'/opt/ml/input/data/dino_checkpoint'          
sm_dino_checkpoint = f'{sm_dino_path}/{checkpoint}'           

# nom du job d'entraînement
classifier_base_job_name = f'classificateur-lineaire-{int(time.time())}'

# création de l'estimateur
estimator = PyTorch(
    base_job_name=classifier_base_job_name,
    source_dir='chemin/vers/aerial_featurizer',
    entry_point = 'eval_linear.py',
    role=role,
    framework_version='1.12',
    py_version='py38',
    instance_count=1,
    instance_type='ml.p3.2xlarge',
    sagemaker_session=sagemaker_session,
    hyperparameters = {
    # hyperparamètres transmis au script du point d'entrée
        'arch': 'vit_small',
        'pretrained_weights': sm_dino_checkpoint,
        'epochs': 50,
        'data_dir': sm_data_path,
        'metadata_dir': sm_metadata_path,
        'output_dir': sm_checkpoint_path,
        'num_labels': 19,
    },
    max_run=1*60*60, 
    checkpoint_local_path = sm_checkpoint_path,
    checkpoint_s3_uri =f's3://{CLASSIFIER_OUTPUT_BUCKET}/checkpoints/{base_job_name}',
)

Nous lançons le job d’entraînement en utilisant la méthode fit, en fournissant les emplacements Amazon S3 des métadonnées BigEarthNet-S2 et des images d’entraînement, ainsi que le point de contrôle du modèle DINO :

# appel à fit pour commencer l'entraînement
estimator.fit(
    inputs={
    'metadata': 's3://bigearthnet-s2-dataset/metadata/',
    'dataset': 's3://bigearthnet-s2-dataset/data_rgb/',
    'dino_checkpoint': f's3://bigearthnet-s2-dataset/dino-models/checkpoints/{dino_base_job_name}',
    },
    wait=False
)

Lorsque l’entraînement est terminé, nous pouvons effectuer des inférences sur l’ensemble de test BigEarthNet-S2 en utilisant SageMaker batch transform ou SageMaker Processing. Dans le tableau suivant, nous comparons la précision moyenne du modèle linéaire sur les images de l’ensemble de test en utilisant deux représentations d’images DINO différentes. Le premier modèle, ViT-S/16 (ImageNet), est le petit point de contrôle du transformateur de vision inclus dans le référentiel DINO, qui a été pré-entraîné à l’aide d’images frontales dans l’ensemble de données ImageNet. Le deuxième modèle, ViT-S/16 (BigEarthNet-S2), est le modèle que nous avons produit en pré-entraînant sur des images aériennes.

Modèle Précision moyenne
ViT-S/16 (ImageNet) 0.685
ViT-S/16 (BigEarthNet-S2) 0.732

Nous constatons que le modèle DINO pré-entraîné sur BigEarthNet-S2 se transfère mieux à la tâche de classification de la couverture terrestre que le modèle DINO pré-entraîné sur ImageNet, ce qui entraîne une augmentation de 6,7% de la précision moyenne.

Nettoyage

Après avoir terminé la formation et le transfert d’apprentissage DINO, nous pouvons nettoyer nos ressources pour éviter des frais supplémentaires. Nous arrêtons ou supprimons notre instance de notebook et supprimons toutes les données ou artefacts de modèle indésirables d’Amazon S3.

Conclusion

Cet article a démontré comment former des modèles DINO sur des images aériennes en utilisant SageMaker. Nous avons utilisé les estimateurs SageMaker PyTorch et SMDDP afin de générer des représentations des images BigEarthNet-S2 sans besoin d’étiquettes explicites. Ensuite, nous avons transféré les caractéristiques DINO vers une tâche de classification d’image en aval, qui consistait à prédire la classe de couverture terrestre des images BigEarthNet-S2. Pour cette tâche, la pré-formation sur des images satellites a entraîné une augmentation de 6,7% de la précision moyenne par rapport à la pré-formation sur ImageNet.

Vous pouvez utiliser cette solution comme modèle pour former des modèles DINO sur des ensembles de données d’images aériennes et satellites à grande échelle et non étiquetées. Pour en savoir plus sur DINO et la construction de modèles sur SageMaker, consultez les ressources suivantes :

  • Propriétés émergentes dans les visionneuses transformateurs auto-supervisées
  • Utilisation de PyTorch avec Amazon SageMaker
  • La bibliothèque de parallélisme de données de SageMaker

We will continue to update IPGirl; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Apprentissage automatique

PDG de NVIDIA Les créateurs seront boostés par l'IA générative

La création d’IA générative va “booster” les créateurs dans tous les secteurs et types de contenus,...

AI

Application pour smartphone augmente la sécurité dans la chirurgie hépatique

Une équipe internationale de chercheurs a développé une application smartphone qui fournit un score de risque personn...

AI

Prévision d'événements futurs Les capacités et les limites de l'IA et du ML

Vous êtes-vous déjà demandé comment les diseurs de bonne aventure, les astrologues ou notre célèbre Baba Vanga prédis...