Type | Decision Tree | Random Forest | Linear SVC | Logistic Regression | Neural Networks | |
---|---|---|---|---|---|---|
DeepFool | Gradients | ❌ | ❌ | ✔️ | ✔️ | ✔️ |
LowProFool | Gradients | ❌ | ❌ | ✔️ | ✔️ | ✔️ |
C&W Attack | Gradients | ❌ | ❌ | ✔️ | ✔️ | ✔️ |
Boundary Attack | Black Box Attack | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
HopSkipJump Attack | Black Box Attack | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
Classifier types in ART
CLASSIFIER_CLASS_LOSS_GRADIENTS_TYPE = Union[ # pylint: disable=C0103
ClassifierClassLossGradients,
EnsembleClassifier,
GPyGaussianProcessClassifier,
KerasClassifier,
MXClassifier,
PyTorchClassifier,
ScikitlearnLogisticRegression,
ScikitlearnSVC,
TensorFlowClassifier,
TensorFlowV2Classifier,
]
CLASSIFIER_NEURALNETWORK_TYPE = Union[ # pylint: disable=C0103
ClassifierNeuralNetwork,
DetectorClassifier,
EnsembleClassifier,
KerasClassifier,
MXClassifier,
PyTorchClassifier,
TensorFlowClassifier,
TensorFlowV2Classifier,
]
CLASSIFIER_DECISION_TREE_TYPE = Union[ # pylint: disable=C0103
ClassifierDecisionTree,
LightGBMClassifier,
ScikitlearnDecisionTreeClassifier,
ScikitlearnExtraTreesClassifier,
ScikitlearnGradientBoostingClassifier,
ScikitlearnRandomForestClassifier,
XGBoostClassifier,
]
CLASSIFIER_TYPE = Union[ # pylint: disable=C0103
Classifier,
BlackBoxClassifier,
CatBoostARTClassifier,
DetectorClassifier,
EnsembleClassifier,
GPyGaussianProcessClassifier,
KerasClassifier,
JaxClassifier,
LightGBMClassifier,
MXClassifier,
PyTorchClassifier,
ScikitlearnClassifier,
ScikitlearnDecisionTreeClassifier,
ScikitlearnExtraTreeClassifier,
ScikitlearnAdaBoostClassifier,
ScikitlearnBaggingClassifier,
ScikitlearnExtraTreesClassifier,
ScikitlearnGradientBoostingClassifier,
ScikitlearnRandomForestClassifier,
ScikitlearnLogisticRegression,
ScikitlearnSVC,
TensorFlowClassifier,
TensorFlowV2Classifier,
XGBoostClassifier,
CLASSIFIER_NEURALNETWORK_TYPE,
]
When the neural network only have one output node, it has the following error:
ValueError: This attack has not yet been tested for binary classification with a single output classifier.
The error is from (source code):
if self.estimator.nb_classes == 2 and preds.shape[1] == 1:
raise ValueError( # pragma: no cover
"This attack has not yet been tested for binary classification with a single output classifier."
)
Hence, we set up two neural networks in our project, "nn" and "nn_2".
nn = tf.keras.models.Sequential(
[
tf.keras.layers.Dense(24,activation='relu'),
tf.keras.layers.Dense(12,activation='relu'),
tf.keras.layers.Dense(12,activation='relu'),
tf.keras.layers.Dense(12,activation='relu'),
tf.keras.layers.Dense(12,activation='relu'),
tf.keras.layers.Dense(1),
tf.keras.layers.Activation(tf.nn.sigmoid),
]
)
nn.compile(optimizer="Adam", loss='binary_crossentropy', metrics=['accuracy'])
nn.fit(X_train, y_train, batch_size=64, epochs=20, shuffle=True)
nn_2 = tf.keras.models.Sequential(
[
tf.keras.layers.Dense(24,activation='relu'),
tf.keras.layers.Dense(12,activation='relu'),
tf.keras.layers.Dense(12,activation='relu'),
tf.keras.layers.Dense(12,activation='relu'),
tf.keras.layers.Dense(12,activation='relu'),
tf.keras.layers.Dense(2),
tf.keras.layers.Activation(tf.nn.softmax),
]
)
nn_2.compile(optimizer="Adam", loss='sparse_categorical_crossentropy', metrics=['accuracy'])
nn_2.fit(X_train, y_train, batch_size=64, epochs=20, shuffle=True)
Two neural networks have similar settings but the actiavtion function of last layer and loss fuction used for compiling models.
From the experiment settings from original paper (https://arxiv.org/abs/1911.03274), LowProFool
can only work on numerical features and continous features, all non-ordered categorical features need to be dropped. Hence, we only use dataset with numerical features ["diabetes", "breast_cancer"]
.
Another problem is that art.attacks.evasion.LowProFool
doesn't work for
To Reproduce Steps to reproduce the behavior:
- Go to my notebook (gist)
- When set the
norm>=2
ornorm='inf'
, the attack model works well. For example,
success_rate=test_general_cancer_lr(breast_cancer_dataset(splitter()), norm=2)
print(success_rate)
Result is :
1.0
- When set the
0<norm<2
, the attack model doesn't work. For example,
success_rate=test_general_cancer_lr(breast_cancer_dataset(splitter()), norm=1)
print(success_rate)
Error:
/usr/local/lib/python3.8/dist-packages/art/attacks/evasion/lowprofool.py:159: RuntimeWarning: divide by zero encountered in power
self.importance_vec * self.importance_vec * perturbations * np.power(np.abs(perturbations), norm - 2)
/usr/local/lib/python3.8/dist-packages/art/attacks/evasion/lowprofool.py:159: RuntimeWarning: invalid value encountered in multiply
self.importance_vec * self.importance_vec * perturbations * np.power(np.abs(perturbations), norm - 2)
...
...
ValueError: Input contains NaN, infinity or a value too large for dtype('float32').
From RuntimeWarning: divide by zero encountered in power
,
In LowProFool
L307-L313 , the attack model initialized the perturbation with np.zero
# Initialize perturbation vectors and learning rate.
perturbations = np.zeros(samples.shape, dtype=np.float64)
eta = self.eta
# Initialize 'keep-the-best' variables.
best_norm_losses = np.inf * np.ones(samples.shape[0], dtype=np.float64)
best_perturbations = perturbations.copy()
In LowProFool
L148-L171 , when 0< norm <2
, it will encounter divide by zero
error.
numerator = (
self.importance_vec * self.importance_vec * perturbations * np.power(np.abs(perturbations), norm - 2)
)