﻿# MixUp and Friends


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

``` python
from fastai.vision.all import *
```

------------------------------------------------------------------------

<a
href="https://github.com/fastai/fastai/blob/main/fastai/callback/mixup.py#L15"
target="_blank" style="float:right; font-size:smaller">source</a>

### reduce_loss

``` python
def reduce_loss(
    loss:Tensor, reduction:str='mean', # PyTorch loss reduction
)->Tensor:
```

*Reduce the loss based on `reduction`*

------------------------------------------------------------------------

<a
href="https://github.com/fastai/fastai/blob/main/fastai/callback/mixup.py#L23"
target="_blank" style="float:right; font-size:smaller">source</a>

### MixHandler

``` python
def MixHandler(
    alpha:float=0.5, # Determine `Beta` distribution in range (0.,inf]
):
```

*A handler class for implementing
[`MixUp`](https://docs.fast.ai/callback.mixup.html#mixup) style
scheduling*

Most `Mix` variants will perform the data augmentation on the batch, so
to implement your `Mix` you should adjust the `before_batch` event with
however your training regiment requires. Also if a different loss
function is needed, you should adjust the `lf` as well. `alpha` is
passed to `Beta` to create a sampler.

------------------------------------------------------------------------

<a
href="https://github.com/fastai/fastai/blob/main/fastai/callback/mixup.py#L56"
target="_blank" style="float:right; font-size:smaller">source</a>

### MixUp

``` python
def MixUp(
    alpha:float=0.4, # Determine `Beta` distribution in range (0.,inf]
):
```

*Implementation of https://arxiv.org/abs/1710.09412*

This is a modified implementation of mixup that will always blend at
least 50% of the original image. The original paper calls for a Beta
distribution which is passed the same value of alpha for each position
in the loss function (alpha = beta = \#). Unlike the original paper,
this implementation of mixup selects the max of lambda which means that
if the value that is sampled as lambda is less than 0.5 (i.e the
original image would be \<50% represented, 1-lambda is used instead.

The blending of two images is determined by `alpha`.

*a**l**p**h**a* = 1.:

- All values between 0 and 1 have an equal chance of being sampled.
- Any amount of mixing between the two images is possible

*a**l**p**h**a* \< 1.:

- The values closer to 0 and 1 become more likely to be sampled than the
  values near 0.5.\
- It is more likely that one of the images will be selected with a
  slight amount of the other image.

*a**l**p**h**a* \> 1.:

- The values closer to 0.5 become more likely than the numbers close to
  0 or 1.
- It is more likely that the images will be blended evenly.

First we’ll look at a very minimalistic example to show how our data is
being generated with the `PETS` dataset:

``` python
path = untar_data(URLs.PETS)
pat        = r'([^/]+)_\d+.*$'
fnames     = get_image_files(path/'images')
item_tfms  = [Resize(256, method='crop')]
batch_tfms = [*aug_transforms(size=224), Normalize.from_stats(*imagenet_stats)]
dls = ImageDataLoaders.from_name_re(path, fnames, pat, bs=64, item_tfms=item_tfms, 
                                    batch_tfms=batch_tfms)
```

We can examine the results of our
[`Callback`](https://docs.fast.ai/callback.core.html#callback) by
grabbing our data during `fit` at `before_batch` like so:

``` python
mixup = MixUp(1.)
with Learner(dls, nn.Linear(3,4), loss_func=CrossEntropyLossFlat(), cbs=mixup) as learn:
    learn.epoch,learn.training = 0,True
    learn.dl = dls.train
    b = dls.one_batch()
    learn._split(b)
    learn('before_train')
    learn('before_batch')

_,axs = plt.subplots(3,3, figsize=(9,9))
dls.show_batch(b=(mixup.x,mixup.y), ctxs=axs.flatten())
```

<style>
    /* Turns off some styling */
    progress {
        /* gets rid of default border in Firefox and Opera. */
        border: none;
        /* Needs to be in here for Safari polyfill so background images work as expected. */
        background-size: auto;
    }
    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
        background: #F44336;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: left;">
<th data-quarto-table-cell-role="th">epoch</th>
<th data-quarto-table-cell-role="th">train_loss</th>
<th data-quarto-table-cell-role="th">valid_loss</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>00:00</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>

![](19_callback.mixup_files/figure-commonmark/cell-7-output-3.png)

We can see that every so often an image gets “mixed” with another.

How do we train? You can pass the
[`Callback`](https://docs.fast.ai/callback.core.html#callback) either to
[`Learner`](https://docs.fast.ai/learner.html#learner) directly or to
`cbs` in your fit function:

``` python
learn = vision_learner(dls, resnet18, loss_func=CrossEntropyLossFlat(), metrics=[error_rate])
learn.fit_one_cycle(1, cbs=mixup)
```

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: left;">
<th data-quarto-table-cell-role="th">epoch</th>
<th data-quarto-table-cell-role="th">train_loss</th>
<th data-quarto-table-cell-role="th">valid_loss</th>
<th data-quarto-table-cell-role="th">error_rate</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>2.041960</td>
<td>0.495492</td>
<td>0.162382</td>
<td>00:12</td>
</tr>
</tbody>
</table>

------------------------------------------------------------------------

<a
href="https://github.com/fastai/fastai/blob/main/fastai/callback/mixup.py#L78"
target="_blank" style="float:right; font-size:smaller">source</a>

### CutMix

``` python
def CutMix(
    alpha:float=1.0, # Determine `Beta` distribution in range (0.,inf]
):
```

*Implementation of https://arxiv.org/abs/1905.04899*

Similar to [`MixUp`](https://docs.fast.ai/callback.mixup.html#mixup),
[`CutMix`](https://docs.fast.ai/callback.mixup.html#cutmix) will cut a
random box out of two images and swap them together. We can look at a
few examples below:

``` python
cutmix = CutMix(1.)
with Learner(dls, nn.Linear(3,4), loss_func=CrossEntropyLossFlat(), cbs=cutmix) as learn:
    learn.epoch,learn.training = 0,True
    learn.dl = dls.train
    b = dls.one_batch()
    learn._split(b)
    learn('before_train')
    learn('before_batch')

_,axs = plt.subplots(3,3, figsize=(9,9))
dls.show_batch(b=(cutmix.x,cutmix.y), ctxs=axs.flatten())
```

<style>
    /* Turns off some styling */
    progress {
        /* gets rid of default border in Firefox and Opera. */
        border: none;
        /* Needs to be in here for Safari polyfill so background images work as expected. */
        background-size: auto;
    }
    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
        background: #F44336;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: left;">
<th data-quarto-table-cell-role="th">epoch</th>
<th data-quarto-table-cell-role="th">train_loss</th>
<th data-quarto-table-cell-role="th">valid_loss</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>00:00</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>

![](19_callback.mixup_files/figure-commonmark/cell-10-output-3.png)

We train with it in the exact same way as well

``` python
learn = vision_learner(dls, resnet18, loss_func=CrossEntropyLossFlat(), metrics=[accuracy, error_rate])
learn.fit_one_cycle(1, cbs=cutmix)
```

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: left;">
<th data-quarto-table-cell-role="th">epoch</th>
<th data-quarto-table-cell-role="th">train_loss</th>
<th data-quarto-table-cell-role="th">valid_loss</th>
<th data-quarto-table-cell-role="th">accuracy</th>
<th data-quarto-table-cell-role="th">error_rate</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>3.440883</td>
<td>0.793059</td>
<td>0.769959</td>
<td>0.230041</td>
<td>00:12</td>
</tr>
</tbody>
</tabl