Package: adaptor
Adaptor: Objective-centric Adaptation libraryAdaptor will help you to easily adapt a language model to your owndata domain(s),task(s),
orcustom objective(s).If you want to jump right in, take a look at thetutorials.Table of ContentClick to expandBackgroundBenefits of Task and Domain AdaptationHow Can Adaptor HelpUsageInstallUse-casesTutorialsHow to ContributeCiteBenefits of Task and Domain AdaptationBoth domain adaptation (e.g.Beltagy, 2019)
and task adaptation (e.g.Gururangan, 2020)
are reported to improve quality of the language models on end tasks,
and improve model's comprehension on morenichedomains,
suggesting that it's usually a good idea to adapt pre-trained model before the final fine-tuning.
However, it is still not a common practice, maybe because it is still a tedious thing to do. In the model-centric training, the multi-step,
or multi-objective training requires a separate configuration of every training step due to the differences in the models'
architectures specific to the chosen training objective and data set.How Adaptor handles training?Adaptor framework abstracts the term ofObjectiveaway from the model.
With Adaptor,Anyobjective can be applied toanymodel, for as long as the trained model has someheadof a compatible shape.The ordering in which theObjectives are applied is determined by the givenSchedule.
In conventional adaptation, the objectives are appliedsequentially(that's whatSequentialScheduledoes),
but they might as well be applied in a combilation (ParallelSchedule), or balanced dynamically,
e.g. according to its objectives` losses.In theAdaptorframework, instead of providing theTrainerwith a model encoded dataset both compatible
with specific training task,
a user constructs aSchedulecomposed of the initialisedObjectives, where each Objective performs its
dataset sampling and objective-specific feature alignment (compliant withobjective.compatible_head).When training classictransformersmodels, a selection of objectives is model-agnostic: each objective takes care
of resolving its own compatible head within givenLangModule.How Can Adaptor HelpAdaptor introduces objective-centric, instead of model-centric approach to the training process,
that makes iteasierto experiment withmulti-objectivetraining, creatingcustom objectives. Thanks to that, you can do some things,
that are difficult, or impossible in other NLP frameworks (like HF Transformers, FairSeq or NLTK). For example:Domain adaptationorTask adaptation: you do not have to handle the model
between different training scripts, minimising a chance of error and improving reproducibilitySeamlessly experiment with differentschedulestrategies, allowing you, e.g. to backpropagate based
on multiple objectives in every training stepTrack the progressof the model, concurrently oneachrelevant objective, allowing you to easier
recognise weak points of your modelEasily performMulti-task learning, which thatcanimproves model robustnessAlthough Adaptor aims primarily for training the models of the transformer family, the library is designed to
work withany PyTorch modelBuilt upon the well-established and maintained 🤗 Transformers library, Adaptor will automatically support
future new NLP models out-of-box. The upgrade of Adaptor to a different version of Hugging Face Transformers library
should not take longer than a few minutes.UsageFirst, install the library:pipinstalladaptorIf you clone it, you can also run and modify the provided example scripts.gitclone{thisrepo}cdadaptor
python-mpipinstall-e.You can also find and run full examples below with all the imports intests/end2end_usecases_test.py.Adapted Named Entity RecognitionSay you have nicely annotated entities in a set of news articles, but eventually, you want to use the language model
to detect entities in office documents. You can either train the NER model on news articles, hoping that
it will not lose much accuracy on other domains. Or you can concurrently train on both data sets:# 1. pick the model baselang_module=LangModule("bert-base-multilingual-cased")# 2. pick objectives# Objectives take either List[str] for in-memory iteration, or a source file path for streamed iterationobjectives=[MaskedLanguageModeling(lang_module,batch_size=16,texts_or_path="tests/mock_data/domain_unsup.txt"),TokenClassification(lang_module,batch_size=16,texts_or_path="tests/mock_data/ner_texts_sup.txt",labels_or_path="tests/mock_data/ner_texts_sup_labels.txt")]# 3. pick a schedule of the selected objectives# This one will initially fit the first objective until convergence on its eval set, then fits the second oneschedule=ParallelSchedule(objectives,training_arguments)# 4. Run the training using Adapter, similarly to running HF.Trainer, only adding `schedule`adapter=Adapter(lang_module,schedule,training_arguments)adapter.train()# 5. save the trained lang_module (with all heads)adapter.save_model("entity_detector_model")# 6. reload and use it like any other Hugging Face modelner_model=AutoModelForTokenClassification.from_pretrained("entity_detector_model/TokenClassification")tokenizer=AutoTokenizer.from_pretrained("entity_detector_model/TokenClassification")inputs=tokenizer("Is there any Abraham Lincoln here?",return_tensors="pt")outputs=ner_model(**inputs)ner_tags=[ner_model.config.id2label[label_id.item()]forlabel_idinoutputs.logits[0].argmax(-1)]Try this exampleon real data, intutorials/adapted_named_entity_recognition.ipynbAdapted Machine TranslationSay you have a lot of clean parallel texts for news articles (like you can find onOPUS),
but eventually, you need to translate a different domain, for example chats with a lot of typos,
or medicine texts with a lot of latin expressions.# 1. pick the base modellang_module=LangModule("Helsinki-NLP/opus-mt-en-de")# (optional) pick train and validation evaluators for the objectivesseq2seq_evaluators=[BLEU(decides_convergence=True)]# 2. pick objectives - we use BART's objective for adaptation and mBART's seq2seq objective for fine-tuningobjectives=[BackTranslation(lang_module,batch_size=1,texts_or_path="tests/mock_data/domain_unsup.txt",back_translator=BackTranslator("Helsinki-NLP/opus-mt-de-en"),val_evaluators=seq2seq_evaluators),Sequence2Sequence(lang_module,batch_size=1,texts_or_path="tests/mock_data/seq2seq_sources.txt",labels_or_path="tests/mock_data/seq2seq_targets.txt",val_evaluators=seq2seq_evaluators,source_lang_id="en",target_lang_id="cs")]# this one will shuffle the batches of both objectivesschedule=ParallelSchedule(objectives,adaptation_arguments)# 4. train using Adapteradapter=Adapter(lang_module,schedule,adaptation_arguments)adapter.train()# 5. save the trained (multi-headed) lang_moduleadapter.save_model("translator_model")# 6. reload and use it like any other Hugging Face modeltranslator_model=AutoModelForSeq2SeqLM.from_pretrained("translator_model/Sequence2Sequence")tokenizer=AutoTokenizer.from_pretrained("translator_model/Sequence2Sequence")inputs=tokenizer("A piece of text to translate.",return_tensors="pt")output_ids=translator_model.generate(**inputs)output_text=tokenizer.batch_decode(output_ids,skip_special_tokens=True)print(output_text)Try this exampleon real data, intutorials/unsupervised_machine_translation.ipynbSingle-objective trainingIt also makes sense to use the comfort of adaptor high-level interface in simple use-cases
where it's enough to apply one objective.# 1. pick the base modellang_module=LangModule(test_base_models["sequence_classification"])# 2. pick any objective - note that all objectives have almost identical interfaceclassification=SequenceClassification(lang_module=lang_module,texts_or_path="tests/mock_data/supervised_texts.txt",labels_or_path="tests/mock_data/supervised_texts_sequence_labels.txt",batch_size=1)# 3. Schedule choice does not matter in single-objective trainingschedule=SequentialSchedule(objectives=[classification],args=training_arguments)# 4. train using Adapteradapter=Adapter(lang_module=lang_module,schedule=parallel_schedule,args=training_arguments)adapter.train()# 5. save the trained lang_moduleadapter.save_model("output_model")# 6. reload and use it like any other Hugging Face modelclassifier=AutoModelForSequenceClassification.from_pretrained("output_model/SequenceClassification")tokenizer=AutoTokenizer.from_pretrained("output_model/SequenceClassification")inputs=tokenizer("A piece of text to translate.",return_tensors="pt")output=classifier(**inputs)output_label_id=output.logits.argmax(-1)[0].item()print("Your new model predicted class:%s"%classifier.config.id2label[output_label_id])Try this exampleon real data intutorials/simple_sequence_classification.ipynbMore examplesYou can find more examples intutorials. Your contributions are welcome :) (seeCONTRIBUTING.md)Motivation for objective-centric trainingWe've seen that transformers can outstandingly perform on relatively complicated tasks, which makes us
think that experimenting with custom objectives can also improve their desperately-needed
generalisation abilities (many studies report transformers inability to generalise the end task, e.g. onlanguage inference,paraphrase detection, ormachine translation).This way, we're also hoping to enable the easy use of the most accurate deep language models for morespecialised domainsof application, where a little supervised data is available, but
much more unsupervised sources can be found (a typicalDomain adaptationcase).
Such applications include for instance machine translation of non-canonical domains (chats or expert texts) or personal names recognition in texts of a domain with none of its own labeled names, but the use-cases are limitless.How can you contribute?If you want to add a new objective or schedule, seeCONTRIBUTING.md.If you find an issue, please report itin this repositoryand if you'd
also be able to fix it, don't hesitate to contribute and create a PR.If you'd just like to share your general impressions or personal experience with others,
we're happy to get into a discussion in theDiscussions section.Citing AdaptorIf you use Adaptor in your research, please cite it as follows.TextŠTEFÁNIK, Michal, Vít NOVOTNÝ, Nikola GROVEROVÁ and Petr SOJKA. Adaptor: Objective-Centric Adaptation Framework for Language Models. InProceedings of 60th Annual Meeting of the Association for Computational Linguistics: Demonstrations. ACL, 2022. 7 pp.BibTeX@inproceedings{stefanik2022adaptor,author={\v{S}tef\'{a}nik, Michal and Novotn\'{y}, V\'{i}t and Groverov{\'a}, Nikola and Sojka, Petr},title={Adapt\$\mathcal\{O\}\$r: Objective-Centric Adaptation Framework for Language Models},booktitle={Proceedings of 60th Annual Meeting of the Association for Computational Linguistics: Demonstrations},publisher={ACL},numpages={7},url={https://aclanthology.org/2022.acl-demo.26},}If you have any other question(s), feel free to create an issue.