# test_on_train_end

Python API: `luxonis_train.callbacks.test_on_train_end`

Tests the best checkpoint when training ends.

## Classes

### TestOnTrainEnd

Callback that tests the best checkpoint when training ends.

The callback passes the checkpoint of
[NeedsCheckpoint.get_checkpoint](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/callbacks/needs_checkpoint.md)
to
[LuxonisModel.test](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/core/core.md).
It always tries the best main metric first, and then the lowest validation loss. Its constructor does not accept
`preferred_checkpoint`.

When `trainer.smart_cfg_auto_populate` is set,
[Config.smart_auto_populate](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/config/config.md)
adds this callback to `trainer.callbacks` if it is missing.
[LuxonisModel.tune](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/core/core.md)
removes it from the config of each trial.

#### Methods

##### init

```python
def __init__(view: View = 'test'):
```

Initialize the callback.

Parameters

 * `view` (`View`): The dataset view to test on. The test reads the PyTorch loader of this view. The logged keys start with
   `test/` for every view.

##### on_train_end

```python
def on_train_end(trainer: pl.Trainer, pl_module: lxt.LuxonisLightningModule):
```

Test the model on the best checkpoint.

Lightning calls this hook once when `trainer.fit` ends. The hook selects a checkpoint with
[NeedsCheckpoint.get_checkpoint](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/callbacks/needs_checkpoint.md)
and passes it to
[LuxonisModel.test](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/core/core.md)
with `view`. The test logs its values to the tracker. It does not finalize the tracker.
[LuxonisModel.train](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/core/core.md)
does that at the end of the run.

When no checkpoint exists, the hook logs a warning. The test then uses the weights of the
[LuxonisModel](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/core/core.md)
constructor, or `model.weights` of the config. Without either, it uses the current weights of the module.

After the test, the hook restores two things:

 * The test moves the module to the CPU. The hook moves `pl_module` back to its earlier device.
 * The test attaches new `ModelCheckpoint` callbacks from
   [LuxonisLightningModule.configure_callbacks](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/lightning/luxonis_lightning.md),
   each with an empty `best_model_path`. The hook copies the earlier paths into them, matched by `monitor`. Thus a later callback,
   such as
   [ConvertOnTrainEnd](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/callbacks/convert_on_train_end.md),
   still finds the best checkpoint.

The test loads the checkpoint into `pl_module.core.lightning_module`, which is `pl_module` in a
[LuxonisModel.train](https://docs.luxonis.com/software-v3/ai-inference/model-source/training/luxonis-train/luxonis-train-api-reference/core/core.md)
run. It loads the checkpoint only for the test. After the hook, that module holds its earlier weights again.

Parameters

 * `trainer` (`pl.Trainer`): The trainer. The hook reads and updates its checkpoint callbacks.
 * `pl_module` (`lxt.LuxonisLightningModule`): The model to test.
