Aller au contenu

Entraîner un modèle sur des données d'annotation

Résoudre les étiquettes de plusieurs annotateurs en cibles d'entraînement, garder fixe une partition de test réservée entre les tours, consigner ce que chaque modèle a vu et dimensionner une première exécution.

Pour entraîner un modèle sur des données d'annotation, résolvez les étiquettes de chaque item en une cible unique ou en la répartition des votes des annotateurs, répartissez les items entre partitions d'entraînement, de validation et de test selon une règle qui reste fixe d'un tour à l'autre, et rapportez le score de test chaque fois que la partition de validation a choisi le point de contrôle. L'entraînement de modèles de Potato exécute chaque étape sur les annotations propres à une étude et consigne les items sur lesquels chaque exécution s'est entraînée.

Nouveauté de la v2.14.0

Les données d'annotation arrivent rarement sous la forme qu'un module d'entraînement lit. Une étude avec recouvrement a plusieurs étiquettes par item, et ces étiquettes sont souvent en désaccord. Une étude en cours gagne des étiquettes chaque jour, et chaque tour de réentraînement voit plus d'items que le précédent. Un module d'entraînement a besoin d'une cible par item et d'un ensemble fixe d'items sur lesquels évaluer, et les décisions ci-dessous produisent les deux. Chaque section ci-dessous nomme le paramètre de Potato qui prend la décision. Pour la page Training elle-même, consultez la vue d'ensemble de l'entraînement de modèles et le tutoriel qui entraîne un premier modèle. Pour entraîner dans votre propre code, Exporter des annotations pour l'apprentissage automatique couvre les formats d'export, et les mêmes décisions s'appliquent au fichier exporté.

Résoudre plusieurs annotateurs en une étiquette

L'agrégation transforme les étiquettes que plusieurs annotateurs ont données à un item en l'étiquette unique sur laquelle un modèle s'entraîne. La méthode la plus simple est le vote majoritaire. Le vote majoritaire compte une fois la réponse de chaque annotateur et garde la réponse la plus fréquente. Dawid et Skene (1979) estiment une matrice de confusion pour chaque annotateur par espérance-maximisation et pondèrent chaque vote par la fiabilité estimée de l'annotateur. Un annotateur négligent pèse alors moins sur le résultat qu'un annotateur soigneux. Agréger des étiquettes issues de la foule compare les deux méthodes et les modèles construits sur Dawid-Skene.

Une exécution d'entraînement dans Potato résout les étiquettes avec model_training.aggregation. La valeur par défaut, consensus, exécute Dawid-Skene dès que le projet compte plus d'un annotateur et revient au vote majoritaire si l'estimation échoue. L'autre valeur, majority, exécute le vote majoritaire seul. Les deux méthodes traitent la réponse complète d'un annotateur sur un schéma comme un seul vote. Deux réponses multiselect ne comptent donc comme le même vote que si les deux réponses cochent le même ensemble d'étiquettes.

Le paramètre consensus de l'exécution et l'export de consensus sont deux fonctionnalités distinctes. L'export de consensus donne un vote à chaque annotateur, rapporte le nombre et la fraction de chaque réponse sur chaque item et marque chaque item retired ou needs_review. Lisez l'export avant d'entraîner si vous voulez voir, item par item, où les annotateurs se divisent. MACE estime un score de compétence pour chaque annotateur à partir des mêmes votes.

Apprendre du désaccord

Sur des tâches subjectives comme l'offensivité ou l'émotion, les annotateurs peuvent être en désaccord parce que chacun lit l'item différemment, et une étiquette unique issue d'un vote écarte cette division. Uma et al. (2021) passent en revue des méthodes qui s'entraînent sur le désaccord plutôt que sur une étiquette agrégée. Une famille de ces méthodes s'entraîne sur des étiquettes souples. Une étiquette souple est une distribution de probabilité sur les étiquettes, construite à partir de la part d'annotateurs qui ont choisi chaque étiquette.

hf-text-classification accepte le paramètre soft_targets: true. Avec ce paramètre, un item que deux annotateurs ou plus ont étiqueté s'entraîne vers la répartition des annotateurs par entropie croisée contre la distribution. Quand deux annotateurs sur trois ont dit positive, la cible est 0,67 positive et 0,33 negative. Pour un schéma multiselect, chaque étiquette s'entraîne vers la part d'annotateurs qui l'ont cochée. Un item avec un seul annotateur s'entraîne comme avant sur l'étiquette de cet annotateur. Le modèle reste alors incertain là où les gens étaient en désaccord, et chaque prédiction inclut les probabilities du modèle. Sur les items réservés qui ont une répartition de votes, l'exécution rapporte trois métriques supplémentaires.

MétriqueCe que la métrique mesure
soft_jsdDivergence de Jensen-Shannon entre la distribution du modèle et la répartition des annotateurs, en bits de 0 à 1
soft_cross_entropyEntropie croisée de la répartition des annotateurs sous la distribution du modèle
eceErreur de calibration attendue de l'étiquette principale par rapport à l'étiquette votée, sur 10 intervalles de confiance

Dans un schéma d'étiquette souple, chaque annotateur donne une distribution avec des curseurs. hf-text-classification entraîne toujours un schéma soft_label vers la distribution moyenne des annotateurs, et la pré-étiquette règle les curseurs sur la distribution prédite. Les cibles souples demandent deux étiquettes ou plus sur un item. Une étude qui prévoit d'entraîner sur le désaccord recueille donc des étiquettes avec recouvrement dès le départ, et Combien d'annotateurs faut-il ? traite des paramètres de recouvrement. Le désaccord est un signal, pas du bruit plaide pour garder la division dans les données.

Partitions d'entraînement, de validation et de test

Les partitions d'entraînement, de validation et de test remplissent trois fonctions différentes. La partition d'entraînement ajuste les poids du modèle. La partition de validation choisit entre des modèles candidats, par exemple l'époque à laquelle s'arrêter. La partition de test estime la performance sur des données jamais vues et ne joue aucun rôle dans l'un ou l'autre choix. Choisir un point de contrôle sur la validation est une forme d'ajustement à la validation. Le point de contrôle gardé pour le meilleur score de validation a un score de validation biaisé vers le haut, et seul le score de test vient d'items que le choix n'a jamais consultés.

Une exécution de Potato répartit par défaut les items étiquetés en 70/15/15 (splits). La partition de chaque item vient d'un hachage à graine fixe de l'identifiant de l'item (split_seed). Un item réservé dans une exécution le reste donc dans la suivante, tant que split_seed et splits ne changent pas. Changer l'un ou l'autre paramètre peut déplacer des items réservés vers l'entraînement, et tout score après le changement mesure alors en partie la mémorisation. Définissez les deux une seule fois, au début de l'étude.

Les modules d'entraînement par affinage, comme hf-text-classification, gardent le point de contrôle de l'époque qui a obtenu le meilleur score sur la validation. Le score principal d'une telle exécution vient de test. sklearn-text, setfit, rdkit-property, les modules d'entraînement de modèles de décision et les passerelles d'inférence ne choisissent rien sur la validation, et une exécution de l'un de ces modules prend son score principal sur la validation dès que celle-ci contient des items. L'infobulle de la colonne Held-out score du tableau Runs nomme la partition et la métrique derrière chaque nombre. Un item qui a une étiquette et pas de prédiction compte comme faux. Un module d'entraînement ne peut pas relever le score en sautant les items difficiles, et <split>_coverage rapporte la part d'items qui ont reçu une prédiction.

Items corrigés et épinglés

Deux sortes d'items vont dans la partition train de toutes les exécutions suivantes, quelle que soit la partition attribuée par le hachage. La première est un item qu'un relecteur a corrigé dans la relecture des modèles, et la seconde est un item que quelqu'un a épinglé avec Train on these à côté d'une tranche de la page Catalog. Les corrections viennent des items sur lesquels le modèle était le moins bon, et dans la validation ou le test elles évalueraient le modèle sur un échantillon de ses propres erreurs. Une exécution qui déplace des items réservés vers l'entraînement consigne un avertissement avec leur nombre, et le score sur items réservés de l'exécution n'est alors pas directement comparable à celui d'une exécution antérieure. Une exécution qui s'entraîne sur un item corrigé qu'une exécution antérieure avait réservé consigne aussi un avertissement, car un score sur les items de validation ou de test de l'exécution antérieure, ou sur un jeu de données enregistré à partir de ces items, inclut alors des items sur lesquels le nouveau modèle s'est entraîné. Les corrections et les items épinglés entrent toujours dans l'entraînement donne les règles.

Consigner ce sur quoi chaque modèle s'est entraîné

Comparer deux exécutions demande de savoir sur quels items chacune s'est entraînée et a été évaluée. Chaque exécution de Potato écrit un lot sous <output_annotation_dir>/training/runs/<run_id>/bundle/ avec train.jsonl, val.jsonl, test.jsonl, labels.json et manifest.json. Le manifeste consigne la graine de partition, la méthode d'agrégation, le nombre d'items dans chaque partition, le nombre d'items forcés dans l'entraînement et une empreinte SHA-256 des fichiers de partition. Rien dans un lot ne renvoie à Potato, et un script extérieur à Potato peut lire le lot comme une copie autonome des étiquettes résolues et des partitions.

La base de données du projet, project.sqlite, tient un registre avec une ligne par exécution. Chaque ligne consigne le module d'entraînement, les paramètres, la taille des partitions, la graine de partition, les métriques sur items réservés et l'empreinte du lot. Une seconde table consigne la partition dans laquelle chaque item se trouvait pour chaque exécution. L'écriture en retour lit cette table et ne pré-étiquette jamais un item sur lequel une exécution encore présente dans le registre s'est entraînée (retain_runs conserve cinq exécutions terminées par défaut). Un modèle est sûr de lui sur les items sur lesquels il s'est entraîné, pour des raisons qui ne disent rien des nouvelles données.

Pour comparer des modèles ultérieurs sur exactement les mêmes items, Keep this split as a dataset sur la page de l'exécution enregistre les items de validation, de test ou d'entraînement de l'exécution comme version d'un jeu de données, avec les étiquettes humaines consolidées. Une version enregistrée ne change plus ensuite. Chaque version enregistrée contient une seule partition et repart de zéro plutôt que de s'ajouter à la version précédente. Les items de validation de l'exécution 2 enregistrés par-dessus ceux de l'exécution 1 incluraient sinon des items sur lesquels l'exécution 2 s'est entraînée. Une évaluation sur une version enregistrée ne peut pas lire la réponse du modèle, car les entrées enregistrées omettent le champ des pré-étiquettes. L'enregistrement demande datasets.enabled: true. Quand le modèle ou le jeu de données quitte le projet, Documenter les jeux de données et les modèles traite des fiches de données et des fiches de modèle.

De combien de données un premier modèle a besoin

Chaque module d'entraînement de Potato refuse de s'ajuster avec moins de min_instances items dans la partition train. Les valeurs par défaut ci-dessous sont les nombres à partir desquels une exécution démarre.

Module d'entraînementValeur par défaut de min_instancesRemarque
setfit8Conçu pour les premiers jours d'un projet, à partir d'environ huit items par étiquette
sklearn-text10Ne calibre les confiances qu'à partir de 50 items d'entraînement
hf-audio-tagger10
hf-text-classification, hf-token-classification, hf-image-classification20
llm-sft, llm-dpo20

Le seuil ne compte que la partition train. Avec la partition 70/15/15 par défaut, une exécution sklearn-text démarre dès qu'environ 15 items ont une étiquette. L'exemple d'entraînement de modèles du dépôt de Potato donne un point mesuré. Avec 120 des 160 avis de produits synthétiques de l'exemple étiquetés une fois chacun, une exécution sklearn-text a obtenu 0,84 de macro-F1 sur la validation et a publié 80 pré-étiquettes. Ce chiffre vient d'une seule tâche synthétique à deux étiquettes, et le score sur items réservés de vos propres exécutions est le nombre à lire pour votre tâche.

Commencez par sklearn-text. Ce module d'entraînement ne demande rien de plus qu'une installation ordinaire et aucun GPU. Réentraînez à mesure que les étiquettes arrivent, et suivez le score sur items réservés d'une exécution à l'autre en laissant split_seed inchangé. Les pré-étiquettes ancrent les annotateurs. Laissez writeback.schemas vide jusqu'à ce que le score sur items réservés justifie de montrer les réponses du modèle. L'étiquetage assisté par un modèle explique ce qui change une fois que les annotateurs voient des pré-étiquettes, et Distinguer relecture et validation mécanique explique comment vérifier que les annotateurs lisent encore les items.

Une configuration qui fixe chaque décision

La configuration ci-dessous entraîne sur un schéma de sentiment à deux étiquettes. Chaque clé sous model_training fixe l'une des décisions ci-dessus.

yaml
annotation_task_name: "Review sentiment"
task_dir: "."
data_files:
  - "data/reviews.json"
item_properties:
  id_key: "id"
  text_key: "text"
output_annotation_dir: "annotation_output"
 
annotation_schemes:
  - annotation_type: "radio"
    name: "sentiment"
    description: "Is this review positive or negative?"
    labels: ["positive", "negative"]
 
model_training:
  enabled: true
  aggregation: consensus
  split_seed: 0
  splits: {train: 0.7, val: 0.15, test: 0.15}
  trainer_params:
    hf-text-classification:
      soft_targets: true

aggregation: consensus résout les étiquettes avec recouvrement par Dawid-Skene. split_seed et splits sont écrits explicitement avec leurs valeurs par défaut, car aucun des deux paramètres ne doit changer pendant toute la vie de l'étude. soft_targets: true fait entraîner chaque exécution hf-text-classification du projet sur les répartitions de votes. Ce module d'entraînement demande pip install "potato-annotation[train-text]", et sklearn-text tourne avec la même configuration sans installation supplémentaire. Sans bloc writeback, les annotateurs ne voient aucune pré-étiquette. Redémarrez le serveur avec la configuration, ouvrez /admin/training, choisissez un module d'entraînement et le schéma sentiment, puis cliquez sur Train now. La référence de configuration de l'entraînement de modèles liste chaque clé, et le tutoriel du modèle dans la boucle ajoute l'écriture en retour et le réentraînement automatique.

Pour aller plus loin

Références

  • Dawid, A. P., and Skene, A. M. (1979). Maximum Likelihood Estimation of Observer Error-Rates Using the EM Algorithm. Applied Statistics, 28(1), 20. doi.org/10.2307/2346806
  • Uma, A. N., Fornaciari, T., Hovy, D., Paun, S., Plank, B., and Poesio, M. (2021). Learning from Disagreement: A Survey. Journal of Artificial Intelligence Research, 72, 1385–1470. doi.org/10.1613/jair.1.12752