Entraîner des modèles sur des molécules, des spectres, des signaux et des épisodes de robots
Ajustez rdkit-property, peak-cnn, signal-cnn et episode-model sur les réponses de votre étude, puis montrez les prédictions aux annotateurs pour qu'ils les acceptent ou les corrigent.
Nouveauté de la v2.14.0
Ce tutoriel entraîne quatre modèles sur des annotations scientifiques d'une étude Potato. rdkit-property répond à une question sur une molécule, peak-cnn repère les pics sur des spectres RMN, IR, Raman, UV-Vis et de masse, signal-cnn classe des époques de sommeil ou marque des intervalles étiquetés sur des enregistrements EEG, ECG et de capteurs, et episode-model marque les phases, le résultat et la courbe de récompense d'un épisode de robot. La page s'adresse aux équipes qui annotent déjà des molécules, des spectres, des signaux ou des épisodes de robots dans Potato et veulent qu'un modèle pré-étiquette les items restants. Pour chaque module d'entraînement, la page donne une configuration qui passe potato validate config.yaml --strict, ce qu'une exécution apprend, le score sur items réservés à lire et la façon dont les prédictions parviennent aux annotateurs. Entraîner votre premier modèle parcourt la page Training avec un classifieur de texte, et le présent tutoriel suppose ce parcours connu.
Les quatre modules d'entraînement
Chaque module apprend des réponses d'un schéma d'annotation et lit l'entrée du modèle dans l'affichage ou le fichier que désigne le schéma :
| Module | Schéma | Entrée | Installation | Score principal sur items réservés |
|---|---|---|---|---|
rdkit-property | radio, select, likert ou slider sur une molécule | un champ d'affichage molecule, ou une réponse chemical_structure | potato-annotation[chemistry] | F1 macro, ou justesse de position exacte pour un curseur |
peak-cnn | peak_picking | spectres JCAMP-DX, mzML, CSV ou données en ligne | potato-annotation[train-vision] | F1 des pics dans une tolérance |
signal-cnn | interval_label, en mode époque ou libre | signaux EDF, BDF, WFDB, CSV, Parquet ou données en ligne | potato-annotation[train-vision], plus [signals] pour WFDB et Parquet | F1 macro sur les époques, ou F1 des intervalles à IoU 0,5 |
episode-model | episode_annotation | épisodes de robots LeRobot, HDF5 ou manifeste d'épisodes de Potato | potato-annotation[train-vision] | F1 macro des phases |
rdkit-property ajuste un modèle scikit-learn, et les trois autres modules ajustent de petits réseaux PyTorch sur l'appareil que choisit model_training.device. Chaque exécution s'entraîne sur un schéma, évalue le modèle sur les items réservés val et test de l'exécution et n'écrit des prédictions en retour que pour les schémas listés sous writeback.schemas. Les items de la partition train d'une exécution ne reçoivent jamais de pré-étiquette. peak-cnn, signal-cnn et episode-model gardent le point de contrôle de l'époque qui a obtenu le meilleur score sur val, de sorte que Potato prend le score sur items réservés des trois réseaux sur test. Une petite étude compte peu d'items de test, et la métrique test_n de l'exécution donne le nombre qui sous-tend le score.
Les trois réseaux donnent à la prédiction d'un item la confiance de la partie la moins sûre de la prédiction, c'est-à-dire le pic, l'intervalle, la phase ou le résultat le plus faible. Un seuil writeback.min_confidence retient donc l'item entier lorsqu'une seule partie passe sous le seuil. Une prédiction de curseur issue de rdkit-property n'a pas de valeur de confiance et passe toujours le seuil.
Propriétés moléculaires avec rdkit-property
rdkit-property apprend les réponses à une question sur la molécule que montre un item, et c'est la structure de la molécule, et non le texte de l'item, qui sert d'entrée au modèle. Chaque structure devient une empreinte de Morgan de rayon 2 et de 2 048 bits, suivie des descripteurs 2D de RDKit, par exemple la masse moléculaire et le logP. Au rayon 2, l'empreinte de Morgan correspond à ECFP4, l'empreinte de connectivité étendue d'un diamètre de 4 liaisons. Une régression logistique ajuste par défaut une réponse radio, select ou likert, et une régression ridge ajuste un slider. Une forêt aléatoire est l'alternative dans les deux cas. Installez RDKit sur le serveur qui entraîne :
pip install "potato-annotation[chemistry]"La configuration ci-dessous montre chaque composé sous forme de dessin de structure et pose deux questions, un curseur de 1 à 10 sur la difficulté de synthèse du composé et un choix oui ou non sur la synthèse du composé à l'étape suivante :
annotation_task_name: "Compound triage"
task_dir: .
output_annotation_dir: annotation_output
data_files: [data/molecules.jsonl]
item_properties: {id_key: id, text_key: note}
user_config:
allow_all_users: true
instance_display:
fields:
- key: smiles # SMILES, a molfile, or a .mol, .sdf or .smi file
type: molecule
label: "Compound"
annotation_schemes:
- annotation_type: slider
name: synthesis
description: "How hard would this compound be to make? 1 is one step from a catalog reagent, 10 is a research project."
min_value: 1
max_value: 10
starting_value: 5
step: 1
- annotation_type: radio
name: advance
description: "Would you make this compound next?"
labels: ["yes", "no"]
model_training:
enabled: true
writeback:
schemas: [synthesis, advance]
include_unlabeled: true
min_confidence: 0.6Chaque ligne du fichier de données contient un composé :
{"id": "cpd_023", "smiles": "CC(=O)Nc1ccc(O)cc1", "note": "Compound 23"}Le module prend la structure dans le premier champ molecule de instance_display. Une étude sans champ molecule peut poser la question à côté d'un schéma chemical_structure, et le module apprend alors de la structure que les annotateurs ont dessinée. Lorsque les annotateurs ont dessiné des structures différentes, le module prend le dessin le plus courant, et lorsque personne n'a dessiné, il prend la structure dont l'éditeur est parti (prefill_field). La page Training propose rdkit-property pour un champ molecule dès qu'au moins 80 % des items remplissent le champ. Une structure que RDKit ne sait pas analyser est exclue de l'entraînement, ne reçoit aucune prédiction et est comptée dans la métrique n_unparseable de l'exécution. Pour une question à choix ou de type Likert, la page Training propose aussi les modules pour le texte, car les items ont toujours un texte.
La prédiction d'un curseur est arrondie au step du curseur et maintenue entre min_value et max_value, de sorte que le modèle propose toujours une position que le curseur possède. Le score principal d'un curseur est la justesse de position exacte, qui compte comme fausse une prédiction de 6 face à une réponse de 7. Lisez val_mae ou test_mae, l'erreur absolue moyenne, à côté de la justesse avant de décider si les prédictions sont assez proches pour être montrées. L'exécution demande au moins 10 molécules étiquetées dans la partition train. Les paramètres comme model, class_weight, radius et bits vont dans le champ Parameters de la page Training ou dans la requête d'API :
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
http://localhost:8000/admin/training/api/runs \
-d '{"trainer": "rdkit-property", "schemas": ["advance"],
"params": {"model": "random_forest", "class_weight": "balanced"}}'Le journal de l'exécution nomme le nombre de molécules, le nombre de caractéristiques et le modèle. Un poids de classe équilibré compte plus fortement les réponses rares. Utilisez class_weight: balanced lorsque la plupart des composés reçoivent la même réponse. Une fois l'exécution terminée, un annotateur qui ouvre un composé non étiqueté trouve le curseur réglé sur la valeur du modèle et le choix du modèle sélectionné, tous deux modifiables.
Pics sur des spectres avec peak-cnn
peak-cnn apprend à repérer des pics à partir des réponses peak_picking que les annotateurs ont données. Le module lit le spectre que montre le viewer_field du schéma, avec les mêmes lecteurs que ceux de l'affichage de spectres. La cible d'entraînement est chaque pic que l'annotateur a conservé, suggestions acceptées et pics ajoutés confondus. Une suggestion que l'annotateur a rejetée marque un endroit sans pic. Le modèle ne prédit que les positions des pics, et les annotateurs donnent toujours à chaque pic une attribution, une étiquette ou une multiplicité. Installez PyTorch sur la machine qui entraîne :
pip install "potato-annotation[train-vision]"La configuration ci-dessous demande aux annotateurs de relire des pics suggérés sur des spectres RMN du 1H :
annotation_task_name: "1H NMR peak picking"
task_dir: .
media_directory: media
output_annotation_dir: annotation_output
data_files: [data/spectra.jsonl]
item_properties: {id_key: id, text_key: note}
user_config:
allow_all_users: true
instance_display:
fields:
- key: spectrum
type: spectrum
label: "1H NMR"
display_options:
prepick:
method: auto # item peaks, then model, then file peak table, then detector
prominence: 0.05
max_peaks: 30
annotation_schemes:
- annotation_type: peak_picking
name: peaks
description: "Accept or reject each suggested peak, and add any the suggestions missed"
viewer_field: spectrum
peak_fields:
- name: assignment
placeholder: "e.g. OCH2"
require_review: true
label_requirement: {required: true}
model_training:
enabled: true
trainer_params:
peak-cnn:
tolerance: 0.02 # ppm
writeback:
schemas: [peaks]
include_unlabeled: trueLes pics du modèle n'atteignent les annotateurs que par le réglage prepick de l'affichage, et sans prepick l'affichage ne montre aucune suggestion. Avec method: auto, l'affichage propose d'abord les peaks propres à l'item, puis les pics du modèle, puis la table de pics du fichier, puis les pics que trouve le détecteur. Avant la première exécution, les annotateurs relisent les suggestions du détecteur, et après une exécution les mêmes items montrent les pics du modèle sans redémarrage. Avec method: model, l'affichage ne montre que les pics du modèle. Utilisez method: model pour mesurer à quelle fréquence les annotateurs acceptent les pics du modèle sans les suggestions du détecteur mélangées. Chaque pic du modèle est listé avec « · model », l'affichage garde les max_peaks plus sûrs, et un pic du modèle accepté est stocké avec source: model.
Le paramètre tolerance fixe l'écart, en unités de x, qu'un pic prédit peut avoir avec un pic annoté tout en comptant comme retrouvé. Sans tolerance, l'exécution utilise 0,5 % de la plage de x du spectre, et 0,5 % d'une fenêtre de 12 ppm en 1H fait 0,06 ppm. À 400 MHz, un couplage de 7 Hz sépare les raies d'un multiplet de 0,0175 ppm. La tolérance par défaut est plus large que cet espacement, et la configuration fixe 0,02 ppm à la place. L'exécution évalue la précision, le rappel et le F1 sur des pics appariés un à un, du plus proche au plus éloigné, et rapporte le décalage moyen des pics appariés. Un pic prédit sur un spectre dont l'annotateur a dit qu'il n'a aucun pic compte comme une fausse alarme. L'exécution demande au moins 5 spectres annotés dans la partition train.
Chaque spectre est rééchantillonné à length points, 4 096 par défaut, avant que le réseau ne le voie. Augmentez length lorsque les pics sont plus étroits que 1/length de la plage de x, par exemple pour un spectre de masse à haute résolution. La lecture de fichiers mzML demande aussi l'extra spectra, comme le décrit la page de l'affichage de spectres.
Stades de sommeil et intervalles de signaux avec signal-cnn
signal-cnn apprend des réponses interval_label sur des enregistrements physiologiques et de capteurs comme l'EEG, l'ECG, l'EMG et les données d'accéléromètre. Le réseau est un petit modèle InceptionTime, une pile de convolutions parallèles de trois largeurs. Le module lit chaque enregistrement avec les lecteurs de l'affichage de séries temporelles, prend les canaux que nomme l'affichage, rééchantillonne chaque canal à rate (100 Hz par défaut) et standardise chaque canal. Installez PyTorch, ainsi que l'extra signals pour les enregistrements WFDB et Parquet :
pip install "potato-annotation[train-vision,signals]"La configuration ci-dessous cote le sommeil par époques de 30 secondes sur une polysomnographie de nuit, comme un cotateur humain étiquette chaque époque comme éveil, N1, N2, N3 ou REM :
annotation_task_name: "Sleep staging"
task_dir: .
media_directory: media
output_annotation_dir: annotation_output
data_files: [data/psg.jsonl]
item_properties: {id_key: id, text_key: note}
user_config:
allow_all_users: true
instance_display:
fields:
- key: signal
type: time_series
label: "PSG"
display_options:
window: 30
channels: ["EEG Fpz-Cz", "EOG", "EMG chin"] # also the channels signal-cnn reads
annotation_schemes:
- annotation_type: interval_label
name: stage
description: "Sleep stage of each 30-second epoch"
signal_field: signal
mode: epoch
epoch_length: 30
require_all_epochs: true
label_requirement: {required: true}
labels:
- {name: W, key_value: "1"}
- {name: N1, key_value: "2"}
- {name: N2, key_value: "3"}
- {name: N3, key_value: "4"}
- {name: REM, key_value: "5"}
model_training:
enabled: true
writeback:
schemas: [stage]
include_unlabeled: trueLe mode du schéma fixe la tâche. En mode époque, chaque époque annotée est un exemple d'entraînement, et le modèle étiquette chaque époque d'un nouvel enregistrement. Une dernière époque dont moins de la moitié de la longueur est enregistrée ne reçoit aucune étiquette. Le score principal sur items réservés est le F1 macro sur les époques annotées. Le F1 macro donne à un stade rare comme N1 le même poids qu'à N2. Par défaut, la perte d'entraînement pondère chaque stade par l'inverse de la fréquence de l'étiquette (balanced: true), et une époque N1 compte alors plus qu'une époque N2. Chaque enregistrement est lu avec les canaux du premier enregistrement d'entraînement, dans cet ordre, et un enregistrement auquel manque l'un des canaux d'entraînement reçoit une ligne plate à la place du canal manquant. Un affichage qui ne nomme aucun canal donne au module tous les canaux, jusqu'à max_channels (16).
Le mode libre s'entraîne plutôt sur des plages marquées. Ajoutez un second schéma interval_label avec mode: free au même signal_field pour marquer des artefacts ou des éveils brefs :
- annotation_type: interval_label
name: artifacts
description: "Mark artifacts"
signal_field: signal
mode: free
labels:
- {name: artifact, key_value: "a"}
- {name: spike, key_value: "s", kind: event}En mode libre, le réseau s'entraîne sur des rognages aléatoires de 30 secondes (window_s), étiquette chaque trame d'une seconde (frame_s), fusionne les trames consécutives portant une même étiquette en un intervalle et écarte les intervalles plus courts que min_duration. Le score principal est le F1 des intervalles, qui apparie un intervalle prédit à un intervalle annoté de même étiquette à IoU 0,5. Les événements ponctuels comme l'étiquette spike ci-dessus ne sont ni entraînés ni prédits. L'exécution demande au moins 3 enregistrements annotés dans la partition train, et le mode époque demande aussi au moins deux étiquettes différentes dans les données.
Les intervalles du modèle apparaissent sur l'enregistrement sous forme de pré-annotations en pointillés, listées avec « · from the model », et sont enregistrés lorsque l'annotateur fait un premier changement ou clique sur « Keep these ». Les annotations propres d'un enregistrement prennent le pas. Un fichier EDF+ qui contient un hypnogramme montre l'hypnogramme et non les intervalles du modèle, et il en va de même pour un item avec des intervalles preannotation_field. Régler pre_annotations: false sur le schéma désactive les deux types.
Épisodes de robots avec episode-model
episode-model apprend les trois couches d'une réponse episode_annotation, c'est-à-dire les phases, le résultat et la courbe de récompense de progression. L'entrée du modèle est chaque série numérique que l'épisode enregistre, comme les positions des articulations et l'état de la pince, avec une ligne par image. L'entrée comprend les séries que series_shown laisse hors de l'écran et exclut la vidéo. Le modèle ne peut pas trouver une phase qui ne se voit qu'à la caméra et laisse inchangées les mesures du robot. Installez PyTorch, plus pyarrow pour les jeux de données LeRobot ou h5py pour les démonstrations HDF5 :
pip install "potato-annotation[train-vision]"La configuration ci-dessous recueille les trois couches sur des démonstrations de saisie et de dépose, comme le décrit la page des épisodes de robots :
annotation_task_name: "Robot episode review"
task_dir: .
media_directory: media
output_annotation_dir: annotation_output
data_files: [data/episodes.jsonl]
item_properties: {id_key: id, text_key: note}
user_config:
allow_all_users: true
annotation_schemes:
- annotation_type: episode_annotation
name: episode_review
description: "Mark the phases, judge the outcome, and draw the progress."
source_field: episode
layers: [phases, outcome, reward]
phases:
- {name: reach, key_value: "1"}
- {name: grasp, key_value: "2"}
- {name: transport, key_value: "3"}
- {name: place, key_value: "4"}
- {name: retract, key_value: "5"}
outcomes: [success, partial, failure]
failure_causes: [missed grasp, object slipped, collision]
reward_range: [0.0, 1.0]
series_shown: [gripper, wrist_force, shoulder_lift, elbow]
model_training:
enabled: true
writeback:
schemas: [episode_review]
include_unlabeled: trueLe réseau applique une convolution sur les séries, suivie d'un GRU bidirectionnel à trois têtes, l'une pour la phase de chaque image, l'une pour le résultat de l'épisode et l'une pour la récompense à chaque image. Une couche qu'une réponse laisse vide est exclue de la perte de cet épisode, de sorte qu'un épisode marqué seulement d'un résultat entraîne tout de même la tête du résultat. La tête du résultat s'entraîne dès que les épisodes d'entraînement comprennent au moins deux résultats différents. La tête de la récompense ne s'entraîne que sur la plage où l'annotateur a tracé la courbe, car en dehors de cette plage l'annotateur n'a donné aucune réponse. Les épisodes de plus de max_frames (2 000) images sont entraînés sur des rognages aléatoires.
La prédiction a la forme d'une réponse stockée, avec des phases tirées de la liste du schéma, l'un des résultats du schéma et une courbe de récompense de 50 points dans reward_range, pour les couches que montre le schéma. La prédiction préremplit la chronologie et est stockée une fois que l'annotateur modifie la chronologie. La cause d'échec et la consigne sont laissées à l'annotateur. Le score principal sur items réservés est le F1 macro des phases sur une grille de 0,1 seconde. L'exécution rapporte aussi le F1 des segments de phases à IoU 0,5, la justesse du résultat et le r de Pearson de la courbe de récompense là où une courbe a été tracée. Un schéma sans phases prend la justesse du résultat comme score principal, puis la corrélation de la récompense. L'exécution demande au moins 5 épisodes annotés dans la partition train. Potato n'a pas de module d'entraînement pour rollout_evaluation, car une préférence sur des déroulements compare des vidéos et episode-model ne lit aucune vidéo.
Lancer une exécution et vérifier le résultat
Redémarrez le serveur après avoir ajouté model_training :
potato start config.yaml -p 8000Ouvrez /admin/training, choisissez le schéma et le module d'entraînement, puis cliquez sur Train now. La page ne propose que les modules adaptés à chaque schéma, et un module non installé est listé avec la mention « not installed » et la commande d'installation. Lorsque l'exécution se termine, Potato liste le score sur items réservés dans le tableau Runs, avec la partition et la métrique dans une infobulle. La page de l'exécution liste chaque métrique et la partition de chaque item. Le rapport d'écriture en retour de GET /admin/training/api/status compte les prédictions publiées et celles que chaque vérification a retenues, par exemple n_skipped_low_confidence.
Les pré-étiquettes ancrent les annotateurs sur la réponse du modèle, de sorte qu'il faut activer include_unlabeled dans une nouvelle étude seulement une fois que le score sur items réservés justifie de montrer les réponses du modèle. Relire les pré-étiquettes du modèle dans la boucle traite de la présentation des pré-étiquettes les moins sûres en premier et du réentraînement sur les corrections, et Configuration liste chaque clé, les backends et les vérifications de l'écriture en retour.
Pour aller plus loin
- Vue d'ensemble de l'entraînement de modèles
- Tous les modules d'entraînement
- Structures chimiques, spectres et séries temporelles
- Annotation d'épisodes de robots et le guide des épisodes de robots
- Potato pour la chimie, la physiologie et la robotique
- Étiquetage assisté par modèle
- Référence en amont pour
rdkit-property,peak-cnn,signal-cnnetepisode-model
Références
- Ismail Fawaz, H., Lucas, B., Forestier, G., Pelletier, C., Schmidt, D. F., Weber, J., Webb, G. I., Idoumghar, L., Muller, P.-A., and Petitjean, F. (2020). InceptionTime: Finding AlexNet for Time Series Classification. Data Mining and Knowledge Discovery, 34(6), 1936-1962. https://doi.org/10.1007/s10618-020-00710-y
- Rogers, D., and Hahn, M. (2010). Extended-Connectivity Fingerprints. Journal of Chemical Information and Modeling, 50(5), 742-754. https://doi.org/10.1021/ci100050t