T5X ist die neue und verbesserte Implementierung von T5 (und mehr) in Jax und Flachs. T5 auf Tensorflow mit Meshtf ist nicht mehr aktiv entwickelt. Wenn Sie neu bei T5 sind, empfehlen wir, mit T5X zu beginnen.
Die t5
Bibliothek dient in erster Linie als Code für die Reproduktion der Experimente zur Erforschung der Grenzen des Transferlernens mit einem einheitlichen Text-zu-Text-Transformator . In dem Papier zeigen wir, wie hochmoderne Ergebnisse bei mehreren NLP-Aufgaben unter Verwendung eines auf einem großen Textkorpus vorgebrachten Text-zu-Text-Transformators erzielt werden können.
Der Großteil des Codes in diesem Repository wird zum Laden, Vorverarbeitung, Mischen und Bewerten von Datensätzen verwendet. Es bietet auch eine Möglichkeit, die vorgeborenen Modelle mit der Veröffentlichung zu optimieren.
Die t5
Bibliothek kann für die zukünftige Modellentwicklung verwendet werden, indem nützliche Module für Trainings- und Feinabstimmungsmodelle (potenziell riesige ) Modelle für Mischungen von Text-zu-Text-Aufgaben bereitgestellt werden.
t5.data
ist ein Paket zum Definieren von Task
, die tf.data.Dataset
s liefern.
Jede Task
besteht aus:
Darüber hinaus können Sie optional angeben:
Die Datenquelle kann eine willkürliche Funktion sein, die ein tf.data.Dataset
liefert. Wir bieten jedoch auch einfachere Verpackungen für Datensätze, die in TensorFlow -Datensätzen (TFDS) (TFDStask) ( TfdsTask
) verfügbar sind oder als Textdateien mit einem Beispiel pro Zeile (ein TextLineTask
) gespeichert sind .
Der Textvorprozessor konvertiert die Beispiele im Quelldatensatz in das entsprechende Format für ein Text-zu-Text-Modell mit Feldern für inputs
und targets
. Zum Beispiel wandelt die vordefinierte t5.data.preprocessors.translate
-Präprozessor Eingänge in der Form um
{ 'de' : 'Das ist gut.' , 'en' : 'That is good.' }
zur Form
{ 'inputs' : 'translate German to English: Das ist gut.' , 'targets' : 'That is good.' }
Zusätzlich zur Vorverarbeitung von Text können Sie auch einen oder mehrere Token-Präprozessoren verwenden, um die Eingaben nach der Umstimmung zu ändern. Wir haben unsere unbeaufsichtigten Voraussetzungsziele mit diesen Token-Präprozessoren implementiert.
Wir bieten viele vordefinierte Präprozessoren in t5.data.preprocessors
, können aber auch Ihre eigenen definieren.
Das Satzstückmodell wird verwendet, um die Eingangszeichenfolgen zu token und die Ausgangs -Token zu dekodieren. Sie können Ihr eigenes Modell mit der Google/Surepiece -Bibliothek erstellen oder unsere Standardeinstellung unter t5.data.DEFAULT_SPM_PATH
verwenden. Wenn Sie Ihre eigenen erstellen, müssen Sie die Flags --pad_id=0 --eos_id=1 --unk_id=2 --bos_id=-1
mit spm_train
verwenden, um mit unserem Modellcode kompatibel zu sein.
Die Metrikfunktion gibt eine Bewertung angesichts des Ziels und der Vorhersage aus dem Modell zurück. Sie können auch eine Postprozessfunktion definieren, um das Ziel- und Vorhersagetext in ein anderes Format umzuwandeln, bevor Sie die Metrik aufrufen. Wir bieten einige vordefinierte Metriken in t5.evaluation.metrics
.
Schließlich enthält t5.data
eine Mixture
, die so instanziiert werden kann, dass sie mehrere Task
für Multi-Task-Training unter Verwendung verschiedener Funktionen zum Angeben der Mischraten kombinieren können.
t5.evaluation
enthält zwei Kernkomponenten:
t5.models
enthält Scheiben zum Anschließen von T5 Tasks
und Mixtures
mit einer Modellimplementierung für Schulungen, Bewertung und Inferenz.
Derzeit sind zwei SCHWEISE VERFAHREN: einen für den Mesh Tensorflow -Transformator, den wir in unserem Papier verwendet haben, und eine für die Umarmungsgesichts -Transformers -Bibliothek. Die umarmende Face-API ist derzeit experimentell und verändert sich, bietet jedoch eine einfache und einfache Möglichkeit, unsere vorgebildeten Modelle mit Pytorch auf einer einzelnen GPU zu laden, zu optimieren und zu bewerten. Wenn Sie unsere größten Modelle für TPUs verwenden und die Ergebnisse in unserem Papier reproduzieren möchten, sollten Sie die MTFModel -API und den Binär t5_mesh_transformer
verwenden. Wenn Sie unsere Modelle mit einer GPU in Pytorch interessieren, sollten Sie die HFPyTorchmodel-API probieren. Da das Hfpytorchmodel experimentell ist, wird der Rest dieses Readme die Verwendung des MTFModel und dessen assoziierter Binärer angenommen. Ein Nutzungsbeispiel für Hfpytorchmodel ist hier erhältlich.
Der einfachste Weg, T5 auszuprobieren, ist eine kostenlose TPU in unserem Colab -Tutorial.
Im Folgenden geben wir Beispiele für die Voraussetzung, Feinabstimmung, Bewertung und Dekodierung eines Modells aus der Befehlszeile mit unserer Codebasis. Sie können diese Anweisungen verwenden, um unsere Ergebnisse zu reproduzieren, einen unserer freigegebenen Kontrollpunkte mit Ihren eigenen Daten und/oder Hyperparametern zu optimieren oder ein Modell von Grund auf neu zu verarbeiten.
Sie können entweder eine neue oder bereits bestehende Task
verwenden oder Beispiele aus einer vorverarbeiteten TSV-Datei laden.
Task
Abhängig von Ihrer Datenquelle (siehe oben) müssen Sie Ihre Daten entsprechend vorbereiten.
Task
Wenn Sie eine Vanille -Aufgabe verwenden, stellen Sie einfach sicher, dass die von Ihrem dataset_fn
geladenen Dateien für die TPU (dh in einem GCS -Eimer) zugänglich sind, und Sie sollten gut gehen!
TfdsTask
Die meisten unserer vordefinierten Task
verwenden TensorFlow -Datensätze (TFDS) als Datenquelle. Wenn Sie unser Training Binary (siehe Anweisungen unten) mit einem TfdsTask
ausführen, wird der Datensatz automatisch heruntergeladen und bei seiner ersten Verwendung vorbereitet. Nach Abschluss der Vorbereitung wird der Datensatz in Ihren lokalen Speicher zwischengespeichert, um diesen Overhead in zukünftigen Läufen zu vermeiden. Wenn wir in der Cloud arbeiten, empfehlen wir Ihnen, das Flag --t5_tfds_data_dir
festzulegen, um auf einen anhaltenden Speicherort wie einen GCS -Eimer zu verweisen. Dies ist eine Voraussetzung für das Training auf TPU.
Der C4-Datensatz, den wir für unbeaufsichtigte Vorausbildung erstellt haben, ist in TensorFlow-Datensätzen verfügbar. Für das Herunterladen der RAW Common Crawl-Kratzer (~ 7 TB) und Berechnung für seine Vorbereitung (~ 335 CPU-Tage) sind jedoch eine erhebliche Menge an Bandbreite erforderlich. Wir empfehlen Ihnen, die Apache -Strahl -Unterstützung in TFDs zu nutzen, die eine verteilte Vorverarbeitung des Datensatzes ermöglicht und auf Google Cloud DataFlow ausgeführt werden kann. Bei 500 Arbeitern sollte der Job in ~ 16 Stunden abgeschlossen werden.
Nachdem Sie MY_PROJECT
und MY_BUCKET
angemessen definiert haben, können Sie den Datensatz in DataFlow von GCP mit den folgenden Befehlen erstellen:
pip install tfds-nightly[c4]
echo ' tfds-nightly[c4] ' > /tmp/beam_requirements.txt
python -m tensorflow_datasets.scripts.download_and_prepare
--datasets=c4/en
--data_dir=gs:// $MY_BUCKET /tensorflow_datasets
--beam_pipeline_options= " project= $MY_PROJECT ,job_name=c4,staging_location=gs:// $MY_BUCKET /binaries,temp_location=gs:// $MY_BUCKET /temp,runner=DataflowRunner,requirements_file=/tmp/beam_requirements.txt,experiments=shuffle_mode=service,region= $MY_REGION "
Lesen Sie mehr in den Anweisungen für TFDS Beam.
TextLineTask
Eine TextLineTask
ist nützlich, wenn Ihre Datenquelle eine Textdatei (oder Dateien) mit einem Beispiel pro Zeile ist. Sie können dann einen Textvorprozessor verwenden, um jede Zeile in ein Wörterbuch mit Eingängen und Zielen umzuwandeln.
Stellen Sie sicher, dass Ihre Dateien für die TPU zugänglich sind (dh in einem GCS -Eimer), und Sie sollten gut gehen!
Anstatt eine neue Task
zu definieren, können Sie eine TSV -Datei (oder Dateien) direkt als Dataset verwenden, in der jede Zeile als <input>t<target>
formatiert ist.
Es gibt jedoch einige Einschränkungen:
Wenn Sie eine dieser Funktionen benötigen, müssen Sie eine neue Task
, TfdsTask
oder TextLineTask
definieren.
Ähnlich wie bei den oben genannten Fällen müssen Ihre TSV -Dateien für die TPU zugänglich sein (dh in einem GCS -Eimer).
Um das T5 -Paket zu installieren, führen Sie einfach aus:
pip install t5[gcp]
Sie müssen zunächst einen virtuellen Computer (VM) auf Google Cloud starten. Details zum Starten der VM finden Sie in der Google Cloud -Dokumentation.
Um das Training oder die Bewertung von Cloud -TPUs auszuführen, müssen Sie die folgenden Variablen basierend auf Ihrem Projekt, Zone und GCS -Bucket angemessen einrichten. Weitere Informationen finden Sie im Cloud TPU QuickStart Guide.
export PROJECT=your_project_name
export ZONE=your_project_zone
export BUCKET=gs://yourbucket/
export TPU_NAME=t5-tpu
export TPU_SIZE=v3-8
export DATA_DIR= " ${BUCKET} /your_data_dir "
export MODEL_DIR= " ${BUCKET} /your_model_dir "
Bitte verwenden Sie den folgenden Befehl, um ein TPU -Gerät in der Cloud -VM zu erstellen.
ctpu up --name= $TPU_NAME --project= $PROJECT --zone= $ZONE --tpu-size= $TPU_SIZE
--tpu-only --noconf
In dem folgenden Befehl trainieren wir ein Modell auf der MRPC -Aufgabe der Kleber -Benchmark von Grund auf neu. Sie können den Parameter MIXTURE_NAME
Gin ändern, um die in unserem Paket bereitgestellten Aufgaben oder Gemische zu verwenden.
t5_mesh_transformer
--tpu= " ${TPU_NAME} "
--gcp_project= " ${PROJECT} "
--tpu_zone= " ${ZONE} "
--model_dir= " ${MODEL_DIR} "
--t5_tfds_data_dir= " ${DATA_DIR} "
--gin_file= " dataset.gin "
--gin_file= " models/bi_v1.gin "
--gin_param= " utils.tpu_mesh_shape.model_parallelism = 1 "
--gin_param= " utils.tpu_mesh_shape.tpu_topology = ' ${TPU_SIZE} ' "
--gin_param= " MIXTURE_NAME = 'glue_mrpc_v002' "
Die vollständige Liste der Aufgaben und Mischungen kann durch Laufen erhalten werden:
python -c " import t5; print(t5.data.MixtureRegistry.names()) "
Sie können auch zusätzliche Aufgaben und Mischungen in einer neuen Datei definieren und sie mit dem Flag --module_import
importieren.
Alternativ können Sie mit einer TSV -Datei trainieren, in der jede Zeile als <input>t<target>
formatiert wird (siehe oben).
Um eines unserer vorgeborenen Modelle zu optimieren, müssen Sie die operative Konfiguration des vorgebildeten Modells an das Trainingsskript übergeben. Die operative Konfiguration sollte als gin_file
-Flag übergeben werden. Es gibt die Modellarchitektur und andere Hyperparameter an. Darüber hinaus müssen Sie die Mischung angeben, um sie zu optimieren. Um das T5-Small-Modell auf der Mischung glue_mrpc_v002
beispielsweise zu optimieren, reiten Sie bitte:
t5_mesh_transformer
--tpu= " ${TPU_NAME} "
--gcp_project= " ${PROJECT} "
--tpu_zone= " ${ZONE} "
--model_dir= " ${MODEL_DIR} "
--t5_tfds_data_dir= " ${DATA_DIR} "
--gin_file= " dataset.gin "
--gin_param= " utils.tpu_mesh_shape.model_parallelism = 1 "
--gin_param= " utils.tpu_mesh_shape.tpu_topology = ' ${TPU_SIZE} ' "
--gin_param= " MIXTURE_NAME = 'glue_mrpc_v002' "
--gin_file= " gs://t5-data/pretrained_models/small/operative_config.gin "
Der korrekte PREAK-Checkpoint-Pfad ist in der operativen Konfiguration enthalten.
Sie können auch zusätzliche Aufgaben und Mischungen in einer neuen Datei definieren und sie mit dem Flag --module_import
importieren.
Alternativ können Sie mit einer TSV-Datei, in der jede Zeile als <input>t<target>
(siehe oben) formatiert wird, fein abstellen. Sie können beispielsweise eines der gepaarten Übersetzungsdatensätze aus WMT '19 News Commentary 14 Training Set (z. B. Englisch-Französisch) ausprobieren. Wenn Sie eine TSV -Datei verwenden, ersetzen Sie das Flag MIXTURE_NAME
durch:
--gin_param= " utils.run.train_dataset_fn = @t5.models.mesh_transformer.tsv_dataset_fn "
--gin_param= " tsv_dataset_fn.filename = 'gs:/path/to/tsv' "
Um mit den gleichen Hyperparametern zu optimieren, die wir in dem Papier verwendet haben (unter Verwendung einer konstanten Lernrate von 0,001), können Sie diese GIN-Datei übergeben, die im T5-Paket enthalten ist:
--gin_file="learning_rate_schedules/constant_0_001.gin"
Die operative Konfiguration für die vorgebreiteten Modelle ist so eingestellt, dass die Anzahl der Zugschritte effektiv keine Grenze gibt. Wenn Sie für eine bestimmte Anzahl von Schritten trainieren möchten, müssen Sie dies eingeben. Da das vorgebildete Modell bereits für 1.000.000 Schritte geschult wurde, sollten Sie die Gesamtzahl der Schritte nach der Voraussetzung und nach dem Training und für Feinabstimmung. Wenn Sie beispielsweise für weitere 10.000 Schritte eine Feinabstimmung erhalten möchten, sollten Sie bestehen
--gin_param="run.train_steps = 1010000"
Sie können auch eine andere Chargengröße für die Feinabstimmung verwenden. Wir setzen die Chargengröße gemäß der Gesamtzahl der Token in einer Charge. Standardmäßig verwendet eine Stapel eine Sequenzlänge von 512. Um die Anzahl der Token in einer Stapel festzulegen, sollten Sie festlegen
--gin_param = "tokens_per_batch=1048576"
Um ein Modell im T5 -Framework zu bewerten, müssen Sie die eval.gin
-Datei verwenden, das Modellverzeichnis, die Dekodierungsmethode und die für die Bewertung des Checkpoint -Schrittes angeben. Um die Aufgabe der Kleber -MRPC mit der Beam -Suche auf allen Checkpoints zu bewerten, verwenden Sie den folgenden Befehl:
t5_mesh_transformer
--tpu= " ${TPU_NAME} "
--gcp_project= " ${PROJECT} "
--tpu_zone= " ${ZONE} "
--model_dir= " ${MODEL_DIR} "
--gin_file= " ${MODEL_DIR} /operative_config.gin "
--t5_tfds_data_dir= ${DATA_DIR}
--gin_file= " eval.gin "
--gin_file= " beam_search.gin "
--gin_param= " run.dataset_split = 'validation' "
--gin_param= " utils.tpu_mesh_shape.tpu_topology = ' ${TPU_SIZE} ' "
--gin_param= " MIXTURE_NAME = 'glue_mrpc_v002' "
--gin_param= " eval_checkpoint_step = 'all' "
Um einen bestimmten Checkpoint zu bewerten, legen Sie einfach den Parameter eval_checkpoint_step
auf den entsprechenden Checkpoint fest.
--gin_param="eval_checkpoint_step = 100000"
Sie können auch greedy_decode.gin
oder sample_decode.gin
anstelle von beam_search.gin
im obigen Befehl verwenden.
Um Vorhersagen aus einem Modell im T5 -Framework zu erstellen, müssen Sie das Modellverzeichnis, die Dekodierungsmethode und die für die Dekodierung verwenden. Unter der Annahme, dass Sie eine Textdatei mit Eingabemaßnahmen haben, die at /path/to/inputs.txt
gespeichert sind, wäre ein Beispielbefehl:
t5_mesh_transformer
--tpu= " ${TPU_NAME} "
--gcp_project= " ${PROJECT} "
--tpu_zone= " ${ZONE} "
--model_dir= " ${MODEL_DIR} "
--gin_file= " ${MODEL_DIR} /operative_config.gin "
--gin_file= " infer.gin "
--gin_file= " sample_decode.gin "
--gin_param= " input_filename = '/path/to/inputs.txt' "
--gin_param= " output_filename = '/tmp/outputs.txt' "
--gin_param= " utils.tpu_mesh_shape.tpu_topology = ' ${TPU_SIZE} ' "
--gin_param= " infer_checkpoint_step = 'all' "
Um mit einem bestimmten Checkpoint vorherzusagen, legen Sie einfach den Parameter infer_checkpoint_step
auf den entsprechenden Checkpoint fest.
--gin_param="infer_checkpoint_step = 100000"
Sie können auch beam_search.gin
oder greedy_decode.gin
anstelle von sample_decode.gin
im obigen Befehl verwenden.
Möglicherweise möchten Sie auch ein SavedModel
exportieren, das für die Serviertage Ihres geschulten Modells (z. B. beim Bereitstellen mit ML Engine oder in einem Docker -Bild) nützlich ist.
t5_mesh_transformer
--gcp_project= " ${PROJECT} "
--tpu_zone= " ${ZONE} "
--model_dir= " ${MODEL_DIR} "
--use_model_api
--mode= " export_predict "
--export_dir= " /path/to/export/dir "
Der obige Befehl exportiert den neuesten Checkpoint im Modellverzeichnis. Um einen bestimmten Kontrollpunkt zu exportieren, fügen Sie die folgenden Flags hinzu:
--checkpoint_mode= " specific "
--checkpoint_steps=1000000
Das T5-Deploy-Notizbuch demonstriert das Exportieren eines SavedModel
und das Verpacken von Docker-Bild zum Servieren.
Wenn Sie GPU anstelle von TPUs verwenden möchten, können Sie die obigen Befehle ändern, indem Sie TPU-spezifische Flags ( --tpu
, --tpu_zone
, --gcp_project
) entfernen und die GIN-Params für mesh_shape
und mesh_devices
basierend auf Ihrem gewünschten Setup festlegen .
Wenn Ihre Maschine beispielsweise Zugriff auf 6 GPUs hat und Sie 3-Wege-Modellparallelität und 2-Wege-Datenparallelität durchführen möchten, wird der oben genannte Feinabstimmungsbefehl:
t5_mesh_transformer
--model_dir= " ${MODEL_DIR} "
--t5_tfds_data_dir= " ${DATA_DIR} "
--gin_file= " dataset.gin "
--gin_param= " utils.run.mesh_shape = 'model:3,batch:2' "
--gin_param= " utils.run.mesh_devices = ['gpu:0','gpu:1','gpu:2','gpu:3','gpu:4','gpu:5'] "
--gin_param= " MIXTURE_NAME = 'glue_mrpc_v002' "
--gin_file= " gs://t5-data/pretrained_models/small/operative_config.gin "
Mit einer einzelnen GPU lautet der Befehl:
t5_mesh_transformer
--model_dir= " ${MODEL_DIR} "
--t5_tfds_data_dir= " ${DATA_DIR} "
--gin_file= " dataset.gin "
--gin_param= " utils.run.mesh_shape = 'model:1,batch:1' "
--gin_param= " utils.run.mesh_devices = ['gpu:0'] "
--gin_param= " MIXTURE_NAME = 'glue_mrpc_v002' "
--gin_file= " gs://t5-data/pretrained_models/small/operative_config.gin "
Wir bieten operative Konfigurationen für alle Experimente in der Arbeit in GS: // T5-DATA/Experimenten. Der experiments
hat unterschiedliche Unterverzeichnisse, die den verschiedenen Abschnitten in unserem Artikel entsprechen. Zum Beispiel enthält GS: // T5-DATA/Experimente/Ziele die Experimente aus Abschnitt 3.3 ("unbeaufsichtigte Ziele"). Jedes Unterverzeichnis des objectives
-Ordners enthält operative Konfigurationen für ein bestimmtes Experiment (wo ein "Experiment" lose sprechend eine der Zeilen in einem der Tabellen in unserem Artikel ist).
Angenommen, Sie möchten die Ergebnisse für das Ziel "Präfix -Sprache" (die erste Zeile in Tabelle 4) reproduzieren. Die operativen Konfigurationen für dieses Experiment live in GS: // T5-DATA/Experimente/Ziele/obj-prefix_lm. Im Basisverzeichnis befindet sich eine operative Konfiguration für das Voraussetzen des Modells (gs: //t5-data/experiments/objective/obj-prefix_lm/operative_config.gin). Dann gibt es für jeden der nachgeschalteten Feinabstimmungsmischungen Unterverhandlungen, von denen jede eine eigene operative Konfiguration hat (z. B. gs: //t5-data/experiments/objectives/obj-prefix_lm/cnn_dailymail_v002/operative_config.gin. ). Um dieses Experiment auszuführen, verarbeiten Sie zunächst ein Modell mit der operativen Konfiguration vor dem Training:
export PRETRAIN_MODEL_DIR= " ${BUCKET} /obj-prefix_lm "
t5_mesh_transformer
--tpu= " ${TPU_NAME} "
--gcp_project= " ${PROJECT} "
--tpu_zone= " ${ZONE} "
--model_dir= " ${PRETRAIN_MODEL_DIR} "
--gin_file= " gs://t5-data/experiments/objectives/obj-prefix_lm/operative_config.gin "
--gin_param= " utils.tpu_mesh_shape.model_parallelism = 1 "
--gin_param= " utils.tpu_mesh_shape.tpu_topology = ' ${TPU_SIZE} ' "
Dann können Sie das vorgebildete Modell auf CNN/Daily Mail wie SO fein abstellen:
export FINETUNE_MODEL_DIR= " ${BUCKET} /obj-prefix_lm/cnn_dailymail_v002 "
t5_mesh_transformer
--tpu= " ${TPU_NAME} "
--gcp_project= " ${PROJECT} "
--tpu_zone= " ${ZONE} "
--model_dir= " ${FINETUNE_MODEL_DIR} "
--gin_file= " gs://t5-data/experiments/objectives/obj-prefix_lm/cnn_dailymail_v002/operative_config.gin "
--gin_param= " init_checkpoint = ' ${PRETRAIN_MODEL_DIR} /model.ckpt-524288' "
--gin_param= " utils.tpu_mesh_shape.model_parallelism = 1 "
--gin_param= " utils.tpu_mesh_shape.tpu_topology = ' ${TPU_SIZE} ' "
Einige Trainingsvarianten benötigen mehrere Flags, um gleichzeitig festgelegt zu werden. Fügen Sie für jede der folgenden Varianten die FLAGS -Gruppe zu ./third_party/py/t5/google/scripts/run_finetune.sh
hinzu.
Deterministisches Training
--train_gin_param= " mesh_train_dataset_fn.seed= ${SEED} "
--train_gin_param= " utils.run.skip_seen_data = True "
Sprachmodell
--objective= " lm "
--train_gin_param= " utils.run.model_type = " lm " "
Wir haben die folgenden Checkpoints für vorgebreitete Modelle veröffentlicht, die in unserem Artikel beschrieben wurden:
Eine Liste zusätzlicher experimenteller vorgebildeter Modellkontrollpunkte finden Sie hier.
Wenn Sie diese Arbeit erweitern oder verwenden, zitieren Sie bitte das Papier, in dem es eingeführt wurde:
@article { 2020t5 ,
author = { Colin Raffel and Noam Shazeer and Adam Roberts and Katherine Lee and Sharan Narang and Michael Matena and Yanqi Zhou and Wei Li and Peter J. Liu } ,
title = { Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer } ,
journal = { Journal of Machine Learning Research } ,
year = { 2020 } ,
volume = { 21 } ,
number = { 140 } ,
pages = { 1-67 } ,
url = { http://jmlr.org/papers/v21/20-074.html }
}