Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attack Recipe Implementation - Leap #794

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/3recipes/attack_recipes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Attacks on classification models
14. TextBugger (TextBugger: Generating Adversarial Text Against Real-world Applications)
15. Pruthi (Combating Adversarial Misspellings with Robust Word Recognition 2019)
16. CLARE (Contextualized Perturbation for Textual Adversarial Attack 2020)
17. LEAP (LEAP: Efficient and Automated Test Method for NLP Software 2023)



Expand Down Expand Up @@ -136,7 +137,9 @@ Attacks on classification models
:members:
:noindex:


.. automodule:: textattack.attack_recipes.leap_2023
:members:
:noindex:



Expand Down
4 changes: 4 additions & 0 deletions docs/api/search_methods.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@ ParticleSwarmOptimization
.. autoclass:: textattack.search_methods.ParticleSwarmOptimization
:members:

ParticleSwarmOptimizationLEAP
--------------------------
.. autoclass:: textattack.search_methods.ParticleSwarmOptimizationLEAP
:members:
6 changes: 3 additions & 3 deletions textattack/attack.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,9 +372,9 @@ def filter_transformations(
uncached_texts.append(transformed_text)
else:
# promote transformed_text to the top of the LRU cache
self.constraints_cache[(current_text, transformed_text)] = (
self.constraints_cache[(current_text, transformed_text)]
)
self.constraints_cache[
(current_text, transformed_text)
] = self.constraints_cache[(current_text, transformed_text)]
if self.constraints_cache[(current_text, transformed_text)]:
filtered_texts.append(transformed_text)
filtered_texts += self._filter_transformations_uncached(
Expand Down
1 change: 1 addition & 0 deletions textattack/attack_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"checklist": "textattack.attack_recipes.CheckList2020",
"clare": "textattack.attack_recipes.CLARE2020",
"a2t": "textattack.attack_recipes.A2TYoo2021",
"leap": "textattack.attack_recipes.LEAP2023",
}


Expand Down
1 change: 1 addition & 0 deletions textattack/attack_recipes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from .pso_zang_2020 import PSOZang2020
from .checklist_ribeiro_2020 import CheckList2020
from .clare_li_2020 import CLARE2020
from .leap_2023 import LEAP2023
from .french_recipe import FrenchRecipe
from .spanish_recipe import SpanishRecipe
from .chinese_recipe import ChineseRecipe
44 changes: 44 additions & 0 deletions textattack/attack_recipes/leap_2023.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""

LEAP
==================================

(LEAP: Efficient and Automated Test Method for NLP Software)

"""
from textattack import Attack
from textattack.constraints.pre_transformation import (
MaxModificationRate,
StopwordModification,
)
from textattack.goal_functions import UntargetedClassification
from textattack.search_methods import ParticleSwarmOptimizationLEAP
from textattack.transformations import WordSwapWordNet

from .attack_recipe import AttackRecipe


class LEAP2023(AttackRecipe):
@staticmethod
def build(model_wrapper):
#
# Swap words with their synonyms extracted based on the WordNet.
#
transformation = WordSwapWordNet()
#
# MaxModificationRate = 0.16 in AG's News
#
constraints = [MaxModificationRate(max_rate=0.16), StopwordModification()]
#
#
# Use untargeted classification for demo, can be switched to targeted one
#
goal_function = UntargetedClassification(model_wrapper)
#
# Perform word substitution with LEAP algorithm.
#
search_method = ParticleSwarmOptimizationLEAP(
pop_size=60, max_iters=20, post_turn_check=True, max_turn_retries=20
)

return Attack(goal_function, constraints, transformation, search_method)
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class TargetedClassification(ClassificationGoalFunction):
"""A targeted attack on classification models which attempts to maximize
the score of the target label.

Complete when the arget label is the predicted label.
Complete when the target label is the predicted label.
"""

def __init__(self, *args, target_class=0, **kwargs):
Expand Down
6 changes: 3 additions & 3 deletions textattack/metrics/attack_metrics/words_perturbed.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ def calculate(self, results):
self.all_metrics["avg_word_perturbed"] = self.avg_number_word_perturbed_num()
self.all_metrics["avg_word_perturbed_perc"] = self.avg_perturbation_perc()
self.all_metrics["max_words_changed"] = self.max_words_changed
self.all_metrics["num_words_changed_until_success"] = (
self.num_words_changed_until_success
)
self.all_metrics[
"num_words_changed_until_success"
] = self.num_words_changed_until_success

return self.all_metrics

Expand Down
1 change: 1 addition & 0 deletions textattack/search_methods/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
from .alzantot_genetic_algorithm import AlzantotGeneticAlgorithm
from .improved_genetic_algorithm import ImprovedGeneticAlgorithm
from .particle_swarm_optimization import ParticleSwarmOptimization
from .particle_swarm_optimization_leap import ParticleSwarmOptimizationLEAP
6 changes: 3 additions & 3 deletions textattack/search_methods/particle_swarm_optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ def _turn(self, source_text, target_text, prob, original_text):
& indices_to_replace
)
if "last_transformation" in source_text.attacked_text.attack_attrs:
new_text.attack_attrs["last_transformation"] = (
source_text.attacked_text.attack_attrs["last_transformation"]
)
new_text.attack_attrs[
"last_transformation"
] = source_text.attacked_text.attack_attrs["last_transformation"]

if not self.post_turn_check or (new_text.words == source_text.words):
break
Expand Down
Loading
Loading