Metadata-Version: 2.4
Name: mixup
Version: 0.2.0
Summary: A unified PyTorch library for SOTA MixUp augmentations.
Home-page: https://github.com/your_username/mixupentations
Author: Andrey Katasonov
Author-email: andre.katasonov@gmail.com
Project-URL: Source, https://github.com/your_username/mixupentations
Keywords: mixup cutmix resizemix fmix saliencymix puzzlemix augmentations computer vision pytorch deep learning
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: torch>=1.10.0
Requires-Dist: numpy>=1.21.0
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: project-url
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# mixup

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![PyTorch](https://img.shields.io/badge/PyTorch-1.10+-ee4c2c.svg)](https://pytorch.org/)

A unified PyTorch library for SOTA MixUp augmentations. It keeps popular image and label mixing methods in one place, making it convenient for rapid experiments and training robust classification models.

---

## Features

- **VanillaMixUp** — classic linear mixing of two images and their labels.
- **CutMix** — replaces a rectangular region of an image with a patch from another image.
- **ResizeMix** — overlays a rescaled patch from another image.
- **FMix** — blends images using a low-frequency noise mask generated via FFT.
- **SaliencyMix** — pastes a patch centered on the most salient region of a partner image.
- **PuzzleMix** — swaps spatial blocks where the partner image is more salient.
- **MixupPipeline** — randomly selects one method from a provided list for multi-mode training.
- **Saliency utilities** — heuristic and gradient-based saliency maps for custom workflows.
- Fully compatible with PyTorch Automatic Mixed Precision (AMP) and soft-label loss functions.
- Easily extensible architecture via the `BaseMixup` abstract class.

---

## Installation

Install directly from PyPI:

```bash
pip install mixup

```

Or install in development mode from source:

```bash
git clone [https://github.com/your_username/mixup.git](https://github.com/your_username/mixup.git)
cd mixup
pip install -e .

```

---

## Input Requirements

All augmentation methods strictly accept One-Hot encoded or soft-label target tensors:

* **Images (`x`)**: Tensor of shape `[B, C, H, W]`
* **Labels (`y`)**: One-Hot / Soft-label Tensor of shape `[B, Num_Classes]` (type `float32` / `float16`)

---

## Quick Start

```python
import torch
import torch.nn.functional as F
from mixup import VanillaMixUp, CutMix, SaliencyMix, PuzzleMix, MixupPipeline

# Dummy batch of images [B, C, H, W] and integer labels [B]
images = torch.randn(8, 3, 32, 32)
labels = torch.randint(0, 100, (8,))

# Convert integer labels to one-hot encoding [B, Num_Classes]
labels_one_hot = F.one_hot(labels, num_classes=100).float()

# 1. Standard VanillaMixUp
mixup = VanillaMixUp(alpha=1.0, probability=0.5)
mixed_images, mixed_labels = mixup(images, labels_one_hot)

# 2. SaliencyMix with a fast heuristic saliency backend
saliencymix = SaliencyMix(alpha=1.0, mode='heuristic')
mixed_images, mixed_labels = saliencymix(images, labels_one_hot)

# 3. Multi-mode pipeline
pipeline = MixupPipeline([
    VanillaMixUp(alpha=1.0),
    CutMix(alpha=1.0),
    SaliencyMix(alpha=1.0, mode='heuristic'),
    PuzzleMix(alpha=1.0, mode='heuristic', block_size=4),
])
mixed_images, mixed_labels = pipeline(images, labels_one_hot)

```

---

## Available Augmentations

### VanillaMixUp

Blends two images and their corresponding labels using a mixing coefficient $\lambda \sim \text{Beta}(\alpha, \alpha)$.

```python
from mixup import VanillaMixUp

mixup = VanillaMixUp(alpha=1.0, probability=1.0)

```

### CutMix

Cuts a rectangular region from one image and pastes a patch from another. The mixing weight $\lambda$ is automatically recalculated based on the cropped area.

```python
from mixup import CutMix

cutmix = CutMix(alpha=1.0, probability=0.5)

```

### ResizeMix

Rescales a partner image and pastes the resulting patch into a random position on the original image.

```python
from mixup import ResizeMix

resizemix = ResizeMix(alpha=1.0)

```

### FMix

Generates a smooth binary mask via the inverse FFT of low-frequency noise and blends images according to this mask.

```python
from mixup import FMix

fmix = FMix(alpha=1.0, decay_power=3.0)

```

### SaliencyMix

Pastes a patch from a partner image centered around its most salient point. Supports two backends:

* `mode='heuristic'` — fast, context-aware saliency with center prior (no model required).
* `mode='gradient'` — input-gradient saliency from the training model.

```python
from mixup import SaliencyMix

# Heuristic mode (model-free)
saliencymix = SaliencyMix(alpha=1.0, mode='heuristic')

# Gradient mode (requires training model)
saliencymix = SaliencyMix(alpha=1.0, mode='gradient', model=model)

```

### PuzzleMix

Swaps spatial blocks where the partner image is more salient than the original image.

```python
from mixup import PuzzleMix

puzzlemix = PuzzleMix(alpha=1.0, mode='heuristic', block_size=4)
puzzlemix = PuzzleMix(alpha=1.0, mode='gradient', model=model, block_size=4)

```

### Low-level Saliency Helpers

```python
from mixup import get_heuristic_saliency_map, get_gradient_saliency_map

sal_maps_heuristic = get_heuristic_saliency_map(images)
sal_maps_gradient = get_gradient_saliency_map(model, images, labels_one_hot)

```

---

## Parameters

Common parameters across all augmentations inheriting from `BaseMixup`:

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `alpha` | float | `1.0` | Beta distribution hyperparameter $\alpha$. If `0.0`, $\lambda=1.0$. |
| `probability` | float | `1.0` | Probability ($0.0 \dots 1.0$) of applying the augmentation. |

Method-specific arguments:

| Class | Parameter | Type | Default | Description |
| --- | --- | --- | --- | --- |
| `FMix` | `decay_power` | float | `3.0` | Decay power in the frequency domain for FFT noise. |
| `SaliencyMix` | `mode` | str | `'heuristic'` | Backend selection: `'heuristic'` or `'gradient'`. |
| `SaliencyMix` | `model` | `nn.Module` | `None` | Target model instance (required when `mode='gradient'`). |
| `PuzzleMix` | `mode` | str | `'heuristic'` | Backend selection: `'heuristic'` or `'gradient'`. |
| `PuzzleMix` | `model` | `nn.Module` | `None` | Target model instance (required when `mode='gradient'`). |
| `PuzzleMix` | `block_size` | int | `4` | Block size in pixels for spatial tile swapping. |

---

## Integration into Training Loop

PyTorch's native `nn.CrossEntropyLoss` supports One-Hot / soft labels out of the box (PyTorch $\ge$ 1.10).

```python
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from mixup import SaliencyMix, PuzzleMix

model = ...  # Your model
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
NUM_CLASSES = 100

# Model-free SaliencyMix
saliencymix = SaliencyMix(alpha=1.0, probability=1.0, mode='heuristic')

# Gradient-based PuzzleMix using the active model
puzzlemix = PuzzleMix(alpha=1.0, mode='gradient', model=model, block_size=4)

model.train()
for images, labels in dataloader:
    images, labels = images.cuda(), labels.cuda()

    # Always convert labels to one-hot floats before applying mixup methods
    labels_one_hot = F.one_hot(labels, num_classes=NUM_CLASSES).float()

    mixed_images, mixed_labels = saliencymix(images, labels_one_hot)

    optimizer.zero_grad()
    outputs = model(mixed_images)
    loss = criterion(outputs, mixed_labels)
    loss.backward()
    optimizer.step()

```

---

## References

* [MixUp: Beyond Empirical Risk Minimization](https://arxiv.org/abs/1710.09412)
* [CutMix: Regularization Strategy to Train Strong Classifiers](https://arxiv.org/abs/1905.04899)
* [ResizeMix: Mixing Data with Preserved Object Information](https://arxiv.org/abs/2012.11101)
* [FMix: Enhancing Mixed Sample Data Augmentation](https://arxiv.org/abs/2002.12047)
* [SaliencyMix: A Saliency Guided Data Augmentation Strategy for Better Regularization](https://arxiv.org/abs/2006.01791)
* [Puzzle Mix: Exploiting Saliency and Local Statistics for Optimal Mixup](https://arxiv.org/abs/2008.05474)

---

## License

This project is licensed under the MIT License.
