T ext A ttack: Lessons learned in designing Python frameworks for NLP (2020)

Abstract: TextAttack is an open-source Python toolkit for adversarial attacks, adversarial training, and data augmentation in NLP. TextAttack unites 15+ papers from the NLP adversarial attack literature into a single framework, with many components reused across attacks. This framework allows both researchers and developers to test and study the weaknesses of their NLP models. To build such an open-source NLP toolkit requires solving some common problems: How do we enable users to supply models from different deep learning frameworks? How can we build tools to support as many different datasets as possible? We share our insights into developing a well-written, well-documented NLP Python framework in hope that they can aid future development of similar packages.

## introduction deep neural network (dnn) models have seen dominant use in nlp tasks such text classification, natural language inference, machine translation, and question answering. however, despite their state-of-the-art performance, nlp dnns are still vulnerable to adversarial attacks @xcite . as a result, there have been growing efforts to develop tools that can help researchers and developers better understand the capability of their nlp models. both @xcite and @xcite introduced web-based visual interactive tools that enable users to see model's local explanations. @xcite introduced a behavioral testing framework that runs a suite of tests to sanity check nlp models. one of the challenges for building such tools is that the tool should be flexible enough to work with many different deep learning frameworks (e.g. pytorch, tensorflow, scikit-learn). also, the tool camembert @xcite and its tokenizer are initialized using huggingface transformers @xcite and wrapped in textattack model wrappers. adversarial attack is pwws @xcite modified to use wordnet in french @xcite instead of english. textattack's flexible api makes these customizations possible in just a few lines of code. we developed textattack, an open-source python framework for adversarial attacks, adversarial training, and data augmentation. our modular and extendable design allows us to reuse many components to offer 15+ different adversarial attack methods proposed by literature. our modelagnostic and dataset-agnostic design allows users to easily run adversarial attacks against their own models built using any deep learning framework. this paper describes some lessons learned along the path to creating textattack. figure 1 shows our api in action. our advice is tailored towards researchers developing nlp libraries in python that support a variety of models and datasets, and use them for downstream applications. we provide the following broad advice to help other future developers create user-friendly nlp libraries in python: ## model agnosticism there are growing number of deep learning frameworks and different researchers and groups have preferences about which frameworks to use for different tasks. unless the library relates to model training or development (and sometimes then), it is possible to build a library that supports deep learning models from any framework. textattack supports both black-box and whitebox attacks on nlp models. black-box attacks can only access the model for inference. in essence, the attack sends lists of text to the model and receives predictions. model predictions come as lists of floats (for classification), strings, or dictionaries. no other information about the model is required. from the start, we wanted textattack to work on models from any framework, without too much headache. ## data agnosticism another goal of textattack was to be able to run the same attack on any dataset. this has obvious benefits: two attacks that report results on different datasets can easily be compared with textattack. ## model output flexibility with goalfunction with the proper input and ouput columns and a corresponding model, adversarial attacks can be run on any dataset on any model. models may have different output formats. for example, a sentiment classifier would produces a list of the probabilities of each class, while a sequence-to-sequence models produce a text output. task-specific subclasses of the textattack goalfunction class allow adversarial attack goal functions to be defined at a high level, such that the same goal function can be used for any model with the same output type. for example, the minimizebleuscore goal function attempts to minimize the bleu score @xcite between the correct output and the output the model produces for a given perturbation. this goal function only assumes that the model output a prediction as a string. given this design pattern, the minimizebleuscore goal function can be applied to attack any sequence-tosequence model. similar goal functions can be designed for other output formats, like classification models or sentence taggers. ## common functions for text inputs with attackedtext across textattack modules, some functionality is required over and over again. many transformations want to split text inputs into a list of words. many constraints require part-of-speech tagging. we want to avoid repeating code in too many places, and also to set a standard as to which tokenization, part-of-speech tagger, etc. is used. therefore, with the exception of models (which take string inputs), textattack modules operate on attackedtext objects -not vanilla python strings. the attackedtext contains string functionality that performs word replacement, prepares text to input to the model, prints inputs along with their column names, and manages attack-specific context attributes. it is relatively common for nlp libraries to provide some base class that provides additional functionality to what are essentially enhanced string objects. for example, flair @xcite performs text-level operations on a sentence class. textattack follows a similar strategy and stores each text input as an attackedtext object. ## improving performance model inference memoization adversarial attacks in nlp spend most of their time on the gpu. for each text input, the attack must obtain the model's output, as well as the output of any models used to apply certain linguistic constraints, like a sentence encoder to ensure semantic similarity between adversarial example and the original text. upon further examination, many of these model inferences appear over and over again during the attack process. for example, the attack needs to compute the model's score for an input that has already been seen. some population-based stochastic search methods, like the genetic algorithm of @xcite , may revisit the same input multiple times during the search process, which increases the number of redundant computations. textattack caches model outputs to avoid redundant computations. this is done using a leastrecently-used (lru) function cache. since outputs are generally small, textattack can maintain a very large lru cache for each purpose without using an excessive amount of memory. in some cases, this high-level caching can cause a significant performance increase. we experimented with attacking 100 samples for bert-base model @xcite trained on sst-2 dataset @xcite using methods proposed by @xcite and @xcite . ## conclusion writing an excellent, well-documented library that is easy to install and run is a good way to get researchers interested in a research topic as it lowers the barriers to entry. moreover, a well-structured, extendable design empowers newcomers to make their contributions to the field. we hope that our lessons from developing textattack will help others create user-friendly open-source nlp libraries.