{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Basic training functionality"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [],
"source": [
"from fastai.basic_train import *\n",
"from fastai.gen_doc.nbdoc import *\n",
"from fastai.vision import *\n",
"from fastai.distributed import *"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[`basic_train`](/basic_train.html#basic_train) wraps together the data (in a [`DataBunch`](/basic_data.html#DataBunch) object) with a PyTorch model to define a [`Learner`](/basic_train.html#Learner) object. Here the basic training loop is defined for the [`fit`](/basic_train.html#fit) method. The [`Learner`](/basic_train.html#Learner) object is the entry point of most of the [`Callback`](/callback.html#Callback) objects that will customize this training loop in different ways. Some of the most commonly used customizations are available through the [`train`](/train.html#train) module, notably:\n",
"\n",
" - [`Learner.lr_find`](/train.html#lr_find) will launch an LR range test that will help you select a good learning rate.\n",
" - [`Learner.fit_one_cycle`](/train.html#fit_one_cycle) will launch a training using the 1cycle policy to help you train your model faster.\n",
" - [`Learner.to_fp16`](/train.html#to_fp16) will convert your model to half precision and help you launch a training in mixed precision."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"
\n",
"\n",
"> Learner(**`data`**:[`DataBunch`](/basic_data.html#DataBunch), **`model`**:[`Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module), **`opt_func`**:`Callable`=***`'Adam'`***, **`loss_func`**:`Callable`=***`None`***, **`metrics`**:`Collection`\\[`Callable`\\]=***`None`***, **`true_wd`**:`bool`=***`True`***, **`bn_wd`**:`bool`=***`True`***, **`wd`**:`Floats`=***`0.01`***, **`train_bn`**:`bool`=***`True`***, **`path`**:`str`=***`None`***, **`model_dir`**:`str`=***`'models'`***, **`callback_fns`**:`Collection`\\[`Callable`\\]=***`None`***, **`callbacks`**:`Collection`\\[[`Callback`](/callback.html#Callback)\\]=***``***, **`layer_groups`**:`ModuleList`=***`None`***)\n",
"\n",
"Trainer for `model` using `data` to minimize `loss_func` with optimizer `opt_func`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner, title_level=2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The main purpose of [`Learner`](/basic_train.html#Learner) is to train `model` using [`Learner.fit`](/basic_train.html#Learner.fit). After every epoch, all *metrics* will be printed and also made available to callbacks.\n",
"\n",
"The default weight decay will be `wd`, which will be handled using the method from [Fixing Weight Decay Regularization in Adam](https://arxiv.org/abs/1711.05101) if `true_wd` is set (otherwise it's L2 regularization). If `bn_wd` is `False`, then weight decay will be removed from batchnorm layers, as recommended in [Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour](https://arxiv.org/abs/1706.02677). If `train_bn`, batchnorm layer learnable params are trained even for frozen layer groups.\n",
"\n",
"To use [discriminative layer training](#Discriminative-layer-training), pass a list of [`nn.Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) as `layer_groups`; each [`nn.Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) will be used to customize the optimization of the corresponding layer group.\n",
"\n",
"If `path` is provided, all the model files created will be saved in `path`/`model_dir`; if not, then they will be saved in `data.path`/`model_dir`.\n",
"\n",
"You can pass a list of [`callback`](/callback.html#callback)s that you have already created, or (more commonly) simply pass a list of callback functions to `callback_fns` and each function will be called (passing `self`) on object initialization, with the results stored as callback objects. For a walk-through, see the [training overview](/training.html) page. You may also want to use an [application](applications.html) specific model. For example, if you are dealing with a vision dataset, here the MNIST, you might want to use the [`create_cnn`](/vision.learner.html#create_cnn) method:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": false
},
"outputs": [],
"source": [
"path = untar_data(URLs.MNIST_SAMPLE)\n",
"data = ImageDataBunch.from_folder(path)\n",
"learn = create_cnn(data, models.resnet18, metrics=accuracy)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Model fitting methods"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> fit(**`epochs`**:`int`, **`lr`**:`Union`\\[`float`, `Collection`\\[`float`\\], `slice`\\]=***`slice(None, 0.003, None)`***, **`wd`**:`Floats`=***`None`***, **`callbacks`**:`Collection`\\[[`Callback`](/callback.html#Callback)\\]=***`None`***)\n",
"\n",
"Fit the model on this learner with `lr` learning rate, `wd` weight decay for `epochs` with `callbacks`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.fit)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Uses [discriminative layer training](#Discriminative-layer-training) if multiple learning rates or weight decay values are passed. To control training behaviour, use the [`callback`](/callback.html#callback) system or one or more of the pre-defined [`callbacks`](/callbacks.html#callbacks)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"Total time: 00:05
\n",
" \n",
" epoch \n",
" train_loss \n",
" valid_loss \n",
" accuracy \n",
" \n",
" \n",
" 1 \n",
" 0.135587 \n",
" 0.082969 \n",
" 0.973503 \n",
" \n",
"
\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"learn.fit(1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> fit_one_cycle(**`learn`**:[`Learner`](/basic_train.html#Learner), **`cyc_len`**:`int`, **`max_lr`**:`Union`\\[`float`, `Collection`\\[`float`\\], `slice`\\]=***`slice(None, 0.003, None)`***, **`moms`**:`Point`=***`(0.95, 0.85)`***, **`div_factor`**:`float`=***`25.0`***, **`pct_start`**:`float`=***`0.3`***, **`wd`**:`float`=***`None`***, **`callbacks`**:`Optional`\\[`Collection`\\[[`Callback`](/callback.html#Callback)\\]\\]=***`None`***, **`tot_epochs`**:`int`=***`None`***, **`start_epoch`**:`int`=***`1`***)\n",
"\n",
"Fit a model following the 1cycle policy. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.fit_one_cycle)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Use cycle length `cyc_len`, a per cycle maximal learning rate `max_lr`, momentum `moms`, division factor `div_factor`, weight decay `wd`, and optional callbacks [`callbacks`](/callbacks.html#callbacks). Uses the [`OneCycleScheduler`](/callbacks.one_cycle.html#OneCycleScheduler) callback. Please refer to [What is 1-cycle](/callbacks.one_cycle.html#What-is-1cycle?) for a conceptual background of 1-cycle training policy and more technical details on what do the method's arguments do."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"Total time: 00:04
\n",
" \n",
" epoch \n",
" train_loss \n",
" valid_loss \n",
" accuracy \n",
" \n",
" \n",
" 1 \n",
" 0.080337 \n",
" 0.062688 \n",
" 0.978901 \n",
" \n",
"
\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"learn.fit_one_cycle(1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> lr_find(**`learn`**:[`Learner`](/basic_train.html#Learner), **`start_lr`**:`Floats`=***`1e-07`***, **`end_lr`**:`Floats`=***`10`***, **`num_it`**:`int`=***`100`***, **`stop_div`**:`bool`=***`True`***, **`wd`**:`float`=***`None`***)\n",
"\n",
"Explore lr from `start_lr` to `end_lr` over `num_it` iterations in `learn`. If `stop_div`, stops when loss diverges. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.lr_find)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Runs the learning rate finder defined in [`LRFinder`](/callbacks.lr_finder.html#LRFinder), as discussed in [Cyclical Learning Rates for Training Neural Networks](https://arxiv.org/abs/1506.01186). "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"LR Finder is complete, type {learner_name}.recorder.plot() to see the graph.\n"
]
}
],
"source": [
"learn.lr_find()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"learn.recorder.plot()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### See results"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> get_preds(**`ds_type`**:[`DatasetType`](/basic_data.html#DatasetType)=***``***, **`with_loss`**:`bool`=***`False`***, **`n_batch`**:`Optional`\\[`int`\\]=***`None`***, **`pbar`**:`Union`\\[`MasterBar`, `ProgressBar`, `NoneType`\\]=***`None`***) → `List`\\[`Tensor`\\]\n",
"\n",
"Return predictions and targets on `ds_type` dataset. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.get_preds)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It will run inference using the learner on all the data in the `ds_type` dataset and return the predictions; if `n_batch` is not specified, it will run the predictions on the default batch size. If `with_loss`, it will also return the loss on each prediction."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is how you check the default batch size."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"64"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"learn.data.batch_size"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[tensor([[9.9540e-01, 4.5968e-03],\n",
" [9.9925e-01, 7.5202e-04],\n",
" [9.9996e-01, 4.2987e-05],\n",
" ...,\n",
" [1.4036e-04, 9.9986e-01],\n",
" [1.0404e-01, 8.9596e-01],\n",
" [5.6783e-01, 4.3217e-01]]), tensor([0, 0, 0, ..., 1, 1, 1])]"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"preds = learn.get_preds()\n",
"preds"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The first element of the tuple is a tensor that contains all the predictions."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[9.9540e-01, 4.5968e-03],\n",
" [9.9925e-01, 7.5202e-04],\n",
" [9.9996e-01, 4.2987e-05],\n",
" ...,\n",
" [1.4036e-04, 9.9986e-01],\n",
" [1.0404e-01, 8.9596e-01],\n",
" [5.6783e-01, 4.3217e-01]])"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"preds[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"While the second element of the tuple is a tensor that contains all the targets."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([0, 0, 0, ..., 1, 1, 1])"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"preds[1]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor(0)"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"preds[1][0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To see what each category is, use:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['3', '7']"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"learn.data.classes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So category 0 is 3 while category 1 is 7."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(Image (3, 28, 28), Category 3)"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"learn.data.valid_ds[0]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"image/jpeg": "/9j/4AAQSkZJRgABAQEAZABkAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCgoKBggLDAsKDAkKCgr/2wBDAQICAgICAgUDAwUKBwYHCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgr/wAARCAAcABwDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+f+vSvC/7Gf7YHjjwBF8V/BX7KXxK1jwtO4SDxLpfgXULjT5GIJAW4jhMZOFY4Dfwn0rz7RdQt9J1m01S70e21GK2uY5ZdPvTIIblVYExSeU6PsYDadjK2CcMDgj9d9T+GP8Awd8+HfHui+J/DV58Wre21sQPoFr4N8VabN4asraSONYUS3tZ3sLS2SN0A3qkaBS2flZgAfkHdWtzY3Mlle28kM0MhSaGVCrIwOCpB5BB4INR19xf8HB/7Q/gv9ob/goEkvhrxF4f8S6x4L+HWg+FfHnj7wysQtPF/iK0tydQ1NTCqo376U24KjaVtV2/Livh2gAr7N/4IZftP/tK/Cz/AIKW/BX4bfC/x1rdx4f8Z/ELTPDXi3wi081zp2o6LqFzFbX6TWmTG6rbs8m4r+7MSyfwV8ZV7r+zr/wUA+KP7Knhu8T4HfDbwJo3jG40S60iz+KMegyHxDptncpLHOtrL532eGV4ppIjciA3ARsCUYGADiv2svBHgX4Z/tT/ABL+HHwvvRc+GfD/AMQNZ03w7crdLOJbGC+mit38xflkzGiHcOGzkda8/pWZnYu7EknJJPWkoA//2Q==\n",
"image/png": "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABHNCSVQICAgIfAhkiAAAAdJJREFUSIntVbGq4kAUvW9ZUZCQIqjBzlohhWAsLEQLwdZUNn6AkEbQD7AJthZWFnYWWgj+gKRIpRZiK1hpIYoY1BSZ86q12SUm8T2L5V04zcyZOffMvZf5ICLQG+PXO8V+BH8EfcVvN6RCoUC1Wo1yuRwlEgmaTqd0Op1ot9vRZDIhwzA8icIJqqrCsizYtg3GGGzbfoAxBsuysNlsIMuy4z1/8EEOg8/zPK3XaxqPx9Tv9x/roVCIKpUKxeNxKpVKJAgCzedzymQyrznUNA35fN4xY0mSHo7dOHz6pM8gSRIYY9B13RX/5S4tFosEgDqdjuszjhlxHAdRFBEMBv/a43ke+/0e2+0WHMe5cvh0LGazGUmSRIvFgo7HI41GI7rf70REpGkaRSIRqtfrdLlcvsZht9sFY+yfOBwOUBTFa92dCYFAALFYDNlsFo1GA+12G6ZpwrZt9Ho9P43mvTNlWcb1esX5fIYgCN8vSERoNptgjKFarb5HkIjAGMNyufR05uU5BOCJ////h0Q+69dqtQDgPU0TjUZxu91gGAbC4fDXCyaTSaiqClEUUS6Xoes6TNNEOp328zruiIqiYDAYYLVaYTgcIpVK+SqF44//HfEJXkMk1eKRk3QAAAAASUVORK5CYII=\n",
"text/plain": [
"Image (3, 28, 28)"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"learn.data.valid_ds[0][0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Indeed it is."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since [`get_preds`](/basic_train.html#get_preds) gets predictions on all the data in the `ds_type` dataset, here the number of predictions will be equal to the number of data in the validation dataset."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2038"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(learn.data.valid_ds)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(2038, 2038)"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(preds[0]), len(preds[1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since the dataset we are working on is a categorization dataset, every prediction contains two numbers; the first one indicates the probability that the item belongs to the first category, and the second one indicates the probability that it belongs to the second."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[9.9540e-01, 4.5968e-03],\n",
" [9.9925e-01, 7.5202e-04],\n",
" [9.9996e-01, 4.2987e-05],\n",
" ...,\n",
" [1.4036e-04, 9.9986e-01],\n",
" [1.0404e-01, 8.9596e-01],\n",
" [5.6783e-01, 4.3217e-01]])"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"preds[0]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([0.9954, 0.0046])"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"preds[0][0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here, the first number is the predicted probability that the item is a 3, while the second number 7."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"image/jpeg": "/9j/4AAQSkZJRgABAQEAZABkAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCgoKBggLDAsKDAkKCgr/2wBDAQICAgICAgUDAwUKBwYHCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgr/wAARCAAcABwDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+f+vSvC/7Gf7YHjjwBF8V/BX7KXxK1jwtO4SDxLpfgXULjT5GIJAW4jhMZOFY4Dfwn0rz7RdQt9J1m01S70e21GK2uY5ZdPvTIIblVYExSeU6PsYDadjK2CcMDgj9d9T+GP8Awd8+HfHui+J/DV58Wre21sQPoFr4N8VabN4asraSONYUS3tZ3sLS2SN0A3qkaBS2flZgAfkHdWtzY3Mlle28kM0MhSaGVCrIwOCpB5BB4INR19xf8HB/7Q/gv9ob/goEkvhrxF4f8S6x4L+HWg+FfHnj7wysQtPF/iK0tydQ1NTCqo376U24KjaVtV2/Livh2gAr7N/4IZftP/tK/Cz/AIKW/BX4bfC/x1rdx4f8Z/ELTPDXi3wi081zp2o6LqFzFbX6TWmTG6rbs8m4r+7MSyfwV8ZV7r+zr/wUA+KP7Knhu8T4HfDbwJo3jG40S60iz+KMegyHxDptncpLHOtrL532eGV4ppIjciA3ARsCUYGADiv2svBHgX4Z/tT/ABL+HHwvvRc+GfD/AMQNZ03w7crdLOJbGC+mit38xflkzGiHcOGzkda8/pWZnYu7EknJJPWkoA//2Q==\n",
"image/png": "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABHNCSVQICAgIfAhkiAAAAdJJREFUSIntVbGq4kAUvW9ZUZCQIqjBzlohhWAsLEQLwdZUNn6AkEbQD7AJthZWFnYWWgj+gKRIpRZiK1hpIYoY1BSZ86q12SUm8T2L5V04zcyZOffMvZf5ICLQG+PXO8V+BH8EfcVvN6RCoUC1Wo1yuRwlEgmaTqd0Op1ot9vRZDIhwzA8icIJqqrCsizYtg3GGGzbfoAxBsuysNlsIMuy4z1/8EEOg8/zPK3XaxqPx9Tv9x/roVCIKpUKxeNxKpVKJAgCzedzymQyrznUNA35fN4xY0mSHo7dOHz6pM8gSRIYY9B13RX/5S4tFosEgDqdjuszjhlxHAdRFBEMBv/a43ke+/0e2+0WHMe5cvh0LGazGUmSRIvFgo7HI41GI7rf70REpGkaRSIRqtfrdLlcvsZht9sFY+yfOBwOUBTFa92dCYFAALFYDNlsFo1GA+12G6ZpwrZt9Ho9P43mvTNlWcb1esX5fIYgCN8vSERoNptgjKFarb5HkIjAGMNyufR05uU5BOCJ////h0Q+69dqtQDgPU0TjUZxu91gGAbC4fDXCyaTSaiqClEUUS6Xoes6TNNEOp328zruiIqiYDAYYLVaYTgcIpVK+SqF44//HfEJXkMk1eKRk3QAAAAASUVORK5CYII=\n",
"text/plain": [
"Image (3, 28, 28)"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"learn.data.valid_ds[0][0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To get predictions on the entire training dataset, simply set the `ds_type` argument accordingly."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[tensor([[1.6543e-02, 9.8346e-01],\n",
" [9.9998e-01, 1.5066e-05],\n",
" [5.2995e-04, 9.9947e-01],\n",
" ...,\n",
" [9.9844e-01, 1.5631e-03],\n",
" [3.9617e-05, 9.9996e-01],\n",
" [4.1428e-05, 9.9996e-01]]), tensor([1, 0, 1, ..., 0, 1, 1])]"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"learn.get_preds(ds_type=DatasetType.Train)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To also get prediction loss along with the predictions and the targets, set `with_loss=True` in the arguments."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[tensor([[9.9540e-01, 4.5968e-03],\n",
" [9.9925e-01, 7.5202e-04],\n",
" [9.9996e-01, 4.2987e-05],\n",
" ...,\n",
" [1.4036e-04, 9.9986e-01],\n",
" [1.0404e-01, 8.9596e-01],\n",
" [5.6783e-01, 4.3217e-01]]),\n",
" tensor([0, 0, 0, ..., 1, 1, 1]),\n",
" tensor([4.6074e-03, 7.5221e-04, 4.2915e-05, ..., 1.4043e-04, 1.0986e-01,\n",
" 8.3894e-01])]"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"learn.get_preds(with_loss=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that the third tensor in the output tuple contains the losses."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> validate(**`dl`**=***`None`***, **`callbacks`**=***`None`***, **`metrics`**=***`None`***)\n",
"\n",
"Validate on `dl` with potential `callbacks` and `metrics`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.validate)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Return the calculated loss and the metrics of the current model on the given data loader `dl`. The default data loader `dl` is the validation dataloader."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can check the default metrics of the learner using:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'[]'"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"str(learn.metrics)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0.062688194, tensor(0.9789)]"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"learn.validate()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0.062688194, tensor(0.9789)]"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"learn.validate(learn.data.valid_dl)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0.044597004, tensor(0.9832)]"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"learn.validate(learn.data.train_dl)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> show_results(**`ds_type`**=***``***, **`rows`**:`int`=***`5`***, **\\*\\*`kwargs`**)\n",
"\n",
"Show `rows` result of predictions on `ds_type` dataset. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.show_results)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> predict(**`item`**:[`ItemBase`](/core.html#ItemBase), **\\*\\*`kwargs`**)\n",
"\n",
"Return predicted class, label and probabilities for `item`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.predict)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> pred_batch(**`ds_type`**:[`DatasetType`](/basic_data.html#DatasetType)=***``***, **`batch`**:`Tuple`=***`None`***, **`reconstruct`**:`bool`=***`False`***) → `List`\\[`Tensor`\\]\n",
"\n",
"Return output of the model on one batch from `ds_type` dataset. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.pred_batch)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> interpret(**`learn`**:[`Learner`](/basic_train.html#Learner), **`ds_type`**:[`DatasetType`](/basic_data.html#DatasetType)=***``***, **`tta`**=***`False`***)\n",
"\n",
"Create a [`ClassificationInterpretation`](/train.html#ClassificationInterpretation) object from `learner` on `ds_type` with `tta`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.interpret, full_name='interpret')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
" Note: This function only works in the vision application.
"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"jekyll_note('This function only works in the vision application.')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Model summary"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> model_summary(**`m`**:[`Learner`](/basic_train.html#Learner), **`n`**:`int`=***`70`***)\n",
"\n",
"Print a summary of `m` using a output text width of `n` chars "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.summary)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Test time augmentation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> TTA(**`learn`**:[`Learner`](/basic_train.html#Learner), **`beta`**:`float`=***`0.4`***, **`scale`**:`float`=***`1.35`***, **`ds_type`**:[`DatasetType`](/basic_data.html#DatasetType)=***``***, **`with_loss`**:`bool`=***`False`***) → `Tensors`\n",
"\n",
"Applies TTA to predict on `ds_type` dataset. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.TTA, full_name = 'TTA')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Applies Test Time Augmentation to `learn` on the dataset `ds_type`. We take the average of our regular predictions (with a weight `beta`) with the average of predictions obtained through augmented versions of the training set (with a weight `1-beta`). The transforms decided for the training set are applied with a few changes `scale` controls the scale for zoom (which isn't random), the cropping isn't random but we make sure to get the four corners of the image. Flipping isn't random but applied once on each of those corner images (so that makes 8 augmented versions total)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Gradient clipping"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> clip_grad(**`learn`**:[`Learner`](/basic_train.html#Learner), **`clip`**:`float`=***`0.1`***) → [`Learner`](/basic_train.html#Learner)\n",
"\n",
"Add gradient clipping of `clip` during training. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.clip_grad)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Mixed precision training"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> to_fp16(**`learn`**:[`Learner`](/basic_train.html#Learner), **`loss_scale`**:`float`=***`None`***, **`max_noskip`**:`int`=***`1000`***, **`dynamic`**:`bool`=***`False`***, **`clip`**:`float`=***`None`***, **`flat_master`**:`bool`=***`False`***) → [`Learner`](/basic_train.html#Learner)\n",
"\n",
"Put `learn` in FP16 precision mode. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.to_fp16)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Uses the [`MixedPrecision`](/callbacks.fp16.html#MixedPrecision) callback to train in mixed precision (i.e. forward and backward passes using fp16, with weight updates using fp32), using all [NVIDIA recommendations](https://docs.nvidia.com/deeplearning/sdk/mixed-precision-training/index.html) for ensuring speed and accuracy."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> to_fp32(**`learn`**:[`Learner`](/basic_train.html#Learner))\n",
"\n",
"Put `learn` back to FP32 precision mode. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.to_fp32)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Distributed training"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> distributed(**`learn`**:[`Learner`](/basic_train.html#Learner), **`cuda_id`**:`int`, **`cache_dir`**:`PathOrStr`=***`'tmp'`***)\n",
"\n",
"Put `learn` on distributed training with `cuda_id`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.distributed, full_name='distributed')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Discriminative layer training"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When fitting a model you can pass a list of learning rates (and/or weight decay amounts), which will apply a different rate to each *layer group* (i.e. the parameters of each module in `self.layer_groups`). See the [Universal Language Model Fine-tuning for Text Classification](https://arxiv.org/abs/1801.06146) paper for details and experimental results in NLP (we also frequently use them successfully in computer vision, but have not published a paper on this topic yet). When working with a [`Learner`](/basic_train.html#Learner) on which you've called `split`, you can set hyperparameters in four ways:\n",
"\n",
"1. `param = [val1, val2 ..., valn]` (n = number of layer groups)\n",
"2. `param = val`\n",
"3. `param = slice(start,end)`\n",
"4. `param = slice(end)`\n",
"\n",
"If we chose to set it in way 1, we must specify a number of values exactly equal to the number of layer groups. If we chose to set it in way 2, the chosen value will be repeated for all layer groups. See [`Learner.lr_range`](/basic_train.html#Learner.lr_range) for an explanation of the `slice` syntax).\n",
"\n",
"Here's an example of how to use discriminative learning rates (note that you don't actually need to manually call [`Learner.split`](/basic_train.html#Learner.split) in this case, since fastai uses this exact function as the default split for `resnet18`; this is just to show how to customize it):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# creates 3 layer groups\n",
"learn.split(lambda m: (m[0][6], m[1]))\n",
"# only randomly initialized head now trainable\n",
"learn.freeze()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"Total time: 00:04
\n",
" \n",
" epoch \n",
" train_loss \n",
" valid_loss \n",
" accuracy \n",
" \n",
" \n",
" 1 \n",
" 0.069001 \n",
" 0.045998 \n",
" 0.983317 \n",
" \n",
"
\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"learn.fit_one_cycle(1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"Total time: 00:06
\n",
" \n",
" epoch \n",
" train_loss \n",
" valid_loss \n",
" accuracy \n",
" \n",
" \n",
" 1 \n",
" 0.021191 \n",
" 0.008666 \n",
" 0.997056 \n",
" \n",
"
\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# all layers now trainable\n",
"learn.unfreeze()\n",
"# optionally, separate LR and WD for each group\n",
"learn.fit_one_cycle(1, max_lr=(1e-4, 1e-3, 1e-2), wd=(1e-4,1e-4,1e-1))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> lr_range(**`lr`**:`Union`\\[`float`, `slice`\\]) → `ndarray`\n",
"\n",
"Build differential learning rates from `lr`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.lr_range)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Rather than manually setting an LR for every group, it's often easier to use [`Learner.lr_range`](/basic_train.html#Learner.lr_range). This is a convenience method that returns one learning rate for each layer group. If you pass `slice(start,end)` then the first group's learning rate is `start`, the last is `end`, and the remaining are evenly geometrically spaced.\n",
"\n",
"If you pass just `slice(end)` then the last group's learning rate is `end`, and all the other groups are `end/10`. For instance (for our learner that has 3 layer groups):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(array([1.e-05, 1.e-04, 1.e-03]), array([0.0001, 0.0001, 0.001 ]))"
]
},
"execution_count": null,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"learn.lr_range(slice(1e-5,1e-3)), learn.lr_range(slice(1e-3))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> unfreeze()\n",
"\n",
"Unfreeze entire model. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.unfreeze)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sets every layer group to *trainable* (i.e. `requires_grad=True`)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> freeze()\n",
"\n",
"Freeze up to last layer. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.freeze)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sets every layer group except the last to *untrainable* (i.e. `requires_grad=False`)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> freeze_to(**`n`**:`int`)\n",
"\n",
"Freeze layers up to layer `n`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.freeze_to)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> split(**`split_on`**:`SplitFuncOrIdxList`)\n",
"\n",
"Split the model at `split_on`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.split)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A convenience method that sets `layer_groups` based on the result of [`split_model`](/torch_core.html#split_model). If `split_on` is a function, it calls that function and passes the result to [`split_model`](/torch_core.html#split_model) (see above for example)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Saving and loading models"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Simply call [`Learner.save`](/basic_train.html#Learner.save) and [`Learner.load`](/basic_train.html#Learner.load) to save and load models. Only the parameters are saved, not the actual architecture (so you'll need to create your model in the same way before loading weights back in). Models are saved to the `path`/`model_dir` directory."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> load(**`name`**:`PathOrStr`, **`device`**:[`device`](https://pytorch.org/docs/stable/tensor_attributes.html#torch-device)=***`None`***, **`strict`**:`bool`=***`True`***, **`with_opt`**:`bool`=***`None`***, **`purge`**:`bool`=***`True`***)\n",
"\n",
"Load model and optimizer state (if `with_opt`) `name` from `self.model_dir` using `device`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.load)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> save(**`name`**:`PathOrStr`, **`return_path`**:`bool`=***`False`***, **`with_opt`**:`bool`=***`True`***)\n",
"\n",
"Save model and optimizer state (if `with_opt`) with `name` to `self.model_dir`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.save)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Deploying your model"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When you are ready to put your model in production, export the minimal state of your [`Learner`](/basic_train.html#Learner) with"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> export(**`fname`**:`str`=***`'export.pkl'`***)\n",
"\n",
"Export the state of the [`Learner`](/basic_train.html#Learner) in `self.path/fname`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.export)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Then you can load it with the following function."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> load_learner(**`path`**:`PathOrStr`, **`fname`**:`PathOrStr`=***`'export.pkl'`***, **`test`**:[`ItemList`](/data_block.html#ItemList)=***`None`***)\n",
"\n",
"Load a [`Learner`](/basic_train.html#Learner) object saved with `export_state` in `path/fn` with empty data, optionally add `test` and load on `cpu`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(load_learner)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can find more information and multiple examples in [this tutorial](/tutorial.inference.html)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Other methods"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> init(**`init`**)"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.init)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Initializes all weights (except batchnorm) using function `init`, which will often be from PyTorch's [`nn.init`](https://pytorch.org/docs/stable/nn.html#torch-nn-init) module."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> mixup(**`learn`**:[`Learner`](/basic_train.html#Learner), **`alpha`**:`float`=***`0.4`***, **`stack_x`**:`bool`=***`False`***, **`stack_y`**:`bool`=***`True`***) → [`Learner`](/basic_train.html#Learner)\n",
"\n",
"Add mixup https://arxiv.org/abs/1710.09412 to `learn`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.mixup)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Uses [`MixUpCallback`](/callbacks.mixup.html#MixUpCallback)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> backward(**`item`**)\n",
"\n",
"Pass `item` through the model and computes the gradient. Useful if `backward_hooks` are attached. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.backward)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> create_opt(**`lr`**:`Floats`, **`wd`**:`Floats`=***`0.0`***)\n",
"\n",
"Create optimizer with `lr` learning rate and `wd` weight decay. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.create_opt)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You generally won't need to call this yourself - it's used to create the [`optim`](https://pytorch.org/docs/stable/optim.html#module-torch.optim) optimizer before fitting the model."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> dl(**`ds_type`**:[`DatasetType`](/basic_data.html#DatasetType)=***``***)\n",
"\n",
"Return DataLoader for DatasetType `ds_type`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.dl)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> Recorder(**`learn`**:[`Learner`](/basic_train.html#Learner)) :: [`LearnerCallback`](/basic_train.html#LearnerCallback)\n",
"\n",
"A [`LearnerCallback`](/basic_train.html#LearnerCallback) that records epoch, loss, opt and metric data during training. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Recorder, title_level=2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A [`Learner`](/basic_train.html#Learner) creates a [`Recorder`](/basic_train.html#Recorder) object automatically - you do not need to explicitly pass it to `callback_fns` - because other callbacks rely on it being available. It stores the smoothed loss, hyperparameter values, and metrics for each batch, and provides plotting methods for each. Note that [`Learner`](/basic_train.html#Learner) automatically sets an attribute with the snake-cased name of each callback, so you can access this through `Learner.recorder`, as shown below."
]
},
{
"cell_type": "markdown",
"metadata": {
"hide_input": true
},
"source": [
"### Plotting methods"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> plot(**`skip_start`**:`int`=***`10`***, **`skip_end`**:`int`=***`5`***)\n",
"\n",
"Plot learning rate and losses, trimmed between `skip_start` and `skip_end`. Optionally plot and return min gradient "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Recorder.plot)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is mainly used with the learning rate finder, since it shows a scatterplot of loss vs learning rate."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"LR Finder is complete, type {learner_name}.recorder.plot() to see the graph.\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"learn = create_cnn(data, models.resnet18, metrics=accuracy)\n",
"learn.lr_find()\n",
"learn.recorder.plot()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> plot_losses(**`last`**:`int`=***`None`***)\n",
"\n",
"Plot training and validation losses. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Recorder.plot_losses)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that validation losses are only calculated once per epoch, whereas training losses are calculated after every batch."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"Total time: 00:09
\n",
" \n",
" epoch \n",
" train_loss \n",
" valid_loss \n",
" accuracy \n",
" \n",
" \n",
" 1 \n",
" 0.193293 \n",
" 0.107442 \n",
" 0.968106 \n",
" \n",
" \n",
" 2 \n",
" 0.093543 \n",
" 0.076363 \n",
" 0.977429 \n",
" \n",
"
\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"learn.fit_one_cycle(2)\n",
"learn.recorder.plot_losses()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> plot_lr(**`show_moms`**=***`False`***)\n",
"\n",
"Plot learning rate, `show_moms` to include momentum. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Recorder.plot_lr)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAtwAAAD8CAYAAABEmnN2AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzs3Xd8leX5x/HPlR0SErKBhBFCEggQVgCRKYjiBBG31Vqt1qqto1Vw1WqdraO/Olqtq25EoKA4UIaAiISRhAAJYSYkZEASQva4f3/k2KYxwAGSPGdc79eLlyfPuZ8n31PoyZXn3Pd1izEGpZRSSimlVMfwsDqAUkoppZRSrkwLbqWUUkoppTqQFtxKKaWUUkp1IC24lVJKKaWU6kBacCullFJKKdWBtOBWSimllFKqA2nBrZRSSimlVAfSglsppZRSSqkOpAW3UkoppZRSHcjL6gDtITw83PTt29fqGEopddI2btxYYoyJsDpHZ9L3bKWUMzuV922XKLj79u1Lamqq1TGUUuqkicg+qzN0Nn3PVko5s1N539YpJUoppZRSSnUgLbiVUkoppZTqQFpwK6WUUkop1YG04FZKKaWUUqoDacGtlFJKKaVUB7Kr4BaR6SKSJSI5IjKnjed9ReQj2/PrRaRvi+fm2o5nici5tmN+IvKDiKSJSKaI/LHF+FjbNXbarulz+i9TKaWUUkopa5yw4BYRT+Al4DwgCbhKRJJaDbsRKDXG9AeeB562nZsEXAkMAqYDL9uuVwtMMcYMBYYB00XkDNu1ngaeN8bEA6W2ayullFJKKeWU7OnDPRrIMcbsBhCRD4EZwLYWY2YAj9gezwdeFBGxHf/QGFML7BGRHGC0MWYdcNQ23tv2x9jOmQJcbXvubdt1XzmlV6c6TG1DI5v3l7Et/whVdQ0A+Pt4EdLFm5AuPsSE+NMrtAt+3p4WJ1VKuYKPU3MpOVpHdIg/Z8aFER7oa3UkpZSTqKxtILe0irzD1RyuquNoTQNHaxs4My6MlL6hnZLBnoI7Gsht8XUeMOZYY4wxDSJSDoTZjn/f6txo+M+d841Af+AlY8x6EQkHyowxDa3HtyYiNwM3A/Tu3duOl6HaQ0VNPX9ftYsPfsjlcGXdcceKQHQ3f4ZEBzOidwgj+oQwNCYYL09dOqCUOjmL0/JZvbMEaH5vmZIYyV3TEhgcHWxxMqWUI6ltaGTjvlJS95aSnldOxoEyCo/UtjnW23OAQxXc0sYxY+eYY55rjGkEholIN2ChiAwGCu34XtjOfxV4FSAlJaXNMap9rcwq4vfz0yk5Wss5SVFcOiKG4b1DCPb3BqC6rpHDVXUcrqwjr7SK3cWV7Co+SlpeGZ9vPQhAsL83ExMiOHtgJGcPjCLA1yU2O1VKdbB3bhxDZW0Du4sr+WrbQf61bh8XvbiGWyfFcde0BLz1F3ml3FZ5VT2fby3gq22FfL/7EFV1jYhAv/AAzowLJz4qkN6hXYgJ6UJ4oA9dfb0J8PXs1BuA9lQ7eUCvFl/HAPnHGJMnIl5AMHDYnnONMWUispLmOd7PAt1ExMt2l7ut76U6mTGGl1fu4i9fZZEY1ZV/XpfC0F7dfjLOx8uD4C7exIYHMLJPyP88V1RRw4Y9pazIKmJlVhFL0vLp4uPJ9EHdmT0yhrFxYTTPKFJKqbYF+HoxJCaYITHB/HJiPx7/dDsvr9xFel45f//ZSAL1F3il3EZjk2H5jiI+2rCfVdnF1DcaeoX6c+mIGCYmRDCmXyhBft5Wx/wPe96dNgDxIhILHKB5EeTVrcYsBq4H1gGzgeXGGCMii4H3ReQ5oCcQD/wgIhFAva3Y9gfOBp62nbPCdo0Pbdf892m/SnXKjDE882UWr6zcxcVDe/L0pcn4+5z8vOzIrn5ckNyDC5J70NRk2Li/lAWbDvBpej4LNh8gISqQG8bFcsnwaJ33rZQ6oSA/b56enUxK3xDmLMjgmte+571fnqFFt1Iurry6nvfX7+fd7/dxoKyayK6+XD+2LzOGRTM4Oshhb96JMSeejSEi5wMvAJ7AG8aYx0XkUSDVGLNYRPyAd4DhNN/ZvrLFIssHgF8ADcCdxpjPRSSZ5gWRnjR3SplnjHnUNr4fzcV2KLAZuNa26PKYUlJSTGpq6sm/enVCL6/M4Zkvsrh6TG/+NGMwHh7t+w+5pr6RT9MLeGPNHrYVHCE80IdfTYrj2jP6aOGt3IKIbDTGpFidozO193v2V5kHufW9TZwZF8br14/Cx0unlyjlasqr63lr7V5eX7ObIzUNjO0XxnVj+zAtKarT14adyvu2XQW3o9OCu2N8ll7Abe9v4uKhPXnhimHtXmy3ZIzh+92HeXHFTtbmHCKyqy93TI3n6tG98ezA76uU1bTgbh8fp+by+/npXHtGb/40c0i7XlspZZ2a+kZe+3Y3r61uLrTPSYriN1PjLV0wfSrv2/rZm2rT7uKj3Ds/jZF9QnhmdnKHFtsAIsLYuDDGxoXx/e5DPPdVNg8t2sr76/fzyEVJjOkX1qHfXynl3C5L6cXOoqO8+u1uRvUNZcawNhtcKaWchDGGLzMP8tin2zlQVs20pCh+a3GhfTr0czf1E7UNjdz2/mZ8vDx48erhnT6144x+YXx0yxm8fM0IjlTXc8Wr33P7+5soOlLTqTmUUs7l9+cmMqpvCA8s3MqBsmqr4yilTtHu4qNc+/p6fvXuJrr6efHBL8/gtetSnLbYBi24VRteWbmL7QVHeGb2UHoE+1uSQUQ4f0gPvr57Er+dGs+ybYVMe/5bFm0+gCtMg1JKtT9vTw+eu3wYTcYw55N0fa9Qysk0Nhn+uXo35/11NRl55Tw6YxCf3jGesXHO/ym3Ftzqf+QUVfDyil1cNLQn05KirI6Dv48nd01LYOlvJxAXEcCdH23hlnc2Ulxx3HW0Sik31Su0C3PPH8jqnSUs3HzA6jhKKTvtKankin+s40+fbWdCfDhf3z2J68b2dZnN8lzjVah20dRkmLsgA38fTx6+MMnqOP8jLiKQj391JvefP4CV2cVMf+Fbvs0utjqWUsoBXTO6N0N7deOpz3dQWdtw4hOUUpb6ZGMe5/91NdmFFTx3+VBeuy6FyCA/q2O1Ky241X8s3HyADXtLeeCCgUR09bU6zk94egg3T4zjszvGEx7oy/Vv/sCzX2XR2KQfGyul/svDQ/jDRUkUVdTy8socq+MopY6huq6Re+encc/HaSTHBPPVXZOYNSLGYXtpnw4tuBXQ3Hbn2a+ySI4JZvaIGKvjHFd8VFcW3TaOy0bG8LflOVzzz+91QaVS6n+M6B3CrOHRvLZ6D/sPVVkdRynVyq7io8x8aS0fb8zjjin9ee+mMXQPdq272i1pwa0AeOu7veSX1zDnvAEd3gKwPfj7ePLM7KE8e9lQ0nLLufjFtWw9UG51LKWUA7nvvAF4CLzwdbbVUZRSLazMKmLmi2spPlrL2zeM5p5zEl1mrvaxuParU3YprazjpRU5TBkQyZlx4VbHOSmXjoxh/q1j8RC47O/r+GJrgdWRlFIOIirIj+vG9mXRlgPsLj5qdRyl3J4xhjfX7uEXb20gJrQLS+4Yz8SECKtjdQotuBWvrt7N0doG7ps+wOoop2RQz2AW3T6OxO5d+dW7m3hx+U5tB6aUAuDmif3w8fLgb8t1LrdSVqpvbOKBRVv545JtTB0YxfxfjSW6mzWth62gBbebK6+q5511+zh/SA8Su3e1Os4pi+zqx4c3n8HMYT35y1fZ3L9wqy6mVOokiMh0EckSkRwRmdPG831E5BsRSReRlSIS0+r5IBE5ICIvdl7qEwsP9OW6sX3595YD7NK73EpZorqukVve2cj76/dz6+Q4/nHtSAJ83Wuzcy243dzb6/ZytLaB2yb3tzrKafPz9uT5K4bx68lxfPDDfm57bxM19Y1Wx1LK4YmIJ/AScB6QBFwlIq17g/4F+JcxJhl4FHiy1fOPAas6OuupuHliP3y9PHl5xS6royjldsqq6rjmn9+zMquIxy8ZzH3TnWOtWHvTgtuNVdY28MbaPUwdEElSzyCr47QLEeHe6QN46MIkvsg8yM/f/IEjNfVWx1LK0Y0Gcowxu40xdcCHwIxWY5KAb2yPV7R8XkRGAlHAV52Q9aSFB/pyeUoMi9MOaEcjpTpRQXk1l/19HVsPHOGlq0dwzZg+VkeyjBbcbuyDH/ZTVlXPbVOc/+52azeOj+WFK4aRureUa15bT1lVndWRlHJk0UBui6/zbMdaSgMutT2+BOgqImEi4gE8C/y+w1OehhvGxdLQZHjn+31WR1HKLeQermL2K+soKK/hrV+M4rwhPayOZCktuN1UQ2MTb67dy+jYUEb0DrE6ToeYOTyaV68bSVZhBVe/tp7SSi26lTqGtj7fbb0I4nfAJBHZDEwCDgANwK+BpcaYXI5DRG4WkVQRSS0u7vxdYvuGBzBtYBTvfr+P6jqdaqZUR8o9XMWVr37P0doGPvjlGU7XAa0jaMHtpr7eXsSBsmp+MS7W6igdasqAKF67LoWc4qNc9dr3HDpaa3UkpRxRHtCrxdcxQH7LAcaYfGPMLGPMcOAB27FyYCxwu4jspXme93Ui8lTrb2CMedUYk2KMSYmIsKYN2I3jYymtqmfB5jxLvr9S7mD/oSqu+Mc6KusaeO+mMQyJCbY6kkPQgttNvbl2D9Hd/JmWFGV1lA43KSGCN64fxZ6SSq5+bb0W3Ur91AYgXkRiRcQHuBJY3HKAiITbpo8AzAXeADDGXGOM6W2M6UvzXfB/GWN+0uXEEYyODWVIdDBvrd2rrUOV6gD7DlVyxavrqKpv5L2bxjA4WovtH2nB7YYy88tZv+cw15/ZB083WSk8Pj6cN38+in2HK7nuDV1IqVRLxpgG4HbgS2A7MM8Ykykij4rIxbZhk4EsEcmmeYHk45aEPQ0iwrVn9GZn0VFS95VaHUcpl/LjNJKa+kbev+kMBvXUYrslLbjd0Nvf7cXf25MrUnpbHaVTndk/nL9fO5LswgpufGuDzuNUqgVjzFJjTIIxJs4Y87jt2MPGmMW2x/ONMfG2MTcZY37yUZEx5i1jzO2dnf1kXDS0J119vXh//X6royjlMooqarj29fVU1TXy/i/PcJnOZ+1JC243U1FTz5K0AmYM60lwF2+r43S6yYmR/PXK4WzcV8ot726ktkGLbqXcSRcfL2YOj+azjALtXqRUOyivque613+guKKWN28YxcAeWmy3RQtuN7MkrYDq+kauHO1ed7dbOn9ID56alcy32cXc+eEWGhqbrI6klOpEV4/pTV1DE59sOmB1FKWcWlVdA794ewO7io/yj5+NdNmuZ+1BC24389GG/Qzo3pWhbr5q+PJRvXjowiQ+33qQBxZu1QVUSrmRgT2CGN67Gx/8sF//v6/UKapraOLWdzexeX8pf71yOBPirek+5Cy04HYj2wuOkJZXzuUpvRBxj8WSx3Pj+FjumNKfj1JzeXF5jtVxlFKd6IqUXuQUHSXjQLnVUZRyOsYY7vsknVXZxTw5awjnu/mmNvbQgtuNfLQhFx9PDy4Z3noDOfd197QEZg2P5tll2SzU3rxKuY3zhvTAx8uDBTqtRKmT9vzXO1m4+QD3TEvgilHuO0X1ZNhVcIvIdBHJEpEcEflJf1UR8RWRj2zPrxeRvi2em2s7niUi59qO9RKRFSKyXUQyReS3LcY/IiIHRGSL7c/5p/8yVU19Iws3H+Dcwd0JCfCxOo7DEBGeujSZM+PCuHd+Ot/llFgdSSnVCYL9vZk2MIolafnU6zoOpew2f2Me//fNTi5PieH2Kf2tjuM0Tlhwi4gn8BJwHpAEXCUiSa2G3QiUGmP6A88DT9vOTaJ5A4VBwHTgZdv1GoB7jDEDgTOA21pd83ljzDDbn6Wn9QoVAF9tK6S8up4rUnqdeLCb8fHy4JVrRxIbHsAt724k62CF1ZGUUp1g1ohoDlXW8W125281r5Qz+i6nhDmfpDOufxiPXzJEp6eeBHvucI8Gcowxu40xdcCHwIxWY2YAb9sezwemSvPfwgzgQ2NMrTFmD5ADjDbGFBhjNgEYYypo3mhB5zl0oPkb84ju5s+ZcWFWR3FIwf7evHnDaPy9Pbnhzeb2Rkop1zYxIYKwAB+dVqKUHXYWVnDLuxuJDQ/g5WtG4u2ps5JPhj3/a0UDuS2+zuOnxfF/xth2LCsHwuw51zb9ZDiwvsXh20UkXUTeEJE2e8yIyM0ikioiqcXFenfieIoralmzs5iZw3vi4SY7S56K6G7+vPHzURyuquNW7dGtlMvz9vTgoqE9Wba9+RNApVTbSivr+MXbG/D18uTNG0YR7O9++3icLnsK7rYqtNZ9lI415rjnikgg8AlwpzHmiO3wK0AcMAwoAJ5tK5Qx5lVjTIoxJiUiQlvRHM9n6fk0GZg5TD9EOJHB0cH85bKhpO4r5aFF2i5QKVc3a0Q0dQ1NfJ5RYHUUpRxSQ2MTt72/icLyWl67biQxIV2sjuSU7Cm484CWE39jgPxjjRERLyAYOHy8c0XEm+Zi+z1jzIIfBxhjCo0xjcaYJuA1mqe0qNOwaEs+A3sEER/V1eooTuHC5J7cMaU/81LzeOu7vVbHUUp1oCHRwcRFBLBgs04rUaotTyzdwXe7DvH4JYMZrhvbnDJ7Cu4NQLyIxIqID82LIBe3GrMYuN72eDaw3DTfGlwMXGnrYhILxAM/2OZ3vw5sN8Y81/JCItKymeMlwNaTfVHqv/YdqmRLbhkzh/W0OopTuevsBM5JiuKxT7exeqdOWVLKVYkIFw3tyYa9hyk6UmN1HKUcyvyNebyxdg8/P7Mvl2nThdNywoLbNif7duBLmhc3zjPGZIrIoyJysW3Y60CYiOQAdwNzbOdmAvOAbcAXwG3GmEZgHPAzYEob7f+eEZEMEUkHzgLuaq8X647+vSUfEbhoqBbcJ8PDQ3j+imEkRHXltvc2sbek0upISqkOcsGQHhgDX2QetDqKUg5jS24Z9y/M4My4MB64YKDVcZyeuMIc1ZSUFJOammp1DIdjjGHqc6uICPTlo1vGWh3HKeUeruKiF9fQPciPhb8eh7+Pp9WRlIsRkY3GmBSrc3QmR3zPnvbcKkIDfPS9Uimg6EgNF724Bm9PDxbfPp5Q3b/jf5zK+7b2dHFhmflH2F1cyUzdWfKU9QrtwgtXDCOrsIIHdRGlUi7r/CE9+EGnlShFfWMTt763iSPVDbx2XYoW2+1EC24XtiQtH29P4bzB3a2O4tQmJ0bymynxfLIpjw9+yD3xCUopp3NBsk4rUQrg6c93sHFfKc/MTmZgjyCr47gMLbhdlDGGpVsLGNc/nG5d9LfT0/WbqfFMTIjgkcWZpOeVWR1HKdXOEqK6Eh8ZyGfp2h5Qua8vth7kn2v2cP3YPrr2q51pwe2iMvOPkHu4mvMH9zjxYHVCnh7CC1cMI6KrL7e+u4nSyjqrIyml2tl/ppVU6LQS5X72Hark9x+nMTQmmPt1kWS704LbRS3NKMDTQ5iWFGV1FJcRGuDDy9eMoLiiljs/2kJTk87nVsqV/Dit5MutOq1EuZea+kZ+/d4mPDyEF68ega+XNghob1pwuyBjDJ9vPciZcWGE6GKHdjW0VzceviiJVdnFvLJql9VxlFLtKCGqK3ERAXyuBbdyM39cso3M/CM8d/lQeoXqTpIdQQtuF5RVWMGekkqm62LJDnHNmN5cmNyD55Zls3HfYavjKKXa0TmDurN+z2HKq+qtjqJUp1i4OY8PftjPrybFMXWgfireUbTgdkFLMw7iIXBOkhbcHUFEeGLWEHp28+M3H2zRH8xKuZBpSVE0NhlWZBVZHUWpDre7+CgPLNzK6L6h/O6cBKvjuDQtuF3Q5xkFjI4NJaKrr9VRXFaQnzd/u2oEhUdquO+TdO3PrZSLGBbTjYiuvizbVmh1FKU6VF1DE7/9cAs+Xh789apheHlqSdiR9H9dF5NTVMHOoqOcP0S7k3S0Yb26ce/0RL7IPMi76/dbHUcp1Q48PISzB0axMquI2oZGq+Mo1WGe/SqLjAPlPDUrmR7B/lbHcXlacLuYLzOb78rodJLOcdP4fkxKiOCxT7exveCI1XGUUu3gnKQoKusa+W7XIaujKNUhVu8s5h/f7ubqMb11vVcn0YLbxSzbVsjQmGC6B/tZHcUteHgIz14+lGB/b+74YDNVdQ1WR1JKnaaxcWF08fHUaSXKJR06Wsvd89KIjwzkoQuSrI7jNrTgdiFFFTVsyS3T3tudLDzQlxeuGMau4qM8/tl2q+MopU6Tn7cnkxIi+HpbofbbVy7FGMPv56dTXl3P/101HH8f7bfdWbTgdiHfbG9eVX+2Ftydblz/cG4aH8t76/ezfIfeFVPK2U1LiqKoopb0A+VWR1Gq3bz93V6W7yji/vMGMLBHkNVx3IoW3C7k622FxIT4kxjV1eoobul35yYyoHtX7p2fwaGjtVbHUUqdhikDIvH0EJZt001wlGvYXnCEJz7fwZQBkVx/Zl+r47gdLbhdRFVdA2tySpiWFIWIWB3HLfl6efLClcM4Ul3PnAUZ2ipQKSfWrYsPI/uEsGJHsdVRlDpttQ2N3PnhFoL9vfnz7GStEyygBbeLWL2zhNqGJqbpLlGWGtA9iHunJ7JsWyHzUnOtjqOUOg1nJUayreAIB8trrI6i1Gl5blk2WYUVPHNpMmGBukeHFbTgdhHLthUS5OfFqNhQq6O4vV+Mi+XMuDD+uGQbe0sqrY6jlF1EZLqIZIlIjojMaeP5PiLyjYiki8hKEYmxHR8mIutEJNP23BWdn75jnDUgAoBV2brrpHJeG/Ye5tVvd3PV6F6cNSDS6jhuSwtuF9DYZFi+o4izBkTirTtFWc7DQ/jLZUPx8hDumreFhsYmqyMpdVwi4gm8BJwHJAFXiUjrfmF/Af5ljEkGHgWetB2vAq4zxgwCpgMviEi3zknesRKjutIz2I/lO7TgVs6psraBe+alERPizwPaAtBSWp25gM37SzlcWaftAB1Iz27+PDZzMJv3l/Hyyl1Wx1HqREYDOcaY3caYOuBDYEarMUnAN7bHK3583hiTbYzZaXucDxQBEZ2SuoOJCJMHRLJmZwl1DfqLs3I+jy/dTm5pFc9eNoxAXy+r47g1LbhdwLJthXh7ChMTXOJnnMuYMSyai4f25K/f7GSrthZTji0aaLnoIM92rKU04FLb40uAriIS1nKAiIwGfACX+S3zrMRIKusaSd172OooSp2UFVlFvL9+PzdP6MdonW5qOS24XcCy7YWc0S+MID9vq6OoVh6bMZiwAB9+93EatQ2NVsdR6ljaalnQus3O74BJIrIZmAQcAP6ztaqI9ADeAW4wxvzkdrCI3CwiqSKSWlzsPJ0/xvUPw8fTQ6eVKKdSVlXHffPTSYgK5K5pCVbHUWjB7fT2H6pid3ElU3QhhEMK7uLNk7OGsONgBX/7JsfqOEodSx7Qq8XXMUB+ywHGmHxjzCxjzHDgAduxcgARCQI+Ax40xnzf1jcwxrxqjEkxxqRERDjPp3FdfLwY0y+UFVlacCvn8dC/MzlcWcdzlw/Dz1t3k3QEdhXcdqxe9xWRj2zPrxeRvi2em2s7niUi59qO9RKRFSKy3bay/bctxoeKyDIR2Wn7b8jpv0zX9ePq+cmJWnA7qqkDo5g9MoZXVu0iPa/M6jhKtWUDEC8isSLiA1wJLG45QETCReTHnxlzgTdsx32AhTQvqPy4EzN3mrMSI9lVXMn+Q1VWR1HqhBan5bMkLZ87z45ncHSw1XGUzQkLbjtXr98IlBpj+gPPA0/bzk2i+Y37x9XrL9uu1wDcY4wZCJwB3NbimnOAb4wx8TQv0PlJga/+a1V2Mb1Du9A3rIvVUdRxPHRhEhGBvtwzT6eWKMdjjGkAbge+BLYD84wxmSLyqIhcbBs2GcgSkWwgCnjcdvxyYCLwcxHZYvszrHNfQcf68RPEldoeUDm4oiM1PLRoK8N6deNXk+KsjqNasOcOtz2r12cAb9sezwemSvM2RjOAD40xtcaYPUAOMNoYU2CM2QRgjKmg+Q0+uo1rvQ3MPLWX5vpqGxr5btchJiVE6K5RDi7Y35snLx3CzqKjvPD1TqvjKPUTxpilxpgEY0ycMeZx27GHjTGLbY/nG2PibWNuMsbU2o6/a4zxNsYMa/Fni5Wvpb31DQ8gNjxA53Erh2aM4cFFW6mpb+TZy4fipW2CHYo9fxv2rF7/zxjbnZJyIMyec23TT4YD622HoowxBbZrFQA6V+IYUveWUlXXyCTtTuIUzkqM5IqUXvxj1S427y+1Oo5S6iRMToxg3a5DVNfpJ1TKMX2WUcBX2wq5e1oCcRGBVsdRrdhTcNuzev1YY457rogEAp8AdxpjjtiR5b/f0ElXvLenVdnF+Hh6MDYu7MSDlUN44MKBRAX58buP06ip1x/cSjmLyYmR1DY0sX7PIaujKPUTh47W8vC/MxkaE8yN42OtjqPaYE/BfcLV6y3HiIgXEAwcPt65IuJNc7H9njFmQYsxhbb2Uj+2mWrzMzxnXfHenlZlFTMqNoQAbWbvNIL8vHn60mR2FVfy/LJsq+Mopew0JjYUHy8PVu8ssTqKUj/xyJJtVNTU88xsnUriqOz5Wznh6nXb19fbHs8GlhtjjO34lbYuJrFAPPCDbX7368B2Y8xzx7nW9cC/T/ZFuYOC8mqyCit0OokTmpgQwVWje/Pa6t1s3KdTS5RyBn7enoyJDeXbbPf8RFU5ri8zD7IkLZ87psST2L2r1XHUMZyw4LZz9frrQJiI5AB3Y+ssYozJBOYB24AvgNuMMY3AOOBnwJQWq9rPt13rKWCaiOwEptm+Vq38+KY/KUGnuDujBy4YSI9gf+77JF27lijlJCbGR7Cz6Cj5ZdVWR1EKgPKqeh5ctJWkHkHcOlm7kjgyu+YiGGOWAktbHXu4xeMa4LJjnPs4/20f9eOxNbQ9vxtjzCFgqj253NnKrGK6B/mREKULI5xRoK8Xj18ymJ+/uYGXludw9zmJVkdSSp3AhIRwWAprdpZw+aheJz5BqQ722GfbOFxZx5s/H4W3TiVxaPq344TqG5tYs7OEyYnaDtCZTU6MZNbwaF6D6PkhAAAgAElEQVReuYvtBSe1ZlgpZYHEqK5EBfmyaqdOK1HWW5FVxPyNedw6KU43uHECWnA7oS25ZVTUNuj8bRfw0IVJBPt7c98n6TQ0NlkdRyl1HCLChPgI1uwsobGpdbMupTpPRU099y/IID4ykDum9rc6jrKDFtxOaFVWMZ4ewpn9w62Ook5TSIAPj1w8iPS8ct5cu9fqOEqpE5gQH055dT0ZB8qtjqLc2JOf76DwSA3PzE7G18vT6jjKDlpwO6GV2UWM6N2NYH9vq6OodnBhcg/OHhjJs8uy2Heo0uo4SqnjmBAfgQjarURZ5rucEt5fv5+bJvRjeO8Qq+MoO2nB7WSKK2rZeuAIkxO1O4mrEBEemzkYbw8P5i7IoLmjplLKEYUG+DC4ZzCrdR63skBVXQP3LUgnNjyAu6clWB1HnQQtuJ3Mj2/yOn/btfQI9mfO+QP4btch5qXmWh1HKXUcExPC2bS/jCM19VZHUW7mr1/vJPdwNU/NGoKft04lcSZacDuZVdnFhAf6kNQjyOooqp1dNao3Y2JD+dNn2yk8UmN1HKXUMUyIj6CxyfBdjm7zrjpPZn45/1yzh6tG92JMvzCr46iTpAW3E2lsMnybXczE+Ag8PLQdoKvx8BCeujSZuoYmHlq0VaeWKOWgRvQOIcDHU6eVqE7T2GSYuyCDkC4+zJk+0Oo46hRowe1EMg6UU1pVz6REnU7iqmLDA7hrWgJfbSvk860HrY6jlGqDj5cHY+PC+XZnsf5irDrF29/tJT2vnD9clERwF22Y4Iy04HYiq7KKEWn+OFO5rpvGxzI4OoiH/51JWVWd1XGUUm2YmBBO7uFq9h2qsjqKcnEHyqr5y1dZnJUYwYXJPayOo06RFtxOZFV2Eckx3QgN8LE6iupAXp4ePH1pMqVVdTyxdLvVcZRSbZhou/HxrU4rUR3IGGObYgiPzRysu0s7MS24nURZVR1bcsu0O4mbGNQzmJsmxDIvNY91u3RhllKOpk9YF3qF+rN6Z4nVUZQLW5pxkOU7irjnnARiQrpYHUedBi24ncTqnSU0GW0H6E7unJpAr1B/HliYQU19o9VxlFItiAjj+0ewbtch6hubrI6jXFB5dT2PLMlkSHQwPz+zr9Vx1GnSgttJrMouJtjfm2G9ulkdRXUSfx9PHp85hN0llby8cpfVcZRSrUyMD+dobQNpuWVWR1Eu6OkvdnDoaC1PzhqCl6eWa85O/wadgDGGVdnFTIgPx1PbAbqViQkRzBjWk1dW5pBTVGF1HKVUC2fGheMh8K1OK1HtbMPew7y/fj83jo9lcHSw1XFUO9CC2wlsL6iguKJWp5O4qYcuTKKLjxdzF2TQ1KQtyJRyFMFdvEmO6cYaXTip2lFtQyNzF2QQ3c2fu3T7dpehBbcTWJWt27m7s/BAXx44fyAb9pbykW77rpRDmRAfzpbcMsqrdZt31T7+vnI3OUVH+dMlg+ni42V1HNVOtOB2AiuzihjYI4jIID+royiLXJYSw5jYUJ5cup2iCt32XSlHMSE+giaDdhNS7SKn6Cgvrcjh4qE9OSsx0uo4qh1pwe3gKmrq2bivVO9uuzkR4YlZQ6ipb+LRJdusjqOUshneu5tu867aRVOT4f4FGfj7ePLQhUlWx1HtTAtuB/fdrkM0NBkm63bubi8uIpDbzurPp+kFrMgqsjqOUgrw9vRgbFwYa3J04aQ6PfNSc/lh72HuP38AEV19rY6j2pkW3A5uVXYxgb5ejOgdYnUU5QB+NbkfcREBPLhwK1V1DVbHUUoB4/uHs+9QFft1m3d1iooqanhi6XbGxIZyeUovq+OoDqAFtwMzxrAqq5gz48Lw8dK/KgW+Xp48OSuZA2XVPL8s2+o4Silggm3K3+ocnVaiTs1jn26npr6JJ2YN0e3bXZRWcQ5sV/FRDpRVM0mnk6gWRseGctXoXryxdi9bD5RbHUcpt9cvPICewX6sztZpJerkrdhRxJK0fG6f0p+4iECr46gOogW3A1uZpe0AVdvmTB9ISBcf5i7IoFF7cytlKRFhQnwE3+0qoUG3eVcnobK2gQcXbSU+MpBfTYqzOo7qQHYV3CIyXUSyRCRHROa08byviHxke369iPRt8dxc2/EsETm3xfE3RKRIRLa2utYjInJARLbY/px/6i/Pua3KLqZ/ZCAxIV2sjqIcTHAXb/5wURIZB8p567u9VsdRLsCO9/k+IvKNiKSLyEoRiWnx3PUistP25/rOTe4YxseHc6SmgXT91EmdhOeXZXOgrJonZw3RqaMu7oR/uyLiCbwEnAckAVeJSOt+NTcCpcaY/sDzwNO2c5OAK4FBwHTgZdv1AN6yHWvL88aYYbY/S0/uJbmG6rpG1u85rHe31TFdmNyDyYkRPPtVFgfKqq2Oo5yYne/zfwH+ZYxJBh4FnrSdGwr8ARgDjAb+ICJut8p7XP9wRGCNbvOu7JSRV84ba/dw9ZjepPQNtTqO6mD2/Do1Gsgxxuw2xtQBHwIzWo2ZAbxtezwfmCrNs/5nAB8aY2qNMXuAHNv1MMZ8Cxxuh9fgkr7ffYi6hiYtuNUxiQiPzRiMMfDwoq0Yo1NL1Cmz530+CfjG9nhFi+fPBZYZYw4bY0qBZRz7ZorLCg3wYXDPYO3HrezS0NjEnAXphAX6ct/0AVbHUZ3AnoI7Gmi5n3Se7VibY4wxDUA5EGbnuW253fax5RvueKcEmqeT+Hl7MDpWf+tVx9YrtAt3T0vgmx1FfL71oNVxlPOy5706DbjU9vgSoKuInM77vMuZEB/O5v1lVNToNu/q+N5cu5fM/CP88eJBBPt7Wx1HdQJ7Cu62+tO0vpV2rDH2nNvaK0AcMAwoAJ5tM5TIzSKSKiKpxcWud0dhVXYxY/uF4efteeLByq3dMK4vg3oG8cjiTMqr9Qe9OiX2vFf/DpgkIpuBScABoMHOc13+PRua53E3NBm+360f3qpjyz1cxXPLsjl7YCTnDe5udRzVSewpuPOAll3YY4D8Y40RES8gmObpIvac+z+MMYXGmEZjTBPwGrYpKG2Me9UYk2KMSYmIcK1pF/sOVbKnpFKnkyi7eHl68OSsIZQcreWZL3ZYHUc5pxO+Vxtj8o0xs4wxw4EHbMfK7TnXNtZl37N/NLJPCP7enqzRaSXqGIwxPLhoKx4Cj84YrD233Yg9BfcGIF5EYkXEh+ZFkItbjVkM/LgyfTaw3DRPKF0MXGnrYhILxAM/HO+biUiPFl9eAmw91lhXtSrb1g4wMdLiJMpZJMd044Zxsby3fj+pe/XumjppJ3yfF5FwEfnxZ8Zc4A3b4y+Bc0QkxDYF8BzbMbfj6+XJmH6hrNaFk+oYlqQXsCq7mHvOSaRnN3+r46hOdMKC2zYn+3aa30C3A/OMMZki8qiIXGwb9joQJiI5wN3AHNu5mcA8YBvwBXCbMaYRQEQ+ANYBiSKSJyI32q71jIhkiEg6cBZwVzu9VqexKquY3qFd6Bum7QCV/e6elkB0N3/mLsigrkF7ASv72fk+PxnIEpFsIAp43HbuYeAxmov2DcCjtmNuaUJ8BLtLKskr1W3e1f8qq6rj0SWZJMcEc/2Zfa2OozqZlz2DbK35lrY69nCLxzXAZcc493Fsb8ytjl91jPE/syeTq6ptaOS7XYeYPTJGP2pSJyXA14s/zRzMDW9t4O+rdvGbqfFWR1JOxI73+fk0d6Fq69w3+O8db7c2IT4caG4PeOXo3hanUY7kyaU7KK2q5+1fjMbTQ3++uxvtsu5gUveWUl3fyGTdzl2dgrMGRHJhcg9eXJ7DruKjVsdRyu3ERwYSFeTL6hydVqL+a92uQ3yUmstN42MZ1DPY6jjKAlpwO5iVWUX4eHpwRr8wq6MoJ/XwRUn4eXswd0EGTbrtu1KdSkQY3z+CtTklNOr//xRQU9/IAwsz6BXqz51nJ1gdR1lEC24Hsyq7mFGxIQT42jXbR6mfiOzqx/3nD+SHPYf5eGPuiU9QSrWriQnhlFXVk5mv27wreHlFDrtLKnl85hD8fbTVr7vSgtuB5JdVk114VNsBqtN2eUovRseG8vhn2ymuqLU6jlJuZVz/5nnc2q1EZRdW8MqqXVwyPJqJ+rPdrWnB7UC+/bEdYIK2A1Snx8NDeOKSIdTUN/Hop9usjqOUWwkP9CWpR5Bu8+7mmpoMcxdkEOjrxYMXDLQ6jrKYFtwOZGVWMd2D/EiICrQ6inIB/SMDue2s/ixJy2fFjiKr4yjlVibEh7NxXymVtQ1WR1EWee+H/WzcV8qDFyQRFuhrdRxlMS24HUR9YxNrcko4a0CEtgNU7eZXk/vRPzKQBxdt1R/8SnWiCfER1Dcaftjjti3J3drB8hqe+XwH4/qHMWtEtNVxlAPQgttBpO4t5Whtg04nUe3K18uTJ2cN4UBZNc8vy7Y6jlJuI6VvCL5eHnyr00rc0iOLM6lrbOLxmUP0JpoCtOB2GCuzi/DyEMb113aAqn2N6hvK1WN688baPWTkadcEpTqDn7cno2NDWaMLJ93Ol5kH+SLzIHeenUDf8ACr4ygHoQW3g1iVVcyovqF09fO2OopyQfdNH0B4oC9zFqTT0KjbvivVGSbEh7Oz6CgF5dVWR1GdpKKmnj/8O5MB3bty04RYq+MoB6IFtwMoKK9mx8EK3V1SdZhgf2/+ePEgMvOP8ObavVbHUcotTIhvfk/Xu9zu489fZlFYUcNTlybj7akllvov/dfgAFZmNc/xm5yo87dVx5k+uDtnD4ziuWXZ5B6usjqOUi5vQPeuhAf6aj9uN7FxXynvfL+P68f2ZVivblbHUQ5GC24HsDKriJ7B2g5QdSwR4dEZg/AQeHDRVozRbaeV6kgiwoT4cNbmlNCk27y7tLqGJu5fkEGPID9+d26i1XGUA9KC22J1DU2szTnEpMRIXcmsOlzPbv78/txEVmUXszgt3+o4Srm88f3DOVRZx7aCI1ZHUR3otdW7ySqs4NEZgwn09bI6jnJAWnBbbOO+5naAOn9bdZafje3L0F7deHTJNkor66yOo5RLmxDfvM37mhydVuKq9pRU8tdvdnLBkB6cnRRldRzloLTgttjKrCK8PYVx/cOtjqLchKeH8NSsIZRX1/PE0u1Wx1HKpUUG+ZEY1VW3eXdRxhjuX5CBr5cHf7goyeo4yoFpwW2xlbZ2gPoRlOpMA3sE8cuJ/fh4Yx7f6Z03pTrUhPhwNuwtpbqu0eooqp19uCGXdbsPMfe8gUQG+VkdRzkwLbgtlF9WTVahtgNU1vjt1Hj6hHVh7sIMLQSU6kDj48Opa2jih726zbsrOVhewxOfbWdsvzCuGt3L6jjKwWnBbaFV2c0fMZ6l7QCVBfy8PXlqVjL7DlXx7FdZVsdRymWNiQ3Dx9ODNTqtxGUYY3hwUQb1TU08dalu365OTAtuC63YUUR0N3/6R2o7QGWNsXFhXHtGb15fu4dN+0utjqOUS/L38WRUbIj243Yhi9Py+Xp7Eb87J5E+Ybp9uzoxLbgt0twOsIRJiRH6m7Gy1H3TB9AjyI9756dT26BTS5TqCOP7R7DjYAVFR2qsjqJO06GjtfxxyTaG9erGDeN0+3ZlHy24LZK67zCVdY06nURZrqufN0/MGkJO0VH+9k2O1XGUcknaHtB1/HHJNipq6nlmdjKeHnrDTNlHC26LrMwqxsfTgzPjwqyOohSTEyOZPTKGV1btYuuBcqvjKOVyknoEERbgwxqdVuLUvt5WyOK0fG4/K56EqK5Wx1FORAtui3yzvZDRsaEEaDtA5SAeuiCJ0AAf7p2fTn1jk9VxlHIpHh7N+y2szinBGN3m3RmVV9fzwKIMBnTvyq2T46yOo5yMXQW3iEwXkSwRyRGROW087ysiH9meXy8ifVs8N9d2PEtEzm1x/A0RKRKRra2uFSoiy0Rkp+2/Iaf+8hzTnpJKdhVXcvZAnU6iHEdwF2/+NHMw2wqO8I9Vu6yOo5TLGR8fTnFFLVmFFVZHUafgyaXbKa6o5ZnZyfh46f1KdXJO+C9GRDyBl4DzgCTgKhFpvZ3SjUCpMaY/8DzwtO3cJOBKYBAwHXjZdj2At2zHWpsDfGOMiQe+sX3tUr7ZXgjA1IG6BaxyLOcO6s6FyT34v29yyNaiQKl29eM87tXZOq3E2azNKeHDDbn8cmI/kmO6WR1HOSF7fkUbDeQYY3YbY+qAD4EZrcbMAN62PZ4PTJXm1hszgA+NMbXGmD1Aju16GGO+BdraBaDltd4GZp7E63EKy7YVMqB7V3qFdrE6ilI/8ceLBxHo58W989NpbNKPvpVqLz2Cm9vArtaFk06lqq6BOQvSiQ0P4K6zE6yOo5yUPQV3NJDb4us827E2xxhjGoByIMzOc1uLMsYU2K5VALjUvIvyqnpS95UyVaeTKAcVFujLIxcPYktuGW+u3WN1HKVcyoT4cNbvPkRNvbbgdBZPfb6DvNJqnpo1BD9vzxOfoFQb7Cm42+p50/q217HG2HPuKRGRm0UkVURSi4udZ/euldlFNDYZztbpJMqBXZTcg7MHRvHnL7PYU1JpdRylXMaE+HBqG5rYuE83mnIGa3NK+Ne6fdxwZixj+mlXMXXq7Cm484BeLb6OAfKPNUZEvIBgmqeL2HNua4Ui0sN2rR5AUVuDjDGvGmNSjDEpERERdrwMx7BsWyHhgb4M1TlgyoGJCI9fMhhfLw9+/3GaTi1Rqp2MiQ3D21P4Vrd5d3gVNfXcOz+dfuEB3Ds90eo4ysnZU3BvAOJFJFZEfGheBLm41ZjFwPW2x7OB5aa579Fi4EpbF5NYIB744QTfr+W1rgf+bUdGp1DX0MSq7GKmDIjAQ5vlKwcXFeTHH2cMInVfKf9cvdvqOEq5hABfL0b0DtF+3E7gT59up6C8mr9cPlSnkqjTdsKC2zYn+3bgS2A7MM8Ykykij4rIxbZhrwNhIpID3I2ts4gxJhOYB2wDvgBuM8Y0AojIB8A6IFFE8kTkRtu1ngKmichOYJrta5ewYe9hKmoadDqJchozh0UzfVB3nv0qm6yD2rXEldnR/rW3iKwQkc0iki4i59uOe4vI2yKSISLbRWRu56d3LhMTIsjMP0LJ0Vqro6hjWLGjiI9Sc7llUhwjertcd2JlAbsaSRpjlhpjEowxccaYx23HHjbGLLY9rjHGXGaM6W+MGW2M2d3i3Mdt5yUaYz5vcfwqY0wPY4y3MSbGGPO67fghY8xUY0y87b9tdTJxSl9vL8THy4PxttZQSjm6H6eWdPXz4u55W6hr0A1xXJGd7V8fpPmGy3CaP+l82Xb8MsDXGDMEGAnc0nIvBvVT4/s3/wxYq91KHFJZVR33fZJOYlRX7jw73uo4ykVo5/ZOYozh6+2FjO8fThcf3V1SOY+wQF+emDWEzPwjvLh8p9VxVMewp/2rAYJsj4P573ocAwTY1u/4A3XAkY6P7LwGRwcT0sWblVk6j9sRPbI4k8OVdTx7+VB8vXQqiWofWnB3kuzCo+QertZ2gMopnTuoO7NGRPPSyl2k5ZZZHUe1P3tauD4CXCsiecBS4A7b8flAJVAA7Af+4kqfTHYETw/hrMRIVmYV6YJkB/PF1oMs2pLPbWf1Z3B0sNVxlAvRgruTfJl5EEDnbyun9YeLBhHZ1Ze7523RHsKux54WrlcBbxljYoDzgXdExIPmu+ONQE8gFrhHRPr95Bs4aSvXjjJlYCSlVfVs3q/tAR3FoaO1PLAwg0E9g7h9Sn+r4ygXowV3J/l860FG9gkhKsjP6ihKnZJgf2/+PHsou4or+fOXWVbHUe3LnhauN9K8CB5jzDrADwgHrga+MMbUG2OKgLVASutv4KytXDvKhPgIvDyEb3a02flWdTJjDA8s3EpFTQPPXj4Ub08tj1T70n9RnWDfoUq2FxzhvMHdrY6i1GkZHx/OdWP78MbaPXy/+5DVcVT7saf9635gKoCIDKS54C62HZ8izQKAM4AdnZbcSQX7ezOqbyjLt2vB7Qg+Ts3ji8yD3HNOAgO6B534BKVOkhbcneCLrc3TSc4dpAW3cn5zzhtAn9Au3DMvjSM19VbHUe3Azvav9wC/FJE04APg57b9Fl4CAoGtNBfubxpj0jv9RTihqQMjySqsIPdwldVR3NqekkoeWZLJ2H5h/HLCT2ZDKdUutODuBF9kHmRwdBC9QrtYHUWp09bFx4vnrhjGwSM1PLxoq9VxVDuxo/3rNmPMOGPMUGPMMGPMV7bjR21tYQcZY5KMMX+28nU4k6m2NT3LdVqJZeobm7jzoy14eQjPXj5UN6VTHUYL7g5WUF7N5v1lnDe4h9VRlGo3I3qH8Nup8Szaks/CzXlWx1HKKcWGB9AvPEDncVvob9/sJC23jCdnJdOzm7/VcZQL04K7g32VWQjodBLlem47qz+j+4by0KJM9h/Sj8SVOhVTB0by/a5DVNY2WB3F7aTuPcyLK3K4dEQMFyTrTTHVsbTg7mCfby0gPjKQ/pGBVkdRql15egjPXzkMEfjNh5upb9RdKJU6WVMGRFHX2MTqnbrrZGeqqKnnzo+2EB3izyMXt95UVan2pwV3Byo5WssPew4zXbuTKBcV3c2fJy4ZwpbcMv7vG92FUqmTldI3hK5+XizfUWh1FLfyh8WZ5JdV88IVw+jq5211HOUGtODuQJ9nFNBk0I+qlEu7aGhPZo+M4aUVOazXVoFKnRRvTw8mJUSwfEcxTbrrZKdYnJbPgk0HuGNKPCP7hFodR7kJLbg70OK0fBKiArWnp3J5j1w8iF6hXbjroy2UV2mrQKVOxtkDoyg5Wsvm3DKro7i8vSWV3L8gg5F9QrhDd5NUnUgL7g6SX1bNhr2lXJTc0+ooSnW4QF8v/nrlcIoqapm7MJ3m9sxKKXucNSASb0/hq8yDVkdxabUNjdz2/ia8PIW/XTUcL91NUnUi/dfWQT5Nb94V+aKhWnAr9zCsVzfuOSeRpRkH+de6fVbHUcppBPt7MzYunC8yD+ovqx3oic+2k5l/hL/MHqotAFWn04K7gyxJKyA5Jpi+4QFWR1Gq09wysR9TBkTyp8+2kaYfjytlt+mDurPvUBU7DlZYHcUlfbG1gLfX7eOm8bGcnRRldRzlhrTg7gB7SirJOFDOxXp3W7kZDw/h2cuGEhHoy23vb9L53ErZaVpSFCLwpU4raXe5h6v4/fx0hsYEc+/0AVbHUW5KC+4OsHhLPiJwoc7fVm4oJMCHF68ZwcHyGn43P00/IlfKDhFdfRnVJ5QvtmrB3Z7qGpq4/YPNALx49Qh8vLTsUdbQf3ntzBjD4rQDjOobSvdgP6vjKGWJEb1DmHPeAJZtK+T1NXusjqOUUzh3cHd2HKxgb0ml1VFcxhNLt5OWW8YzlybTK7SL1XGUG9OCu52l55Wzq7iSmcOirY6ilKVuHB/LOUlRPPX5DjbuK7U6jlIO79xBzXOLdVpJ+1i4OY+3vtvLL8bFct4Q3Q9DWUsL7nY2LzUXP28PLhyq/+dW7k1E+PNlQ+nRzY/b3ttEcUWt1ZGUcmgxIV0YEh3MF1pwn7Zt+UeYuyCD0bGhzD1f520r62nB3Y5q6htZnJbP9EHdCdKtYpUi2N+bv187krLqOn793kbqGpqsjqSUQ5s+uDub95dxoKza6ihOq6yqjlveTSXY35uXrh6Bt/bbVg5A/xW2oy8zD1JR08BlKb2sjqKUwxjUM5hnZg9lw95SHvt0m9VxlHJoFyY3fzr6aVq+xUmcU2OT4bcfbuFgeQ2vXDuSiK6+VkdSCtCCu13N35hHdDd/xvYLszqKUg7l4qE9uXliP975fh8fbdhvdRylHFafsACG9urGYi24T8lfv85mVXYxf7hoECN6h1gdR6n/sKvgFpHpIpIlIjkiMqeN531F5CPb8+tFpG+L5+bajmeJyLknuqaIvCUie0Rki+3PsNN7iZ3jQFk1a3JKmD0yBg8PsTqOUg7n3nMTmRAfzkOLMtm0XxdRKnUsFw/tSWb+EXYVH7U6ilP5KvMg/7c8h8tGxnDNmN5Wx1Hqf5yw4BYRT+Al4DwgCbhKRJJaDbsRKDXG9AeeB562nZsEXAkMAqYDL4uIpx3X/L0xZpjtz5bTeoWdZMHGPIyB2SNjrI6ilEPy8vTgb1cNJyrYl1vf3UhRRY3VkZRySBcm90CkeU8HZZ9t+Ue486MtJMcE89jMwYjojS/lWOy5wz0ayDHG7DbG1AEfAjNajZkBvG17PB+YKs3/2mcAHxpjao0xe4Ac2/XsuabTaGwyzNuYy9h+YdrnU6nj6NbFh1d/lsKR6gZueWcjNfWNVkdSyuFEBflxRmwYS9LzdeMoOxRV1HDT2xsI8vPmtetS8PP2tDqSUj9hT8EdDeS2+DrPdqzNMcaYBqAcCDvOuSe65uMiki4iz4uIw694WJVdRO7haq7Wj7CUOqGBPYJ47vKhbN5fxu8+TqOpSQsKpVq7eFhPdhdXkpl/xOooDq2mvpGb/7WRw1V1/PP6FKKCdMM55ZjsKbjb+lym9U/IY4052eMAc4EBwCggFLivzVAiN4tIqoikFhcXtzWk0/xr3T4iu/py7qDuluZQylmcN6QH900fwKfpBTy3LNvqOEo5nPMGd8fbU1iiiyePyRjDvfPT2ZJbxgtXDGNwdLDVkZQ6JnsK7jygZZ+7GKD1O8B/xoiIFxAMHD7Ouce8pjGmwDSrBd6kefrJTxhjXjXGpBhjUiIiIux4GR1j36FKVmUXc9Xo3vh4adMXpez1q0n9uCKlFy+uyOHj1NwTn6CUG+nWxYeJ8REsTsunUT8FatPfluewOC2f35+byPTButmccmz2VIgbgHgRiRURH5oXQS5uNWYxcL3t8WxguWmeeLYYuNLWxSQWiAd+ON41RaSH7b8CzAS2ns4L7Gjvfr8PTxGdTqLUSRIR/nTJYMb1D+P+hRms23XI6khKOZRLR8ZQUF7DmpwSq6M4nI9Tc3luWTaXDI/m15PjrHCL7msAABW6SURBVI6j1AmdsOC2zcm+HfgS2A7MM8ZkisijInKxbdjrQJiI5AB3A3Ns52YC84BtwBfAbcaYxmNd03at90QkA8gAwoE/tc9LbX9VdQ3MS83j3EHddd6YUqfA29ODl68ZSZ+wAG55J5XswgqrIynlMM4eGEVowP+3d+fhVVX3Gse/PzIxJZCQMMgURmXSMIRZRbSKtBWsWnAAUSpVsLfW9rb63Pt40au39bYOHRxAARVRcKri0AooCleBEIEwzyKEKWEKc8Z1/zgbTWMSQsg5+yR5P8+TJ+fss89eb1ZOfiz2sHY0byzXEaDiFm7K4oF31jC4YyKP33CxZiSRaiGyIis55z4CPiqx7KFij08DN5Xx3seAxyqyTW/50IpkCgdzlu8i51Q+dw5O9juKSLXVqF4UM8alcsNzXzJ2Whpv3TOAVvGa7UckOrIOI1NaMnPpDg6dyCOhQbTfkXyXsesIE19dwUXNY3l+TG+dyinVhj6plZRfWMSLi78mNTme3m0T/I4jUq21TqjPK+P7cjKvgLHT0jh4PNfvSCJhYVRqa/ILHe+u3O13FN/tOHCCO19aTmJsNDPuSKVhTIX2GYqEBQ24K+mD1XvYfeQUd1+uc8dEqsJFzeOYPi6VPTmnGDdjOcdzC/yOJOK7C5vHckmrRryRvqtWz8m9/+hpxk5PwwEv39GXprE6jVOqFw24K8E5x5TPt9OpaUOuuLCp33FEaow+yQk8e2sv1u89yoRX0nVjHBHgpj6t2bjvGGt25/gdxRcHjudyywtLOXg8l+njUmmf1NDvSCLnTAPuSpi3fj8b9x3j55d3oE4dXawhUpWGXtSMP910MV9uO8ikWSvILdCgW2q361IuICayDrNr4cWTh0/kcduLy9h95BTTx6WS0rqx35FEKkUD7nNUWOR4ct5m2ic2YGTKBX7HEamRru/ZikdHdueTjVlMmrWCvIIivyPVeGY2zMw2mdlWM3uglNfbmNlCM1vp3Ql4eLHXLjazJWa2zszWmJmO91ehuLpR/OjiC3h35W6Ons73O07I5JzKZ+z0NLYfOMGLY1Pp176J35FEKk0D7nP0fsYeNu0/xq9+0JnICHWfSLDc1r8t/z2yOws2ZDHpNQ26g8nMIoBngGuBrsDNZta1xGr/SWAK154E7p3wrPfeSOBV4G7nXDdgCFB7RoUhMm5gMifzCnkzPdPvKCFxPLeAO2aksXHfUZ6/rReDOyX6HUnkvGjEeA7yC4t4cv5murSI44c9dFcrkWAb078tj4zoxvz1+7n3tRXkF2rQHSR9ga3Oue3OuTxgNjCixDoOiPMeN+K7Ow5fDax2zmUAOOcOOud0HlAV69GqEb3bxvPKkh0U1fA7T+acymfMtGVkZObw15t7MvSiZn5HEjlvGnCfg1lLv2HnoZP85urOOndbJETGDkhm8o+7Mm/9fibOWqELKYOjJVD8BOFMb1lxk4HbzCyTwD0UfuEt7ww4M/vYzFaY2W+DHba2GjcwmW8OnuSzzVl+RwmaQyfyuOWFpazdncMzt/TULdulxtCAu4Kyjp3miXmbubRTIkMv0swkIqE0blC7b/d036EpA4OhtD0IJXej3gy85JxrBQwHZppZHQI3UBsM3Op9v97MrvxeA2YTzCzdzNKzs7OrNn0tMax7c5rFxTDjix1+RwmKrKOnGTVlCVuzjjN1bB8NtqVG0YC7gv7w0UZyC4p4+Lpuuo2siA/GDkjm6VEppO049O0UYVJlMoHWxZ634rtTRs4YD7wB4JxbAtQFEr33fu6cO+CcO0lg73evkg0456Y65/o45/okJSUF4Ueo+aIi6jB2QDKLtxxgTWbNmiLwm4Mn+OmUJew+cooZd6Rqyl2pcTTgroCl2w/yzsrdTLisveb/FPHRyJ4tmTqmN5v2HeOmKUvIPHzS70g1xXKgk5m1M7NoAhdFzi2xzk7gSgAz60JgwJ0NfAxcbGb1vQsoLwfWhyx5LTNmQFti60byzMKtfkepMqt2HeEnz35Jzql8Zo7vx8AOukBSah4NuM/ieG4B//5WBq0T6jHpio5+xxGp9a7s0oyZ4/uRfSyXkc98ycqdh/2OVO055wqAewkMnjcQmI1knZk9YmbXeav9GrjLzDKA14FxLuAw8CSBQfsqYIVz7sPQ/xS1Q1zdKG4fkMw/1+1jy/5jfsc5b/PX72f01CU0iInk7XsG0rttvN+RRIJCA+6zeOT9dew+fIqnfppCvegIv+OICNC3XQJ/nziQ+tERjJ66lA9X7/U7UrXnnPvIOdfZOdfBOfeYt+wh59xc7/F659wg59wlzrkU59y8Yu991TnXzTnX3TmniyaD7M7B7agXFcGzn23zO0qlOeeY8cXX/HxmOhc2i+WdiQN1BFlqNA24yzE7bSdvpGdyz5AO9ElO8DuOiBTTsWksf584kB4tGzHptRX89ZMtNX66NBGAhAbR3NqvDXMz9rA167jfcc7Z6fxCfvPmah5+fz1XdmnG6xP6k9gwxu9YIkGlAXcZlu84xEPvrePSTonc/4ML/Y4jIqVo0jCGWXf14/qeLXli/mYmzEwn56TuuSI13z1DOlAvKoLH/7nR7yjnZG/OKUZNWcLbKzK576pOTLmtN/WjI/2OJRJ0GnCXYt2eHO58aTmt4uvxl9E9idCc2yJhKyYygid/egmTf9yVzzdn86O/LWbt7po1g4NISU0axnDPkA7MX7+ftK8P+R2nQhZvyebHf/2CbdknmDqmN/ddpXtaSO2hAXcJy7Yf5OapS4mNiWTmz/oR3yDa70gichZmxrhB7Zjz8wEUFDp+8tyXvLJkB87pFBOpue4c1I7mcXV57KMNYf1Zzyso4n8+2sCYaWnE14/i3UkDubpbc79jiYSUBtyeoiLHi4u3M2ZaGkmxMcz5+QBaNq7ndywROQe92sTzwS8GM6B9Ex56bx1jp6exN+eU37FEgqJedAS/vrozGbuO8GZ6pt9xSrU9+zg/ee4Lpi7azm392/D+LwbTsWms37FEQq7WD7hP5xfyjzV7ue6Z/+PRDzdwWeck3r5nIK0T6vsdTUQqoUnDGF66I5VHR3YnfcdhrnlqEe+u3B3WewBFKuuGXq3om5zAox+uJ+voab/jfCu/sIhnFm7l2j8vJvPwKaaM6c2jI3tQN0qzfUntVCuvVCgqcox/eTn7j+ay/cBxTucX0bZJfZ4elcKIlAt0J0mRas7MuK1/WwZ3TOT+N1Zx35xVvL0ik8nXdaODph6TGqROHeMPN/Rg2J8X89B763h+TG+/I5Gx6wi/e3s1G/cdY1i35jw8ohvN4ur6HUvEV7VywF2njpFbUESLRnXp1z6ByzsnMbhjIpERtX6Hv0iNkpzYgDfvHsirS7/hT/M2MezpRdx1aXvuHdpRMyNIjdE+qSG/uqozj/9zI++t2s2IlJa+5Mg6epqnFmxmzvJdJMXGMGVMb67RudoiQC0dcAO8dld/vyOISAhE1DFuH5jM8B4t+P1HG3j2s228+VUm917RkdF9WxMTqUPcUv3ddWk7PtmwnwffWUO3C+JCep70idwCXli8namLtpNXUMTYAcncf3Vn4upGhSyDSLjTLl0RqRWSYmN4clQKb909gHZNGvBfc9cx9E+fM2f5TvIKivyOJ3JeIiPq8LdbelEvKoIJr3zFoRN5QW/z2Ol8nvtsG5f/cSFPL9jCkAuTWHD/5Uy+rpsG2yIlWE24kKhPnz4uPT3d7xgiUk0451i85QBPzNtERmYOSbExjO3fllv7tyUhxFOBmtlXzrk+IW3UZ6rZwbN8xyFufXEZXVvEMetn/WgQU/UHsncePMlraTuZtewbjp0u4NJOidx3VWd6t42v8rZEwlFl6naF9nCb2TAz22RmW83sgVJejzGzOd7ry8wsudhrD3rLN5nZNWfbppm187axxdumJsIWkSplZlzWOYl3Jw3ipTtS6dIijifmb6b/7z9h4qyvWLB+P/mF2ust1U9qcgJ/Gd2TNbtzuOWFpRw8nlsl2z2RW8DcjD2MmbaMy/64kKmLtjG4YyLv3zuYmeP7abAtchZn3cNtZhHAZuAHQCawHLjZObe+2DoTgYudc3eb2WjgeufcKDPrCrwO9AUuABYAnb23lbpNM3sDeMc5N9vMngcynHPPlZdRe0tE5Hxt2X+MWct28n7GHg6eyKNx/SiGdE7iiouaclmnpKDdBEt7uCUYFqzfz6TXVtCkQTRPjUqhX/sm57yNXYdOsmTbQRZs2M/nm7O/nWxgVGprRqW2pkUj3atCaqfK1O2KDLgHAJOdc9d4zx8EcM79vtg6H3vrLDGzSGAfkAQ8UHzdM+t5b/veNoE/ANlAc+dcQcm2y6LiLSJVJb+wiEWbs/lw9V4+25z97bmw7ZMa0LN1PN1bxtEusQHtExvSrFHMeV90qQG3BEvGriP8cvZKdhw8ybXdm3P7wGT6tI3/3oxcx3ML2HvkFLsOn2TD3mNs2HuUjMwj7DoUuGlUs7gYru3eguE9WtC7bTwRuh271HKVqdsVObmrJbCr2PNMoF9Z63gD5Rygibd8aYn3npmvqLRtNgGOOOcKSllfRCTooiLqcGWXZlzZpRmFRY6MzCMs2XaQlTuP8NmmLN5e8a939KsfHUF8/WjqRUfw9KgUurds5FNykX91SevGfPhvlzLl821M/2IH/1i7j5jIOjSNiwHgVF4Rp/IKOJFX+C/vaxVfj24XxDF+UDsGdUykY9OGuj+FyHmqyIC7tL+ykrvFy1qnrOWlnTte3vrfD2U2AZgA0KZNm9JWERE5LxF1jF5t4unVJnB+qnOOgyfy+PrACb7OPkHWsdMcPpnP4ZN5nM4vpH60phiU8NIgJpL7r76QCZd3YNHmbFZ8c5js47lEmBETFUG9qAiaxcXQvFFdWjauR+fmsZphRCQIKjLgzgRaF3veCthTxjqZ3ikljYBDZ3lvacsPAI3NLNLby11aWwA456YCUyFweLICP4eIyHkxMxIbxpDYMIbU5AS/44hUWMOYSIb3CJwWIiKhV5FZSpYDnbzZQ6KB0cDcEuvMBW73Ht8IfOoCJ4fPBUZ7s5i0AzoBaWVt03vPQm8beNt8r/I/noiIiIiIv866h9s7J/te4GMgApjunFtnZo8A6c65ucA0YKaZbSWwZ3u099513qwj64ECYJJzrhCgtG16Tf4OmG1mjwIrvW2LiIiIiFRLuvGNiIiPNEuJiEj1ErQb34iIiIiISOVowC0iIiIiEkQacIuIiIiIBJEG3CIiIiIiQaQBt4iIiIhIENWIWUrMLBv4phJvTSRws51woTzlU56yhVMWUJ6zKZ6nrXMuyc8woaaaHTTKUz7lKZ/ylK1klnOu2zViwF1ZZpYeTtNxKU/5lKds4ZQFlOdswi1PdRFu/aY85VOe8ilP+cIpT1Vk0SklIiIiIiJBpAG3iIiIiEgQ1fYB91S/A5SgPOVTnrKFUxZQnrMJtzzVRbj1m/KUT3nKpzzlC6c8552lVp/DLSIiIiISbLV9D7eIiIiISFDVygG3mQ0zs01mttXMHvApww4zW2Nmq8ws3VuWYGbzzWyL9z0+iO1PN7MsM1tbbFmp7VvAX7z+Wm1mvUKUZ7KZ7fb6aJWZDS/22oNenk1mdk0Q8rQ2s4VmtsHM1pnZL73lvvRROXl86SMzq2tmaWaW4eV52FvezsyWef0zx8yiveUx3vOt3uvJIcrzkpl9Xax/UrzlofhMR5jZSjP7wHvuS9/UFH7Xbb9rttde2NRt1exK51HNLj+PbzXbayd4dds5V6u+gAhgG9AeiAYygK4+5NgBJJZY9r/AA97jB4DHg9j+ZUAvYO3Z2geGA/8ADOgPLAtRnsnAb0pZt6v3e4sB2nm/z4gqztMC6OU9jgU2e+360kfl5PGlj7yfs6H3OApY5v3cbwCjveXPA/d4jycCz3uPRwNzqrh/ysrzEnBjKeuH4jN9P/Aa8IH33Je+qQlfhEHdxuea7bURNnW7jCy+1COvDdXs8vOoZlcsV9Dqdm3cw90X2Oqc2+6cywNmAyN8znTGCOBl7/HLwMhgNeScWwQcqmD7I4BXXMBSoLGZtQhBnrKMAGY753Kdc18DWwn8Xqsyz17n3Arv8TFgA9ASn/qonDxlCWofeT/nce9plPflgKHAW97ykv1zpt/eAq40MwtBnrIE9fdlZq2AHwIves8Nn/qmhgjXuh2ymg3hVbdVsyudpyyq2T7WbAh+3a6NA+6WwK5izzMp/48gWBwwz8y+MrMJ3rJmzrm9EPhjBZqGOFNZ7fvZZ/d6h4+m23eHa0OaxztU1JPA/8B976MSecCnPvIOva0CsoD5BPbIHHHOFZTS5rd5vNdzgCbBzOOcO9M/j3n985SZxZTMU0rWqvA08FugyHveBB/7pgYIh7odjjW7vAx+9Zlqdvl5QDW71Dw+12wIct2ujQPu0v4H4sdULYOcc72Aa4FJZnaZDxkqyq8+ew7oAKQAe4EnQp3HzBoCbwP3OeeOlrdqKDKVkse3PnLOFTrnUoBWBPbEdCmnzZDnMbPuwIPARUAqkAD8Lth5zOxHQJZz7qvii8tpL1xqUjgLhz6qTjUb/Okz1eyz51HNLiOPXzUbQlO3a+OAOxNoXex5K2BPqEM45/Z437OAvxP48O8/c4jE+54V4lhlte9Lnznn9nt/kEXAC3x3eC0kecwsikChnOWce8db7FsflZbH7z7yMhwBPiNwXl1jM4sspc1v83ivN6Lih6Mrm2eYd1jXOedygRmEpn8GAdeZ2Q4Cpz4MJbDnxPe+qcZ8r9thWrMpJ0PI+8zveqSaXTGq2aUKet2ujQPu5UAn78rTaAInu88NZQAza2BmsWceA1cDa70ct3ur3Q68F8pc5bQ/FxjrXSXcH8g5c4gumEqcn3U9gT46k2e0d5VwO6ATkFbFbRswDdjgnHuy2Eu+9FFZefzqIzNLMrPG3uN6wFUEzlFcCNzorVayf870243Ap865qtw7UVqejcX+oTUC594V75+g/L6ccw8651o555IJ1JdPnXO34lPf1BC+1u0wrtmUkyHkdVs1++x5VLPLzeNLzYYQ1W0XhKs8w/2LwNWumwmcv/QfPrTfnsDVyBnAujMZCJz/8wmwxfueEMQMrxM4nJVP4H9q48tqn8Chk2e8/loD9AlRnplee6u9D3eLYuv/h5dnE3BtEPIMJnB4aDWwyvsa7lcflZPHlz4CLgZWeu2uBR4q9tlOI3DBz5tAjLe8rvd8q/d6+xDl+dTrn7XAq3x3VXzQP9NeO0P47mp3X/qmpnzhY90mDGq2117Y1O0ysqhmnz2Panb5eXyt2V5bQwhC3dadJkVEREREgqg2nlIiIiIiIhIyGnCLiIiIiASRBtwiIiIiIkGkAbeIiIiISBBpwC0iIiIiEkQacIuIiIiIBJEG3CIiIiIiQaQBt4iIiIhIEP0/VmR10MOURg4AAAAASUVORK5CYII=\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"learn.recorder.plot_lr(show_moms=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> plot_metrics()\n",
"\n",
"Plot metrics collected during training. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Recorder.plot_metrics)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that metrics are only collected at the end of each epoch, so you'll need to train at least two epochs to have anything to show here."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
""
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"learn.recorder.plot_metrics()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Callback methods"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You don't call these yourself - they're called by fastai's [`Callback`](/callback.html#Callback) system automatically to enable the class's functionality."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"on_backward_begin[source] \n",
"\n",
"> on_backward_begin(**`smooth_loss`**:`Tensor`, **\\*\\*`kwargs`**:`Any`)\n",
"\n",
"Record the loss before any other callback has a chance to modify it. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Recorder.on_backward_begin)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_batch_begin(**`train`**, **\\*\\*`kwargs`**:`Any`)\n",
"\n",
"Record learning rate and momentum at beginning of batch. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Recorder.on_batch_begin)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_epoch_end(**`epoch`**:`int`, **`num_batch`**:`int`, **`smooth_loss`**:`Tensor`, **`last_metrics`**=***`typing.Collection[typing.Union[torch.Tensor, numbers.Number]]`***, **\\*\\*`kwargs`**:`Any`) → `bool`\n",
"\n",
"Save epoch info: num_batch, smooth_loss, metrics. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Recorder.on_epoch_end)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_train_begin(**`pbar`**:`PBar`, **`metrics_names`**:`StrList`, **\\*\\*`kwargs`**:`Any`)\n",
"\n",
"Initialize recording status at beginning of training. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Recorder.on_train_begin)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Inner functions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following functions are used along the way by the [`Recorder`](/basic_train.html#Recorder) or can be called by other callbacks."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> add_metrics(**`metrics`**)\n",
"\n",
"Add `metrics` to the inner stats. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Recorder.add_metrics)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> add_metric_names(**`names`**)\n",
"\n",
"Add `names` to the inner metric names. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Recorder.add_metric_names)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> format_stats(**`stats`**:`MetricsList`)\n",
"\n",
"Format stats before printing. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Recorder.format_stats)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Module functions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Generally you'll want to use a [`Learner`](/basic_train.html#Learner) to train your model, since they provide a lot of functionality and make things easier. However, for ultimate flexibility, you can call the same underlying functions that [`Learner`](/basic_train.html#Learner) calls behind the scenes:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> fit(**`epochs`**:`int`, **`model`**:[`Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module), **`loss_func`**:`LossFunction`, **`opt`**:[`Optimizer`](https://pytorch.org/docs/stable/optim.html#torch.optim.Optimizer), **`data`**:[`DataBunch`](/basic_data.html#DataBunch), **`callbacks`**:`Optional`\\[`Collection`\\[[`Callback`](/callback.html#Callback)\\]\\]=***`None`***, **`metrics`**:`OptMetrics`=***`None`***)\n",
"\n",
"Fit the `model` on `data` and learn using `loss_func` and `opt`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(fit)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that you have to create the `Optimizer` yourself if you call this function, whereas [`Learn.fit`](/basic_train.html#fit) creates it for you automatically."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> train_epoch(**`model`**:[`Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module), **`dl`**:[`DataLoader`](https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader), **`opt`**:[`Optimizer`](https://pytorch.org/docs/stable/optim.html#torch.optim.Optimizer), **`loss_func`**:`LossFunction`)\n",
"\n",
"Simple training of `model` for 1 epoch of `dl` using optim `opt` and loss function `loss_func`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(train_epoch)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You won't generally need to call this yourself - it's what [`fit`](/basic_train.html#fit) calls for each epoch."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> validate(**`model`**:[`Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module), **`dl`**:[`DataLoader`](https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader), **`loss_func`**:`OptLossFunc`=***`None`***, **`cb_handler`**:`Optional`\\[[`CallbackHandler`](/callback.html#CallbackHandler)\\]=***`None`***, **`pbar`**:`Union`\\[`MasterBar`, `ProgressBar`, `NoneType`\\]=***`None`***, **`average`**=***`True`***, **`n_batch`**:`Optional`\\[`int`\\]=***`None`***) → `Iterator`\\[`Tuple`\\[`IntOrTensor`, `Ellipsis`\\]\\]\n",
"\n",
"Calculate `loss_func` of `model` on `dl` in evaluation mode. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(validate)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is what [`fit`](/basic_train.html#fit) calls after each epoch. You can call it if you want to run inference on a [`DataLoader`](https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader) manually."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> get_preds(**`model`**:[`Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module), **`dl`**:[`DataLoader`](https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader), **`pbar`**:`Union`\\[`MasterBar`, `ProgressBar`, `NoneType`\\]=***`None`***, **`cb_handler`**:`Optional`\\[[`CallbackHandler`](/callback.html#CallbackHandler)\\]=***`None`***, **`activ`**:[`Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module)=***`None`***, **`loss_func`**:`OptLossFunc`=***`None`***, **`n_batch`**:`Optional`\\[`int`\\]=***`None`***) → `List`\\[`Tensor`\\]\n",
"\n",
"Tuple of predictions and targets, and optional losses (if `loss_func`) using `dl`, max batches `n_batch`. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(get_preds)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> loss_batch(**`model`**:[`Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module), **`xb`**:`Tensor`, **`yb`**:`Tensor`, **`loss_func`**:`OptLossFunc`=***`None`***, **`opt`**:`OptOptimizer`=***`None`***, **`cb_handler`**:`Optional`\\[[`CallbackHandler`](/callback.html#CallbackHandler)\\]=***`None`***) → `Tuple`\\[`Union`\\[`Tensor`, `int`, `float`, `str`\\]\\]\n",
"\n",
"Calculate loss and metrics for a batch, call out to callbacks as necessary. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(loss_batch)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You won't generally need to call this yourself - it's what [`fit`](/basic_train.html#fit) and [`validate`](/basic_train.html#validate) call for each batch. It only does a backward pass if you set `opt`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Other classes"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"class LearnerCallback[source] \n",
"\n",
"> LearnerCallback(**`learn`**) :: [`Callback`](/callback.html#Callback)\n",
"\n",
"Base class for creating callbacks for a [`Learner`](/basic_train.html#Learner). "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(LearnerCallback, title_level=3)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"class RecordOnCPU[source] \n",
"\n",
"> RecordOnCPU() :: [`Callback`](/callback.html#Callback)\n",
"\n",
"Store the `input` and `target` going through the model on the CPU. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(RecordOnCPU, title_level=3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Undocumented Methods - Methods moved below this line will intentionally be hidden"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> _tta_only(**`learn`**:[`Learner`](/basic_train.html#Learner), **`ds_type`**:[`DatasetType`](/basic_data.html#DatasetType)=***``***, **`scale`**:`float`=***`1.35`***) → `Iterator`\\[`List`\\[`Tensor`\\]\\]\n",
"\n",
"Computes the outputs for several augmented inputs for TTA "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.tta_only)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": true
},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> _TTA(**`learn`**:[`Learner`](/basic_train.html#Learner), **`beta`**:`float`=***`0.4`***, **`scale`**:`float`=***`1.35`***, **`ds_type`**:[`DatasetType`](/basic_data.html#DatasetType)=***``***, **`with_loss`**:`bool`=***`False`***) → `Tensors`\n",
"\n",
"Applies TTA to predict on `ds_type` dataset. "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(Learner.TTA)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
"\n",
"\n",
"> on_batch_begin(**`last_input`**, **`last_target`**, **\\*\\*`kwargs`**)\n",
"\n",
"Set HP before the step is done. Returns xb, yb (which can allow us to modify the input at that step if needed). "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"show_doc(RecordOnCPU.on_batch_begin)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## New Methods - Please document or move to the undocumented section"
]
}
],
"metadata": {
"jekyll": {
"keywords": "fastai",
"summary": "Learner class and training loop",
"title": "basic_train"
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}