{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Tracking Callbacks"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [],
"source": [
"from fastai.gen_doc.nbdoc import *\n",
"from fastai import *\n",
"from fastai.vision import *\n",
"from fastai.callbacks import *"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This module regroups the callbacks that track one of the metrics computed at the end of each epoch to take some decision about training. To show examples of use, we'll use our sample of MNIST and a simple cnn model."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"path = untar_data(URLs.MNIST_SAMPLE)\n",
"data = ImageDataBunch.from_folder(path)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"
class
TerminateOnNaNCallback
[source]
\n",
"\n",
"> TerminateOnNaNCallback
() :: [`Callback`](/callback.html#Callback)\n",
"\n",
"A [`Callback`](/callback.html#Callback) that terminates training if loss is NaN. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(callbacks.TerminateOnNaNCallback)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sometimes, training diverges and the loss goes to nan. In that case, there's no point continuing, so this callback stops the training."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Total time: 00:04\n",
"epoch train_loss valid_loss accuracy\n",
"1 nan nan 0.504416 (00:02)\n",
"2 nan nan 0.504416 (00:02)\n",
"\n"
]
}
],
"source": [
"model = simple_cnn((3,16,16,2))\n",
"learn = Learner(data, model, metrics=[accuracy])\n",
"learn.fit_one_cycle(2,1e4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Using it prevents that situation to happen."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
"
\n",
" 0.00% [0/2 00:00<00:00]\n",
"
\n",
" \n",
"\n",
" \n",
" epoch | \n",
" train_loss | \n",
" valid_loss | \n",
" accuracy | \n",
"
\n",
" \n",
"\n",
"
\n",
"
\n",
"\n",
"\n",
" \n",
" \n",
"
\n",
" Interrupted\n",
"
\n",
" "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch/Batch (0/5): Invalid loss, terminating training.\n"
]
}
],
"source": [
"model = simple_cnn((3,16,16,2))\n",
"learn = Learner(data, model, metrics=[accuracy], callbacks=[TerminateOnNaNCallback()])\n",
"learn.fit(2,1e4)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"class
EarlyStoppingCallback
[source]
\n",
"\n",
"> EarlyStoppingCallback
(`learn`:[`Learner`](/basic_train.html#Learner), `monitor`:`str`=`'val_loss'`, `mode`:`str`=`'auto'`, `min_delta`:`int`=`0`, `patience`:`int`=`0`) :: [`TrackerCallback`](/callbacks.tracker.html#TrackerCallback)\n",
"\n",
"A [`TrackerCallback`](/callbacks.tracker.html#TrackerCallback) that terminates training when monitored quantity stops improving. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(EarlyStoppingCallback)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This callback tracks the quantity in `monitor` during the training of `learn`. `mode` can be forced to 'min' or 'max' but will automatically try to determine if the quantity should be the lowest possible (validation loss) or the highest possible (accuracy). Will stop training after `patience` epochs if the quantity hasn't improved by `min_delta`. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
"
\n",
" 6.00% [3/50 00:06<01:49]\n",
"
\n",
" \n",
"\n",
" \n",
" epoch | \n",
" train_loss | \n",
" valid_loss | \n",
" accuracy | \n",
"
\n",
" \n",
" 1 | \n",
" 0.692837 | \n",
" 0.692778 | \n",
" 0.496565 | \n",
"
\n",
" \n",
" 2 | \n",
" 0.692831 | \n",
" 0.692778 | \n",
" 0.496565 | \n",
"
\n",
" \n",
" 3 | \n",
" 0.692877 | \n",
" 0.692778 | \n",
" 0.496565 | \n",
"
\n",
" \n",
"\n",
"
\n",
"
\n",
"\n",
"\n",
" \n",
" \n",
"
\n",
" 100.00% [22/22 00:00<00:00]\n",
"
\n",
" "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 4: early stopping\n"
]
}
],
"source": [
"model = simple_cnn((3,16,16,2))\n",
"learn = Learner(data, model, metrics=[accuracy], \n",
" callback_fns=[partial(EarlyStoppingCallback, monitor='accuracy', min_delta=0.01, patience=3)])\n",
"learn.fit(50,1e-42)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"class
SaveModelCallback
[source]
\n",
"\n",
"> SaveModelCallback
(`learn`:[`Learner`](/basic_train.html#Learner), `monitor`:`str`=`'val_loss'`, `mode`:`str`=`'auto'`, `every`:`str`=`'improvement'`, `name`:`str`=`'bestmodel'`) :: [`TrackerCallback`](/callbacks.tracker.html#TrackerCallback)\n",
"\n",
"A [`TrackerCallback`](/callbacks.tracker.html#TrackerCallback) that saves the model when monitored quantity is best. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(SaveModelCallback)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This callback tracks the quantity in `monitor` during the training of `learn`. `mode` can be forced to 'min' or 'max' but will automatically try to determine if the quantity should be the lowest possible (validation loss) or the highest possible (accuracy). Will save the model in `name` whenever determined by `every` ('improvement' or 'epoch'). Loads the best model at the end of training is `every='improvement'`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"class
ReduceLROnPlateauCallback
[source]
\n",
"\n",
"> ReduceLROnPlateauCallback
(`learn`:[`Learner`](/basic_train.html#Learner), `monitor`:`str`=`'val_loss'`, `mode`:`str`=`'auto'`, `patience`:`int`=`0`, `factor`:`float`=`0.2`, `min_delta`:`int`=`0`) :: [`TrackerCallback`](/callbacks.tracker.html#TrackerCallback)\n",
"\n",
"A [`TrackerCallback`](/callbacks.tracker.html#TrackerCallback) that reduces learning rate when a metric has stopped improving. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(ReduceLROnPlateauCallback)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This callback tracks the quantity in `monitor` during the training of `learn`. `mode` can be forced to 'min' or 'max' but will automatically try to determine if the quantity should be the lowest possible (validation loss) or the highest possible (accuracy). Will reduce the learning rate by `factor` after `patience` epochs if the quantity hasn't improved by `min_delta`. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"class
TrackerCallback
[source]
\n",
"\n",
"> TrackerCallback
(`learn`:[`Learner`](/basic_train.html#Learner), `monitor`:`str`=`'val_loss'`, `mode`:`str`=`'auto'`) :: [`LearnerCallback`](/basic_train.html#LearnerCallback)\n",
"\n",
"A [`LearnerCallback`](/basic_train.html#LearnerCallback) that keeps track of the best value in `monitor`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(TrackerCallback)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Undocumented Methods - Methods moved below this line will intentionally be hidden"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## New Methods - Please document or move to the undocumented section"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_epoch_end
(`epoch`, `kwargs`:`Any`)\n",
"\n",
"Called at the end of an epoch. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(SaveModelCallback.on_epoch_end)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_batch_end
(`last_loss`, `epoch`, `num_batch`, `kwargs`:`Any`)\n",
"\n",
"Called at the end of the batch. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(TerminateOnNaNCallback.on_batch_end)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_train_begin
(`kwargs`:`Any`)\n",
"\n",
"To initialize constants in the callback. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(EarlyStoppingCallback.on_train_begin)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_train_end
(`kwargs`)\n",
"\n",
"Useful for cleaning up things and saving files/models. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(SaveModelCallback.on_train_end)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_epoch_end
(`epoch`, `kwargs`:`Any`)\n",
"\n",
"Called at the end of an epoch. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(ReduceLROnPlateauCallback.on_epoch_end)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_epoch_end
(`epoch`, `kwargs`:`Any`)\n",
"\n",
"Called at the end of an epoch. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(EarlyStoppingCallback.on_epoch_end)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_epoch_end
(`kwargs`:`Any`)\n",
"\n",
"Called at the end of an epoch. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(TerminateOnNaNCallback.on_epoch_end)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_train_begin
(`kwargs`:`Any`)\n",
"\n",
"To initialize constants in the callback. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(TrackerCallback.on_train_begin)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_train_begin
(`kwargs`:`Any`)\n",
"\n",
"To initialize constants in the callback. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(ReduceLROnPlateauCallback.on_train_begin)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"get_monitor_value
[source]
\n",
"\n",
"> get_monitor_value
()"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(TrackerCallback.get_monitor_value)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"class
TerminateOnNaNCallback
[source]
\n",
"\n",
"> TerminateOnNaNCallback
() :: [`Callback`](/callback.html#Callback)\n",
"\n",
"A [`Callback`](/callback.html#Callback) that terminates training if loss is NaN. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(TerminateOnNaNCallback)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
"jekyll": {
"keywords": "fastai",
"summary": "Callbacks that take decisions depending on the evolution of metrics during training",
"title": "callbacks.tracker"
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}