> For the complete documentation index, see [llms.txt](https://infinitode-docs.gitbook.io/documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://infinitode-docs.gitbook.io/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions.md).

# Defenses Functions

Every adversarial defense in DeepDefend 0.2.0, with signatures and links to full reference pages.

DeepDefend 0.2.0 ships sixteen defenses plus the `FeatureDenoisingBlock` layer. Two of them change how a model is **trained**; the rest wrap a trained model and preprocess its input at **inference** time.

{% hint style="warning" %}
Preprocessing defenses are not robustness guarantees. They are routinely broken by a small-step adaptive attack. Evaluate any defense you deploy with a strong attack, and read [Limitations & responsible use](/documentation/package-documentation/deepdefend-package-documentation/limitations-and-responsible-use.md) before quoting a number.
{% endhint %}

## Quick reference

### Training-time defenses

| Function                                                                                                                                                                  | Signature                                                                                                                                    | What it does                                                         |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| [`adversarial_training`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/adversarial-training.md)           | `adversarial_training(model, x, y, epsilon=0.01, epochs=10, batch_size=32, attack=None, optimizer=None, loss=None, verbose=1, shuffle=True)` | Fine-tunes a **clone** of the model on clean + adversarial batches   |
| [`defensive_distillation`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/defensive-distillation.md)       | `defensive_distillation(model, teacher_model, temperature=2)`                                                                                | Trains the student against `T²`-scaled teacher soft targets          |
| [`adversarial_logit_pairing`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/adversarial-logit-pairing.md) | `adversarial_logit_pairing(model, paired_model=None, epsilon=0.01, num_steps=1, alpha=None)`                                                 | Pulls clean and adversarial logits together inside the training step |

### Inference-time preprocessing defenses

All of these return a **new** `tf.keras.Model`.

| Function                                                                                                                                                                        | Signature                                                                              | What it does                                            |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| [`feature_squeezing`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/feature-squeezing.md)                       | `feature_squeezing(model, bit_depth=4)`                                                | Uniformly quantises the input to `bit_depth` bits       |
| [`input_transformation`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/input-transformation.md)                 | `input_transformation(model, transformation_function)`                                 | Applies your own callable or Keras layer first          |
| [`randomized_smoothing`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/randomized-smoothing.md)                 | `randomized_smoothing(model, noise_level=0.1, seed=None, add_noise_at_inference=True)` | Adds clipped Gaussian noise                             |
| [`smooth_predict`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/smooth-predict.md)                             | `smooth_predict(model, x, n_samples=100, noise_level=None, seed=None)`                 | Monte-Carlo prediction with a certified-radius estimate |
| [`feature_denoising`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/feature-denoising.md)                       | `feature_denoising(model, method="median", kernel_size=3, sigma=1.0)`                  | Median or Gaussian denoising of the input               |
| [`thermometer_encoding`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/thermometer-encoding.md)                 | `thermometer_encoding(model, num_bins=10)`                                             | Shape-preserving quantisation into `num_bins` levels    |
| [`spatial_smoothing`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/spatial-smoothing.md)                       | `spatial_smoothing(model, kernel_size=3, method="median", sigma=1.0)`                  | Median (default) or Gaussian smoothing                  |
| [`median_smoothing`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/median-smoothing.md)                         | `median_smoothing(model, kernel_size=3)`                                               | Alias of `spatial_smoothing(method="median")`           |
| [`gaussian_blur`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/gaussian-blur.md)                               | `gaussian_blur(model, kernel_size=3, sigma=1.0)`                                       | Separable Gaussian blur; `sigma` is honoured            |
| [`jpeg_compression`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/jpeg-compression.md)                         | `jpeg_compression(model, quality=75)`                                                  | JPEG encode/decode round-trip                           |
| [`pixel_deflection`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/pixel-deflection.md)                         | `pixel_deflection(model, deflection_count=100, window_size=10, seed=None)`             | Replaces random pixels with random neighbours           |
| [`total_variation_minimization`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/total-variation-minimization.md) | `total_variation_minimization(model, iterations=10, regularization_parameter=0.1)`     | Gradient-descent total-variation denoising              |
| [`word_masking`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/word-masking.md)                                 | `word_masking(text, mask_token="[MASK]", mask_prob=0.1, seed=None)`                    | Masks words in a string                                 |

### Layers

| Class                                                                                                                                                               | Signature                              | What it does                                                 |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------ |
| [`FeatureDenoisingBlock`](/documentation/package-documentation/deepdefend-package-documentation/deepdefend-reference/defenses-functions/feature-denoising-block.md) | `FeatureDenoisingBlock(kernel_size=3)` | Learnable residual box filter to insert **inside** a network |

## Shared behaviour

These guarantees apply to every defense in 0.2.0:

1. **Preprocessing defenses return a savable Keras model.** `defended.save("file.keras")` and `tf.keras.models.load_model("file.keras")` work without `custom_objects` — except for `input_transformation` with a plain Python callable (see its page).
2. **Image-only defenses raise `ValueError` on non-4-D inputs** instead of silently returning the input: `gaussian_blur`, `median_smoothing`, `spatial_smoothing`, `jpeg_compression`, `pixel_deflection`, `total_variation_minimization`, `feature_denoising`. JPEG additionally requires 1 (grayscale) or 3 (RGB) channels.
3. **Subclassed or multi-input models raise `TypeError`.** These defenses need a Functional or Sequential model with a known `input_shape`.
4. **Invalid parameters raise `ValueError` instead of producing `NaN`.** Examples: `bit_depth` must be 1–8, `num_bins >= 2`, JPEG `quality` 1–100, kernel sizes must be odd, noise levels must be `>= 0`, `epsilon >= 0`, `num_steps >= 1`.
5. **`feature_squeezing`, `jpeg_compression` and `total_variation_minimization` use a straight-through gradient**, so gradient-based attacks against a defended model still work instead of crashing or silently returning zero perturbation.
6. **`word_masking`, `word_swap` and `char_swap` preserve whitespace, newlines and punctuation exactly.**
7. **Every randomized helper accepts `seed=`** and is reproducible when it is set.

## Saving and reloading a defended model

```python
import numpy as np
import tensorflow as tf
from deepdefend.defenses import randomized_smoothing

model = tf.keras.Sequential([
    tf.keras.Input(shape=(8, 8, 1)),
    tf.keras.layers.Conv2D(8, 3, activation="relu"),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(3, activation="softmax"),
])

defended = randomized_smoothing(model, noise_level=0.1, seed=0)
defended.save("defended.keras")

restored = tf.keras.models.load_model("defended.keras")   # no custom_objects
x = np.random.rand(2, 8, 8, 1).astype("float32")
print(restored(x).shape)                                  # (2, 3)
```

## Attacking a defended model

Because preprocessing layers keep a usable gradient, the attack functions accept a defended model directly:

```python
import numpy as np
import tensorflow as tf
from deepdefend.attacks import pgd
from deepdefend.defenses import randomized_smoothing

model = tf.keras.Sequential([
    tf.keras.Input(shape=(8, 8, 1)),
    tf.keras.layers.Conv2D(8, 3, activation="relu"),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(3, activation="softmax"),
])
defended = randomized_smoothing(model, noise_level=0.1, seed=0)

x = np.random.rand(2, 8, 8, 1).astype("float32")
adv = pgd(defended, x, np.array([0, 2]), epsilon=0.05, num_steps=20, seed=0)
print(adv.shape)   # (2, 8, 8, 1)
```

If the attack reports a suspiciously tiny perturbation, check that the defense you applied is not suppressing the attack itself (`ead` with a large `beta`, or `randomized_smoothing` with a large `noise_level`), rather than concluding the model is robust.
