Awesome
Combating Adversarial Misspellings
Code for the following paper.
Combating Adversarial Misspellings with Robust Word Recognition
Danish Pruthi, Bhuwan Dhingra and Zachary C. Lipton
The 57th Annual Meeting of the Association for Computational Linguistics (ACL-19) (To Appear).
Requirements
nltk
dynet
allennlp
torchvision
As we use NLTK stopwords, you might have to download stopwords
$ python3.6
>>> import nltk
>>> nltk.download('stopwords')
Reproducing Results
Attacks (Table 3)
You can attack the already trained BiLSTM (word-only, char-only or word+char) models using swap/drop/key-board/add attacks. To do so use the following command.
CUDA_VISIBLE_DEVICES=0 python3.6 main.py --dynet-seed 1 --mode dev --load model_dumps/bilstm-word-only --attack swap --num-attacks 2 --model
bilstm-char
Upon successfully running this, you would be able to see how a BiLSTM word only model (with an initial test accuracy of 79.19%) is reduced to 63.9% and 53.6% on one and two character swap attacks respectively.
You can change the arguments:
--attack
: the choice of attack. Available options: swap
, drop
, add
, key
, and all
(for exhaustively trying all types of attacks)
--load
: load the pre-trained BiLSTM model. Available options: bilstm-char-only
, bilstm-word-only
, bilstm-word-plus-char
. Note that you would have to select the appropriate option in the --model
flag below.
--model
: the type of the model. Use bilstm-word
, bilstm-char
for word-only and char-only models. If you wish to use the BiLSTM word+char model, use only bilstm
.
--small
: optionally, you can use the small flag to test only on a fraction of the test set (200 examples).
TODO: add pre-trained BERT models.
Defenses (Table 3)
CUDA_VISIBLE_DEVICES python3.6 main.py --dynet-seed 1 --mode dev --load model_dumps/bilstm-word-only --attack swap --num-attacks 2 --model bilstm-word --defense
Upon successfully running this, you would notice that the accuracy is restored to 78+% on 1/2 character swap attacks.
The only difference from the above is the --defense
flag. The default defense is a semi-character based RNN (ScRNN) which reconstructs word with a backoff strategy of passing through words when predicted as UNK
(ScRNN + Pass-Through). If you wish to run ScRNN with other backoff strategies use the following flags
--defense --sc-neutral
: for ScRNN + Neutral
--defense --sc-background
for ScRNN + Background
Baseline Defense
We use ATD
spell-checker as our baseline defense.
Make sure you have the ATD package downloaded and running as
a server on localhost.
Download the source and models from here
Then follow the installation / test instructions here
This will run the ATD server on localhost at 127.0.0.1:1049. Once this is done, you can use the --defense --sc-atd
flag to run the ATD spell checker.
Standalone Usage
You can also use (and train) ScRNN as a defense independently for your use case. To directly use a pretrained ScRNN + PassThrough defense, do the following:
$ cd defenses/scRNN/
$ python3.6
>> from corrector import ScRNNChecker
>> checker = ScRNNChecker()
>> checker.correct_string("nicset atcing I have ever witsesed")
'nicest acting i have ever witnessed'
The above defense was trained on the Stanford Sentiment Treebank (SST corpus).
TODO: add instructions to train defenses on your own corpus.
Note
If you use the code, please consider citing:
@article{pruthi2019combating,
title={Combating Adversarial Misspellings with Robust Word Recognition},
author={Pruthi, Danish and Dhingra, Bhuwan and Lipton, Zachary C},
booktitle = {The 57th Annual Meeting of the Association for Computational Linguistics (ACL)},
address = {Florence, Italy},
month = {July},
year = {2019}
}