Getting started
The GROOT repository contains several useful modules for fitting and scoring decision trees and ensembles against adversarial examples:
- Implementations of robust decision tree learning algorithms:
- Adversary for attacking and scoring decision trees
- Kantchelian's MILP attack for attacking and scoring trees / ensembles4
- Easy functions to import datasets
- Utilities for exporting scikit-learn models
- 2D decision tree visualizer
For an introduction to decision trees and adversarial examples see this blogpost.
Installing
GROOT can be directly install from PyPi:
pip install groot-trees
To use Kantchelian's MILP attack it is required that you have GUROBI installed along with their python package:
python -m pip install -i https://pypi.gurobi.com gurobipy
Toolbox
The GROOT toolbox contains the useful Model
class which can take models of different types (e.g. Scikit-learn, GROOT, TREANT) and turn these into a general JSON representation. It can also be used to easily evaluate the performance of these models against adversarial attacks.
GROOT Example
Below is a very simple example demonstrating how to train and score a GROOT tree on a toy dataset. We start by creating a 2D dataset using scikit-learn then split it into a train and test set.
from groot.model import GrootTreeClassifier
from groot.toolbox import Model
from sklearn.datasets import make_moons
# Load the dataset
X, y = make_moons(noise=0.3, random_state=0)
X_test, y_test = make_moons(noise=0.3, random_state=1)
To encode an attacker that can increase/decrease a sample by 0.3 for both features we set the attack_model to [0.3, 0.3]
.
# Define the attacker's capabilities (L-inf norm radius 0.3)
epsilon = 0.3
attack_model = [epsilon, epsilon]
We train the GrootTreeClassifier
using .fit()
just like other scikit-learn models.
# Create and fit a GROOT tree
tree = GrootTreeClassifier(
attack_model=attack_model,
random_state=0
)
tree.fit(X, y)
Lastly, we test the performance. To get the regular accuracy we use .score()
and to determine adversarial accuracy we can use the Model
class that exposes some useful functionality.
# Determine the accuracy and accuracy against attackers
accuracy = tree.score(X_test, y_test)
model = Model.from_groot(tree)
adversarial_accuracy = model.adversarial_accuracy(X_test, y_test, attack="tree", epsilon=0.3)
print("Accuracy:", accuracy)
print("Adversarial Accuracy:", adversarial_accuracy)
See the groot.toolbox for more information on how to use the Model
class.
Putting it all together
The full script is given below.
from groot.model import GrootTreeClassifier
from groot.toolbox import Model
from sklearn.datasets import make_moons
# Load the dataset
X, y = make_moons(noise=0.3, random_state=0)
X_test, y_test = make_moons(noise=0.3, random_state=1)
# Define the attacker's capabilities (L-inf norm radius 0.3)
epsilon = 0.3
attack_model = [epsilon, epsilon]
# Create and fit a GROOT tree
tree = GrootTreeClassifier(
attack_model=attack_model,
random_state=0
)
tree.fit(X, y)
# Determine the accuracy and accuracy against attackers
accuracy = tree.score(X_test, y_test)
model = Model.from_groot(tree)
adversarial_accuracy = model.adversarial_accuracy(X_test, y_test, attack="tree", epsilon=0.3)
print("Accuracy:", accuracy)
print("Adversarial Accuracy:", adversarial_accuracy)
Which evaluates to:
Accuracy: 0.83
Adversarial Accuracy: 0.65
-
Vos, Daniël, and Sicco Verwer. "Efficient Training of Robust Decision Trees Against Adversarial Examples." arXiv preprint arXiv:2012.10438 (2020). ↩↩
-
Calzavara, Stefano, et al. "Treant: training evasion-aware decision trees." Data Mining and Knowledge Discovery 34.5 (2020): 1390-1420. ↩
-
Andriushchenko, Maksym, and Matthias Hein. "Provably robust boosted decision stumps and trees against adversarial attacks." arXiv preprint arXiv:1906.03526 (2019). ↩
-
Kantchelian, Alex, J. Doug Tygar, and Anthony Joseph. "Evasion and hardening of tree ensemble classifiers." International Conference on Machine Learning. PMLR, 2016. ↩