{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Computer Vision Learner" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[`vision.learner`](/vision.learner.html#vision.learner) is the module that defines the [`create_cnn`](/vision.learner.html#create_cnn) method, to easily get a model suitable for transfer learning." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [], "source": [ "from fastai.gen_doc.nbdoc import *\n", "from fastai.vision import *\n", "from fastai import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Transfer learning" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Transfer learning is a technique where you use a model trained on a very large dataset (usually [ImageNet](http://image-net.org/) in computer vision) and then adapt it to your own dataset. The idea is that it has learned to recognize many features on all of this data, and that you will benefit from this knowledge, especially if your dataset is small, compared to starting from a randomly initiliazed model. It has been proved in [this article](https://arxiv.org/abs/1805.08974) on a wide range of tasks that transfer learning nearly always give better results.\n", "\n", "In practice, you need to change the last part of your model to be adapted to your own number of classes. Most convolutional models end with a few linear layers (a part will call head). The last convolutional layer will have analyzed features in the image that went through the model, and the job of the head is to convert those in predictions for each of our classes. In transfer learning we will keep all the convolutional layers (called the body or the backbone of the model) with their weights pretrained on ImageNet but will define a new head initiliazed randomly.\n", "\n", "Then we will train the model we obtain in two phases: first we freeze the body weights and only train the head (to convert those analyzed features into predictions for our own data), then we unfreeze the layers of the backbone (gradually if necessary) and fine-tune the whole model (possily using differential learning rates).\n", "\n", "The [`create_cnn`](/vision.learner.html#create_cnn) factory method helps you to automatically get a pretrained model from a given architecture with a custom head that is suitable for your data." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

create_cnn[source]

\n", "\n", "> create_cnn(`data`:[`DataBunch`](/basic_data.html#DataBunch), `arch`:`Callable`, `cut`:`Union`\\[`int`, `Callable`\\]=`None`, `pretrained`:`bool`=`True`, `lin_ftrs`:`Optional`\\[`Collection`\\[`int`\\]\\]=`None`, `ps`:`Floats`=`0.5`, `custom_head`:`Optional`\\[[`Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module)\\]=`None`, `split_on`:`Union`\\[`Callable`, `Collection`\\[`ModuleList`\\], `NoneType`\\]=`None`, `bn_final`:`bool`=`False`, `kwargs`:`Any`) → [`Learner`](/basic_train.html#Learner)" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(create_cnn, doc_string=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This method creates a [`Learner`](/basic_train.html#Learner) object from the [`data`](/vision.data.html#vision.data) object and model inferred from it with the backbone given in `arch`. Specifically, it will cut the model defined by `arch` (randomly initialized if `pretrained` is False) at the last convolutional layer by default (or as defined in `cut`, see below) and add:\n", "- an [`AdaptiveConcatPool2d`](/layers.html#AdaptiveConcatPool2d) layer,\n", "- a [`Flatten`](/layers.html#Flatten) layer,\n", "- blocks of \\[[`nn.BatchNorm1d`](https://pytorch.org/docs/stable/nn.html#torch.nn.BatchNorm1d), [`nn.Dropout`](https://pytorch.org/docs/stable/nn.html#torch.nn.Dropout), [`nn.Linear`](https://pytorch.org/docs/stable/nn.html#torch.nn.Linear), [`nn.ReLU`](https://pytorch.org/docs/stable/nn.html#torch.nn.ReLU)\\] layers.\n", "\n", "The blocks are defined by the `lin_ftrs` and `ps` arguments. Specifically, the first block will have a number of inputs inferred from the backbone `arch` and the last one will have a number of outputs equal to `data.c` (which contains the number of classes of the data) and the intermediate blocks have a number of inputs/outputs determined by `lin_frts` (of course a block has a number of inputs equal to the number of outputs of the previous block). The default is to have an intermediate hidden size of 512 (which makes two blocks `model_activation` -> 512 -> `n_classes`). If you pass a float then the final dropout layer will have the value `ps`, and the remaining will be `ps/2`. If you pass a list then the values are used for dropout probabilities directly.\n", "\n", "Note that the very last block doesn't have a [`nn.ReLU`](https://pytorch.org/docs/stable/nn.html#torch.nn.ReLU) activation, to allow you to use any final activation you want (generally included in the loss function in pytorch). Also, the backbone will be frozen if you choose `pretrained=True` (so only the head will train if you call [`fit`](/basic_train.html#fit)) so that you can immediately start phase one of training as described above.\n", "\n", "Alternatively, you can define your own `custom_head` to put on top of the backbone. If you want to specify where to split `arch` you should so in the argument `cut` which can either be the index of a specific layer (the result will not include that layer) or a function that, when passed the model, will return the backbone you want.\n", "\n", "The final model obtained by stacking the backbone and the head (custom or defined as we saw) is then separated in groups for gradual unfreezeing or differential learning rates. You can specify of to split the backbone in groups with the optional argument `split_on` (should be a function that returns those groups when given the backbone). \n", "\n", "The `kwargs` will be passed on to [`Learner`](/basic_train.html#Learner), so you can put here anything that [`Learner`](/basic_train.html#Learner) will accept ([`metrics`](/metrics.html#metrics), `loss_func`, `opt_func`...)" ] }, { "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": {}, "outputs": [ { "data": { "text/html": [ "Total time: 00:09

\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", " \n", "
epochtrain_lossvalid_lossaccuracy
10.1272110.0804210.976938
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "learner = create_cnn(data, models.resnet18, metrics=[accuracy])\n", "learner.fit_one_cycle(1,1e-3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learner.save('one_epoch')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Get predictions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once you've actually trained your model, you may want to use it on a single image. This is done by using the following method." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

predict[source]

\n", "\n", "> predict(`img`:[`ItemBase`](/core.html#ItemBase), `kwargs`)\n", "\n", "Return prect class, label and probabilities for `img`. " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(Learner.predict)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(Category 7, tensor(1), tensor([0.0200, 0.9800]))" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "img = learner.data.train_ds[0][0]\n", "learner.predict(img)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here the predict class for our iamge is '3', which corresponds to a label of 0. The probabilities the model found for each class are 99.65% and 0.35% respectively, so its confidence is pretty high.\n", "\n", "Note that if you want to load your trained model and use it on inference mode with the previous function, you can create a `cnn_learner` from empty data. First export the relevant bits of your data object by typing:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "data.export()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And then you can load an empty data object that has the same internal state like this:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "empty_data = ImageDataBunch.load_empty(path, tfms=get_transforms()).normalize(imagenet_stats)\n", "learn = create_cnn(empty_data, models.resnet18)\n", "learn = learn.load('one_epoch')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Customize your model" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can customize [`create_cnn`](/vision.learner.html#create_cnn) for your own model's default `cut` and `split_on` functions by adding them to the dictionary `model_meta`. The key should be your model and the value should be a dictionary with the keys `cut` and `split_on` (see the source code for examples). The constructor will call [`create_body`](/vision.learner.html#create_body) and [`create_head`](/vision.learner.html#create_head) for you based on `cut`; you can also call them yourself, which is particularly useful for testing." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

create_body[source]

\n", "\n", "> create_body(`model`:[`Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module), `cut`:`Optional`\\[`int`\\]=`None`, `body_fn`:`Callable`\\[[`Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module), [`Module`](https://pytorch.org/docs/stable/nn.html#torch.nn.Module)\\]=`None`)\n", "\n", "Cut off the body of a typically pretrained `model` at `cut` or as specified by `body_fn`. " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(create_body)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

create_head[source]

\n", "\n", "> create_head(`nf`:`int`, `nc`:`int`, `lin_ftrs`:`Optional`\\[`Collection`\\[`int`\\]\\]=`None`, `ps`:`Floats`=`0.5`, `bn_final`:`bool`=`False`)" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(create_head, doc_string=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Model head that takes `nf` features, runs through `lin_ftrs`, and ends with `nc` classes. `ps` is the probability of the dropouts, as documented above in [`create_cnn`](/vision.learner.html#create_cnn)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

class ClassificationInterpretation[source]

\n", "\n", "> ClassificationInterpretation(`data`:[`DataBunch`](/basic_data.html#DataBunch), `probs`:`Tensor`, `y_true`:`Tensor`, `losses`:`Tensor`, `sigmoid`:`bool`=`None`)\n", "\n", "Interpretation methods for classification models. " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(ClassificationInterpretation)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This provides a confusion matrix and visualization of the most incorrect images. Pass in your [`data`](/vision.data.html#vision.data), calculated `preds`, actual `y`, and your `losses`, and then use the methods below to view the model interpretation results. For instance:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learn = create_cnn(data, models.resnet18)\n", "learn.fit(1)\n", "preds,y,losses = learn.get_preds(with_loss=True)\n", "interp = ClassificationInterpretation(data, preds, y, losses)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following fatory method gives a more convenient way to create an instance of this class:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

from_learner[source]

\n", "\n", "> from_learner(`learn`:[`Learner`](/basic_train.html#Learner), `ds_type`:[`DatasetType`](/basic_data.html#DatasetType)=``, `sigmoid`:`bool`=`None`, `tta`=`False`)\n", "\n", "Create an instance of [`ClassificationInterpretation`](/vision.learner.html#ClassificationInterpretation). `tta` indicates if we want to use Test Time Augmentation. " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(ClassificationInterpretation.from_learner)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "
Warning: In both those methods `sigmoid` is a deprecated argument and will be removed in a future version.
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "jekyll_warn('In both those methods `sigmoid` is a deprecated argument and will be removed in a future version.')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

plot_top_losses[source]

\n", "\n", "> plot_top_losses(`k`, `largest`=`True`, `figsize`=`(12, 12)`)\n", "\n", "Show images in `top_losses` along with their prediction, actual, loss, and probability of predicted class. " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(ClassificationInterpretation.plot_top_losses)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `k` items are arranged as a square, so it will look best if `k` is a square number (4, 9, 16, etc). The title of each image shows: prediction, actual, loss, probability of actual class." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAakAAAHOCAYAAAAi3fa5AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzt3Xe4FEX2N/DvgUvOoIiKgKJIEBOwGIkqiuiqKLqyCIuoqKwBV8wrYgLXDIsJEQTjz3XNaQ1gDhgWBIFVCaKASL5EgXr/6LovfYqZnhkm1cz9fp5nnntPd013dXdNn+mu7h4xxoCIiMhHFfJdASIioniYpIiIyFtMUkRE5C0mKSIi8haTFBEReYtJioiIvMUkVUREpIuIGPvqYocNLxuWoXnMt9ObkInpFaNk17mITLDl5ueoat7IZDsSkQGhdt8slXKxtgHbuF+YpIrfIgCf2VdSYiW7kK/ttH7IXBVj1uFgO//TMzjNpHZm2SQil4nIVhFpmI/5u7Kxnj22DNs/C5siyu3Qxpm48qck3xWg7USksjFmcyanaYwZB2BcBqd3aqamlcApADYCeCNH88uVUwB8Yoz5VUTyXRcgg+s5G+03k4wxrwJ4NYlyuWrjlAQeSWVB6FvX4yJys4gsFZF1IvKkiNRxykwSkbtE5DfYox0RqSwiN4jIHBHZJCLL7XsbO/MZLCILRWS9iLwMYM8YdYl56klE+ojIhyKy1r7/WxE5RUSGA3gvVPS98DfIWN8oRaS+iIyxdfldRH4VkadEpHmseohIVxH5SkQ22L+HxViNpwB4xxhTKiJNReR1EfnJvmeDre9lEtrTS2CwiHxpl6nU/n+Ere9joenPs3UZbt9rwrEdNsUOmxIa9g8RmSkiq+yy/iIiE0Vk9xjL4G6LBgCOAvBCRJmKInKFnccmEVkjIu+KSHenzC0i8r1dFytF5BsRGRkqc7yIfGTHbRCReSLybxHZO2I9h480/2jfv1FE/icip4amHS7XR0SmichmAD3t+KNE5E0RWW2XYY6IXCcilWIvstwgIkvE+YzYkX+zy7bCru9lIvK8iLSIswpbi8j7SdS7WcQ2+P9tXESaSfDZaWpH9w9No0fo/1ah9w+0wzaISN1486EkGWP4yvALwHwABsE31FUA5tjYAHjWKbPJvmYA+MCOe9mO2wpgOoAVNl4AoJ4t0zM0zeUITk2UhoZ1seWGlw0L1e+KULk1dh6ltuwgALNC42cB+BTADU69J9i4qq27AbAFwEwAG2y8DEBjtx52vcwG8LuN5wMoCdWvmR0+yMbtbfwTgK8ALA1N6+LQ+0aHhq+w9doAYACAG+w6Khv/tV2usnmUDR8emt4UO2xKaNi3dpvOAPAdgG22zOehMjusczt8gB2+r40nlC1/qMy4UF2+B/AbtreFE2yZv4bW938RtK+NAL6343dB0KYMgIUAvkHQRgyAoyLW8wDsuI3WhObVNka5TQB+BvA/AH8E0CW0XVdCt/2nYnxGShHnM2LLvWLLzLLrfAu2t4WqMepTmmS9m0Vsg7K6TQCwO4J2UrY+l9n4UwBil9sA+Efo/a/ZYU/ne19UDK+8V6AYX6FGvhxAQzvsXjtsG4B9oJPUgbZMRQCdQh+k4+zwuvbDYQBcZ4dNLftwAahjh00KvbeLHTa8bJiNq2N7MvsMQN3Q8Jb2/y7udGIs2wQb/yVU9nQ77IDQzuQutx4A/mqHXRIa1jI0j8sQ7JQbhpa/WWh8hdDylyX2ZtieMF7E9h1YPQB72/8HwNlJhaaZbJI6EECFUDwo9N7msdZ5qOwLAL4NxRPKtqGNm4eWYYwdVgvAXDvsSzusLBk/GppWNQBH2P/bYfsXkOpO3XeNWM/h9XOLHdYY29vLxBjlnihbHwjab9l2WYjtX6hGhsqXJYz5SPAZscPaAKgUqvMxoWl1T6PezWJtg1htPN4wO/xyO3wJgu6TOtie0I7P976oGF483ZddU4wxv9r/n7F/BcEHr8x7xpjpAGCM2QqgY2jcm/ZUw0oE344BoOzUWNuyMsaY1fb/Z5OoUxsANez/Y40xq+y81xtjZifxflcH+3czgH/ZaX2L4OgMCI6CXJPs31mhYbuF/v///TY2/h3AMBFZICK/I9ixdrLj9gjVo+zU393GmI22LiuNMfNSXqr4DgLwhT2VaAA8Ehq3R5z3QESqAzgOEaf6ECSXsmV4EgCMMWsRHE0AwMEiUtHGBsBAEVksIlMB3IogKQHB0eyPCBLcryLytYhMBtAawZFZGXc9hz1j578IwEd22AExyo02xmyzZbdie3t4wxizMrwsltseEn1GmiA45bxGRLYB+E/ovbHWd7L1zpTHAKxH0H57ATgZQGUAv0DXlXYSL5zIv6UR4z5HsDMKW5jFuuREWWJEcLRVRgDVb3N1aNy9CI5YgOD0ygoERx27IPj2nknh6dUJjxCRowBMtHVdjiDJ1gTQKsZ7XcchONqJSlJJMca8KSKHAjgDQdI8BEHSPk9EWhtjfhKRdgD6IfjS0xrA2QD6Ijh9dU+c9bwzotpvWkRkHwTrqzKAtQC+RLDPOtgWyfS2T5kxZpWIPAXgXPvaakdNtkmb0sQjqezqLCK72v/PCA2fGfrfTUJfhP6/2xhzmDHmMACHAxgG4CE77lv79zgRqWX/T+Yy4pkA1tn/B4tIbQAQkaoisr8dvj5UvgaildW3MoDedloHIDi1BADTkqhT2EkIdj7hnXnZ0eNbxpgWCE5H/hyjHmXr8jIRqWLrUifUSR61XGXf5pvb9+2LHb+Bd8T2I522xpg/AHg84RIFTgGwyBgTtT6+DC3Dn2w9aiH4hg4A3xhjtorIgQCWGWOuM8b0QnAEBgQJ8w92m7ZCcMrwz8aYQwG8Zct0s39jreewM+z89wBwhB32bYxy8drv8SJSz/5/dmi8u/xRn5FDELQrAOhhjOkAYFSc+qZa71SVtZ1Yn4d/2r8nADje/j8xA/MkgH1S2XghulP4/5wyE2K8/7VQ+bkIOozLOoIH2DK9QmV+Q3BRwMbQsC623PCyYaHpuxdO/Nf+HW7HN0Bw+q6sz+BTbO9vUvVG7Asn1mN7J/MOF06E6tElRn1Vv40d9kSo3Bw73bILAeaHyoUvnFiO4JTj+tA6OzA0frFdriPtuCdD46badboVoT4pAMc66/y7UD3irnMEyeA32H6mUH0nxFiGZC6cuAVBv81CBImtrL9yC4CWAPa18Qq7DmaHpnlrxHoeECpXapdvdWj+B8Yo18yZRhekf+FE2WekJbb3ba5G0M6WhcoNSLfecbZBWd0mhIY9H5relwAec5b749C0Pw+P4yu9F4+ksutfAO5CcNpoPYLz5ecl8b5TAdyIYOfSFEEn8I92WlMAwBjzCoAhCI4oaiBIUhcmUyljzF0AzkTwwaoAoAWCq6X+a8cvR3BRw08ILjzoCKBRnGltBNAZwbfJxXZa6+yyHmaCvoGkRPTbDEVwMUQpgn6WfyC4AtJ1CYCLEFy5Vx3BBSrfIThFCBP0/d2M4BRVI7tcZd/2hyK4h6YUwN4IvrF/6CzrfwBchaC/oRqC7ZPMOj8aQeJP5lTfBQCuRHAqcS8AVRDcEnCcMeZ1W2Yqgi8yguBorwTBtuxtgn7F5Qj6ShYjuKCkKYL2MQrATUn2j/VBkBCq2PeeaddfJGPMFABdERy5VUCwLuciuLrynBhvifsZscsyEMA8BEdUv8EeYWa63km4HsGXms0ADsX2PuEy/wz9z6OoDBL7LYAySIJHrDRFcFXRgPzWpnCIyCkA/g2gg4k+LVZQROReAP0RXFm3JVH5HNQn5noWkQHYfi/Z3saY+bmvXWGyfYRfIjibsacxZkWeq1Q0eCRFPlkP4PpiSlDWLASX3ec9QVnFup5zTkRaiciTCI70geC2ACaoDOLVfeQNY8xb2N7BXzSMMQ/nuw5hxbqe82Q3BKcg1yG4BWRYfqtTfHi6j4iIvMXTfURE5C0mKSIi8haTFBEReYtJioiIvMUkRURE3mKSIiIibzFJERGRt5ikiIjIW0xSRETkLSYpIiLyFpMUERF5i0mKiIi8xSRFRETeYpIiIiJvMUkREZG3mKSIiMhbTFJEROQtJikiIvIWkxQREXmLSYqIiLzFJEVERN7yLkmJyGQRWSwia0RkrogMilHmGhG5TUT6ikhp6LVeRIyItIuYfmUR+U1EasYZf5aIfCci60TkBxE5OmJa+4jIKyKy1k7zDju8iog8KiIL7LhvROSEJJb9IRE5P864y0VkiV0v40WkSsR0uovIbLs+3hORpqFxVez719jpDU1ULx85271URLaKyGinTFk7aS0i00RkpX29LSKtE0w/bjsRkSkisjE07zkR03ndqedmEZkRo1xn23ZvSWLZ54hIixjDU9q2UW1KRJrZtrPetqVjEtXLRwXUTq4UkW/t/mKeiFwZp5xv7eRmEZkhIltEZHiiOu0UY4xXLwBtAFSx/7cEsARAO6fMhwCOivHeAQB+ACAR0z8GwNtxxh0LYAGAwxAk8D0B7BmnbGU7r6EAagCoCuBAO64GgOEAmtnp9AKwFkCzBMu+EEDjGMN7AFhq1009AFMAjIwzjV0ArAZwhq3TPwB8Ghp/O4AP7HRa2fV7fL63e5ptpiaAUgCdYrUTAHXtthAAFQFcAmB6gmlGtZMpAAbtZF2nAPi7M6wSgG8AfArglgTvbw7g+zjjkt62idoUgE8A3A2gGoDeAFYB2DXf27pY2wmAYQAOBVACYH+7HzqrANpJfwAnAHgRwPCsbLd8N5wEK3p/AIsB9AkNqwfgVwAVY5R/D8CNCaZ5N4ChccZ9DODcJOt2PoAPUliW6QB6R4w/MN4HAsCTAG4Lxd0BLImo18ehuAaADQBa2vgXAMeFxt8M4Ol8b+s020l/AD8i9OUkXjuxO4GLAaxPo50kvfNx3tcMwFY4X1YAXA3gDgATktj5XALg/jjjkt62UW0KQAsAmwDUCo3/AMDgfG/r8tBO7HvvBzDa53bilJuMLCUp7073AYCIjBWR9QBmI0hSr4VG9wDwjjFmq/OepgA6AXg8weR7Ang1xjwrAmgPYFcR+V5EFonIGBGpFmc6hwGYb0/n/GYP7dvGWZ7dEHzwZ6ZaL6sNgP+G4v8C2E1EGiQqa4xZh+CIr42I1AOwe4xptYmoVyHoD+BxYz8t1g7tRERWAdgIYDSA2xJMM2p7AMDtdrt/JCJdkqznOQi+2MwP1akpgIEARiQ5jXjtN9VtG9Wm2gD40RizNslpFYqCaCciIgCORmh/4Wk7yQkvk5Qx5iIAtRBsqOcRfKsrcyJ00ipTtgOYF2+6ItIcQIkxJta54d0QHE6fbud7MIBDAFwfZ3KNAZyF4BvPHggaxIsiUtmZZyUATwCYaIyZHa9uEcsFBKcpVofisv9rJVG2rHwtOw7YcVqxplMQ7Ie3M4CJzqgd1qcxpi6AOgCGAPg6YppR7QQArgKwD4LTwQ8DeNm+J5FzEHwLDrsfwA3GmNJEbxaR6gA6IPiG7kp120a1qag2VJAKrJ0MR7Bvfiw0zMd2khNeJikAMMZsNcZ8iCAZXAgAIlIBQb/RGzHecg52bICungBejzNug/072hiz2BjzG4JD+Z4R5T80xrxujNkM4E4ADRCc40WovpMAbEbQ4GMSkboI+t8+jlOkFEDtUFz2/9okypaVX2vHATtOK9Z0CkU/BNvh/385iWon9sjyQQCPi0jDONOMaicwxnxmjFlrjNlkjJkI4CPEbydldToKQCMAz4WGnYTglNozUe8N6Y7gVO6mGONS3bZRbSqqDRWqQmknQxDsy04s284et5Oc8DZJhZQg6AQEgm8HC4wxy8IFRORIBEczzyFaT8Q5WjHGrASwCED4VICJVdaaHjXeHrI/iuAIrbcx5veIafUA8K57CjNkJoCDQvFBAJYaY5YnKisiNRCsv5l2GRfHmFbUaUjfxfpyErOdhFQAUB3BN9xY4raTOAyCzvYo/QE873wT7g6gvb1yagmAMwFcJiIvplqvndi2UW1qJoB9RKSWM57tRMtoOxGRgQj6nbobYxaFRvnaTnIjGx1dO/sC0BDBKbSaCK6u6QFgHYCT7fib4FwZZYc/jOBcc9S0qwNYDqBqRJkRAL6w9aiHoLP45jhl9wewHsHVPRUBXI6g76eyHf8ggqtwaiax3BMBnBMx/ngEV+C0RnAF0ruIf3XfrggOyXsjuLpvFPTVfSMBTLXL1xJBgy3Iq/sAHGHbRy1nuGonCL4tH2K3U20Ep05+idUWErUTu/572HVbAqCvrUOLiHpWs9ukmzO8FoKjq7LXMwDuAVA/znTmA2gSMZ+kt22iNmXb7p12OU9FAV/dVwjtxI5fAqBVjHE+t5NKdhmfBHCL/X+Hi9rS2n75bkDOCtnVrrxVANYAmAHgvND4aQDaO++past3TzDtXgBeSVCmEoCxdnpLbCOtasc1QXDo2yRU/jQA39u6TgHQxg5viuBb00b7nrJX3xjzFDuvhgnqNhTBpaBrEJyrrhIaNzM8bQSJczaCU5JTELqaDEAVAOPtdJYizpVJhfAC8BCASTGGq3aC4HL82XYbLEPQf3jgzrQT20a/QHC6YxWCnfmxofFHAyh13vMnBJcUx701wpabgDhXbQE4AMC3Cd4fd9vGab9RbaqZbTsbAMwBcEy+t3cxtxMA8wD87uwvHiyAdjIBwb4u/BqQye0ndkbes1fIfY3gvqWUKy0iYxFsvLEZr1waROQPAMYYY/6Q77oUgyJuJ8MA7GKMGZbvuhQDtpPCUZLvCqSgDoArdqZBWd8AeDmD9cmkG/NdgSJSrO1kPvysV6FiOykQBXMkRURE5U8hXN1HRETlFJMUERF5K6d9UiLCc4sFzBiT6F6gjGA7KWxsJ5SMZNsJj6SIiMhbTFJEROQtJikiIvIWkxQREXmLSYqIiLzFJEVERN5ikiIiIm8xSRERkbeYpIiIyFtMUkRE5C0mKSIi8haTFBEReYtJioiIvMUkRURE3mKSIiIibzFJERGRt5ikiIjIW0xSRETkLSYpIiLyFpMUERF5i0mKiIi8xSRFRETeYpIiIiJvleS7AkREheiKK65Q8Zlnnqni9u3bq1hEVDx9+nQVX3755Sp+9913061iUeCRFBEReYtJioiIvMUkRURE3irXfVJNmjRR8ahRo1R81llnqfjJJ59Ucd++fbNTsTi6deum4i+//FLFq1evzmV1yo3DDjtMxW5fQdWqVVXs9j0YY9Ka/4YNG1R82WWXRZbfunWrisePH5/W/MurSpUqqfiRRx5RcY8ePVT86KOPqvi0005TsduORo4cqeJ+/fqpmH1SAR5JERGRt5ikiIjIW0xSRETkLUn3fHlKMxPJ3cwAVKtWTcW33HKLii+88EIVr127VsWffvqpinv27KniZcuWqfjSSy9V8cKFC1U8YsQIFTdu3FjFFSro7wwNGjRQcf369VX80UcfqfiPf/yjiletWoVMMsZI4lLpy3U7OfDAA1U8bNgwFXft2lXFjRo1ynqd0rFt2zYV/+Mf/1DxzTffrGK3zytdxdJOqlevruLS0lIVt2rVSsVz5sxJafpXX321it37pHbbbbeUpldokm0nPJIiIiJvMUkREZG3mKSIiMhbRd0ndeWVV6rYvQ/K9dBDD6n4jjvuUPHgwYNV7N4n5faB1ahRQ8WVK1eOnH+6unTpouL3338/o9Mvlr4Gl9snk+p2WrFihYqHDx+ebpVScv3116u4YcOGkeUPPvhgFc+YMSOj9SmWdlKlShUV//jjjypu27atit12kMhee+2l4gULFqjYvS9yypQpKU3fd+yTIiKigsckRURE3mKSIiIibxX1s/t69+6t4rffflvFbl+Ee5/DvHnzVHzTTTep+KuvvlKxe9+Ea/78+SouKdGr372/xb2PYt9991XxmjVrVOzel0WB888/X8X33Xefit0+KHe9vvjiiyp274dz29HmzZt3qp47q27duip278ejnbNp0yYVH3PMMSpev359VufftGnTrE6/UPBIioiIvMUkRURE3mKSIiIibxV1n5Tb9+A+6859Fp/7rDyXew76mWeeSaN2O3J/36pNmzYqdp/tNXnyZBW7fV4UGDhwoIoT9UG5z3R8+umns1OxneQ+w/Hcc8+NLL9y5UoVu30tlJzvvvsuo9Nz78Oi2HgkRURE3mKSIiIibzFJERGRt4q6T+q5555T8RVXXKHiv/3tbyp+4IEHsl6nKBdddJGK3T4o9/eh3GcLUmyjR49Wsft7ULNmzVLx66+/nvU6pcPtY0t0P80TTzyh4rlz52a8TpS6M888M3I8+5gDPJIiIiJvMUkREZG3mKSIiMhbRfV7UuPGjVPx4YcfrmL32XqPPPKIii+44ILs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m+lq3bq1it2+h1WrVqn4o48+yuj8KTvGjx+v4k8++UTF7n1WEyZMUPH111+vYvf+vkMPPVTF9erVUzH7pIiIiNLEJEVERN5ikiIiIm8VdZ+U+6w+18SJE1U8f/78LNaGfLXHHnuouHLlypHl586dq2K3byFd7rP63Gfxudw+slz/zlh58fjjj6vYvU/K7ct84IEHVPzuu++q+PXXX1exux0fffTRyPq89dZbke8fN26cin/++efI6fmKR1JEROQtJikiIvIWkxQREXmrqPukEvnuu+/yXQWlUaNGkePd35sqLS3NZnXKjSFDhqi4bt26Kt64caOKb7rppqzWp127diru0qVLZHm3b5Wy4+WXX1ax2+ftPsPRffZmutxnNNauXTty/u6zRwsVj6SIiMhbTFJEROQtJikiIvJWUfdJPf300yr+05/+pOIVK1bksjo7cH/f6oYbbogsf/vtt6vYPQdNO+eEE06IHD9q1CgVv/jii9msDtq3b59S+VtuuSVLNaGwpUuXqjjV34dKl3s/38KFC1XstoNi6bPmkRQREXmLSYqIiLzFJEVERN4S93lTWZ2ZSO5mBqBKlSoqfv7551XcvHlzFbu/P5VtL730kopPPPFEFbu/d9W2bVsV57pPzRgjuZhPrttJmzZtVLzLLruoeOrUqbmsDt58800VH3PMMZHlK1asmM3qpKxY20mmufubHj16qPi8885TcYsWLVTs/s5ZjRo1VLx169Z0q5hVybYTHkkREZG3mKSIiMhbTFJEROStor5PatOmTSq+/PLLVew++yrb3N8F6tq1q4oXL16s4lNOOUXF+b6vq1jNnDkzq9Nv2LChit2+0MGDB6vY7SNL1G/s/m7Rtddeq+KVK1cmVU9KT6VKlVS8//77q9h99p+7/6lXr15K89uyZYuKzzrrLBU/++yzKv79999Tmr4veCRFRETeYpIiIiJvMUkREZG3ivo+qXwbMGCAikePHq3i6tWrq/jGG29UsW/PZOP9LwH3frXDDjtMxb1791Zx06ZNVeze75LuZ9Dta+jVq5eK33nnnbSmn6ry2k7c+9Xc++3cZ+25fViZNnz4cBWPGDEiq/NLFe+TIiKigsckRURE3mKSIiIib7FPKoPc+6DGjBmjYrcP6v7771fx1VdfrWL3Pq98K699DY888oiKTz31VBXXrVs3pemJ6NWY6mdw1qxZKnbvj3HH51p5bSeJuJ9n9/eeFixYoGK33f3vf/9TcUmJvs11/PjxKnaf3Tdu3DgV33TTTQlqnF3skyIiooLHJEVERN5ikiIiIm+xTyoF7n0P7jlg91l8q1evVvH777+v4mHDhql40aJF6VYxq8prX4N7bj/RZ8btE3r99ddV7P7uj/vsPtdzzz2n4kGDBqnY7dvIt/LaThI588wzVfzTTz+p+OOPP05r+gcccICKP//8cxW/++67Kj7ttNNUvHnz5rTmnyr2SRERUcFjkiIiIm8xSRERkbfYJxXB7WO6/vrrVdylSxcVu78H5d5P88UXX2SucnlQrH0NHTp0ULG7ndxnKg4dOlTF7jPR7rrrrsj5NWrUSMU///xzZPnJkyer2L0fzzfF2k4KzaRJk1Tct29fFR9++OEq/uyzz7JepzD2SRERUcFjkiIiIm8xSRERkbdKEhcpXnXq1FHxRRddpOLrrrtOxdWqVVPxkiVLVHzKKaeoeNq0aelWkXIgUV+h+4yz//u//1Nxus/KS9Qv7D4b0P0dIvf3pIgAoGrVqiqePXu2ihP1hfqCR1JEROQtJikiIvIWkxQREXmrXPVJufc9uX1O7njXww8/HPn+FStWpFE7KhTp9kE1bdo0pfKHHnqoit1n/61atSqt+lBx6tGjh4rd+/l8f1ZoGR5JERGRt5ikiIjIW0xSRETkraLuk3LP3d96660q7tixo4qXL1+u4jvvvFPF9957r4pz/fsrVBx69+6dUvkxY8aomH1QlIwff/xRxe6z/AoFj6SIiMhbTFJEROQtJikiIvJWUfVJuc/We/XVV1Xs9kG552jdZ/etX78+g7UjCri/X+Vy+0IT/T4VUSwnn3yyipcuXZqnmqSHR1JEROQtJikiIvIWkxQREXlLEv2WTUZnJpLVmTVo0EDFv/76q4ovvPBCFY8bN07F27Zty07FioQxRnIxn2y3E8quYm0nF198sYrdPu01a9Zkdf7u79W9//77Ki60Z4cm2054JEVERN5ikiIiIm8xSRERkbeK6j4p99l7FStWzFNNiKjYbNmyRcWjR49Wcf/+/VOaXs2aNVVcWloaWb5y5coqbtSokYoLrU8qWTySIiIibzFJERGRt5ikiIjIW0V1nxRlV7He/0KZVV7aifu7YO6zQd966y0Vv/322yq+4447VDxs2LAM1s5/vE+KiIgKHpMUERF5i0mKiIi8ldM+KSIiolTwSIqIiLzFJEVERN5ikiIiIm8xSRERkbeYpIiIyFtMUkRE5C0mKSIi8haTFBERecu7JCUik0VksYisEZG5IjIoRplrROQ2EekrIqWh13oRMSLSLmL6lUXkNxGp6QyvIiKPisgCEVkrIt+IyAkR06kiIveIyC8islJExopIpdD4+iLybxFZZ6d5dhLL/qaIHBdjuIjIKBFZbl+jRCTuwxlF5Gw7z3Ui8oKI1A+NmyIiG0PrbE6ievmogNqJiMgtIvKziKy2679NaHwfEfnY1mlKkst+jYjcFmdc3G0fo+zBIvKlnfeXInKwM/5QEXnfrrOlInJpMvXzibPdS0Vkq4iMdsqUtZPWIjLNfp5XisjbItI6wfQz1U4edOq5SUTWhsb7uj9JuH7TZozx6gWgDYAq9v+WAJYAaOeU+RDAUTHeOwDAD7BP0ogz/WMAvB1jeA0AwwE0Q5C8ewFYC6BZnOncCOADAPUB7ArgUwA3hcY/BeAZADUBHAVgNYA2EfWqAWB52bI74y4AMAdAYwB7ApgFYHDE+lsLoJOd95MAng6NnwJgUL63czlqJ30A/AJgHwAVAdwO4CtnPn0A/B3AlCSXPd5yRW57p2xlAAsAXA6gCoBLbFzZjt8FwK8A+trxtQC0yvd2T7PN1ARQCqBTrPUJoK7drmK31SUApieYZkbaSYz3TwAwPhR7uT9JZv2mvd3y3XASbKj9ASwG0Cc0rJ798FSMUf49ADcmmObdAIYmOf/pAHrHGTcNwBmh+GwAP4UayGYALULjJwEYGTGvkwG8FGfcxwDOD8XnAvg0TtnbADwZipvbutSy8RQUQZIqoHZyFYBnQ3EbABtjlBuEJJJUguWK3PZO2eMA/IxQogawEMDxoWlNyve2zXA76Q/gR2eZY65PACUALgawPhftxClXwyaGzqHYy/1JovWbiZd3p/sAQIJTZ+sBzEaw83ktNLoHgHeMMVud9zRFkO0fTzD5ngBeTaIOuwFoAWBmVDHn/8YiUse+b4sxZm5o/H8R7KB2pl5t7PuTmZYqa4z5AbaBh8rcbk9RfCQiXSLq5LUCaSdPA2guIi0kOB3cH8AbiaYbIeZyWcls+3DZ6cbuXazp2N6uDgOwwp6K/FVEXhaRJmnU2wf9ATzuLPMO61NEVgHYCGA0gp10lEzuT8r0BrAMwPs29n1/UibW+k2bl0nKGHMRgtMLRwN4HsCm0OgToXdGZc4B8IExZl686YpIcwAlxpjIfhi7M3kCwERjzOw4xd4AcKmI7CoijRCcGgCA6ggOe9c45VfbZYqnJ2IvF+z0VjvTqhnnPLJb1p33VQhOPe0J4GEAL9v1UnAKpJ0sRnA6aQ6ADQDOQHCKbWfFWy4g8bZPpWxjBDudSwE0ATAPwSmngmS/nHQGMNEZtcP6NMbUBVAHwBAAX0dMM5PtJMzd2fu8PwEQuX7T5mWSAgBjzFZjzIcIPiwXAoCIVABwLGJ/Ez0HiVdQTwCvRxWw85iE4NvCkIiityJowN8gOHx+AcDvAJYiOC9b2ylfG8EhfKx5tgWw2hjzU5x5udOrDaA0zjeWyHkbYz4zxqw1xmwyxkwE8BGC9VKQCqCd/B1ABwB7AagK4CYA74pI9QR1iDfPeMsFpNbuEpXdAODfxpgvjDEbbb2PsGcKClE/AB+Gv5xErU9jzDoADwJ4XEQaxplmJttJWfkmALpAH+l7uz8J2WH9Zoq3SSqkBMF5UCD4sC8wxiwLFxCRIwHsAeC5BNOK+nYB+03iUQC7ITh3/Hu8ssaYDcaYIcaYPY0x+yDopPzSGLMNwFwAJSKyX+gtByH+oX5kvez7DkpyWqqsiOyDoON7bpzyBvq0ZaHysp0AOBjAM8aYRcaYLcaYCQj6QSKvGosj5nKFpLLtZwI40Pn2fCC2t6vpCNpGmUL/TZ9YX04Src8KCM6M7BlnfCbbSZl+AD4yxvwYGlYI+5NkvvztnEx2cKX7AtAQwFkIDjErIjhfvA7AyXb8TQD+HuN9DyM4PI6adnUEiaRqRJkHEVylVzOJuu6JYIcnCM7f/wTguND4pxGcHqkB4EhEXI0DYCoirogBMBjAd6F5zkT01ThrEJwCqwFgMuzVOAiuXuqB4Bt9CYIrt9Yh1CFbCK8Cayc3IjjdtxuCnV4/W9e6dnxFuz0GI+iDqAqgUpxpxVyuZLZ9jLJlV/ddimCnMwT66r5uAFYiSLKVANyD4DRp3rf/TrSXI+w6r+UMV+sTwVHVIXab1AZwP4IrM3doC5luJ6H3zAEwMMZw7/YnidZvxrZfvhuQs7C72hW8yq6YGQDOC42fBqC9856qtnz3BNPuBeCViPFNEXxb3IjgELfs1deOb2LjJjbuBGA+gPW2YfV1plcfwSnAdQiumjo7znzrIugkLYmomwC4A8AK+7oD+gqlUgBHh+Kz7TzXAXgRQP3Q+v0CwaH6KvsBOjbf273I20lVAP9E0De1BsBXsFfQ2fED7PTCrwlx5r3DcsUoE3Pb23GvA7g2FB8C4EsEp/a+AnCIM60LEVwBuBLAywD2yve238n28hBiXKnork8E/YWz7fZbhuDCgwNz0U7ssMMRZ2cPD/cnidZvpl4F88u89uqYrwHsaXai0iIyFsC3xpixGa9cGkSkD4DTjTF98l2XYlDE7SSt5SKtiNtJ0e1PSvJdgRTUAXBFGh/QbxB8G/TNKgSnUigzirWdpLtcpBVrOym6/UnBHEkREVH5UwhX9xERUTnFJEVERN7KaZ+UiPDcYgEzxuTkfiq2k8LGdkLJSLad8EiKiIi8xSRFRETeYpIiIiJvMUkREZG3mKSIiMhbTFJEROQtJikiIvIWkxQREXmLSYqIiLzFJEVERN5ikiIiIm8xSRERkbeYpIiIyFtMUkRE5C0mKSIi8haTFBEReYtJioiIvMUkRURE3mKSIiIib5XkuwJEvjn33HNVPG7cOBVv2LBBxU8++aSKH330URV/8sknGawdUfnCIykiIvIWkxQREXmLSYqIiLzFPikix8aNG1W8bNkyFYuIiv/yl7+ouG/fvip+6623VHzmmWdGzo9yo0WLFip+4403VNy0adPI91955ZUqNsakVZ+vvvpKxVOnTk1resWCR1JEROQtJikiIvIWkxQREXlL0j2PmtLMRHI3M8o4Y4wkLpU+39tJ5cqVVXz++eer+OSTT1Zx9+7dVez2UZ1xxhkqLi0tTbeKeVUo7aRatWoqfv/991V8yCGHJJq/itPdl65bt07Fq1atiizvjnfb0dy5c9OqT7Yl2054JEVERN5ikiIiIm8xSRERkbeKqk+qTp06KnbP8W7ZsiWbsy96hdLXkG/169dX8b/+9S8Vd+7cWcX9+vVT8RNPPJGdiuVIobaTE088UcXjx49XcYMGDdz5qzjdfWm601uwYIGKmzdvnlZ9so19UkREVPCYpIiIyFtMUkRE5K2C6pO66qqrVNypUycVd+vWTcXu/SizZs1y66PiWrVqqfiXX35RsXvfxJ577qni77//XsXufRgXXHCBipcvX45CUqh9Db7Ztm2bimfOnKnitm3b5rI6GVcs7eSwww5TcePGjVN6v/vsvyFDhkSWb9KkiYpT3Te/+OKLKu7du3dK78819kkREVHBY5IiIiJvMUkREZG3CqpPyj2XX2j+85//qLhHjx55qsnOKZa+hnxbsmSJimvXrq3iiy66SMWXX365it37YdxnBeYb20lsdevWVfH111+vYnc7s08qwCMpIiLyFpMUERF5i0mKiIi8VZLvCqSiXbt2KnafgdayZcvI97vn8qtWrariLl26qHjRokUqrlSpkopXrFih4s8//1zFI0eOVLH7TDcqn9x22L59exXffffdKnafSVnofbPlVa9evVTs9kFVqKCPGRJt57Vr16r4/vvvT6N2/uKRFBEReYtJioiIvMUkRURE3iqoPqmvv/46Ms43t+/gn//8p4r5e1YEAB06dFCxez+M245c06ZNy3idKH177bWXit3fBXOf/elud7cPKtF9Us8++6yKGzZsqOKDDz5Yxd98803k9HzFIykiIvIWkxQREXmLSYqIiLxVUH1S+eY+Y839vSj392OqVKmi4hkzZmSnYlSurF69Ot9VoBjcPqgjjjgiq/MbOHBgZLx06VIVu31Uy5Yty07FMoxHUkRE5C0mKSIi8haTFBEReYt9Uil45JFHVNy9e3cVv/HGG5Hvb9SokYrdZxG63GdzzZ07N1EVKQNatGgRGS9cuFDFp512morddpGusWPHqnjEiBEZnT5lhnsfUqp9Uu6zQt37ptw+bve+KJe7vxk9erSKr7rqKhW7z5T0BY+kiIjIW0xSRETkLSYpIiLyliR6PlRGZyaSu5llwaxZs1Sc6Per0vX777+reN26dSqePn26iqdOnRoZv/vuu2nVxxgjaU0gSfluJ+eee66Kx40bp+J0PzMiejW60xs2bJiK77zzzrTml2vlpZ24Bg0apOJrrrlGxe59lC+++KKKe/fuHTn93XffXcVnnnmmik866SQVu7+PN2fOHBU/+OCDKs7171El2054JEVERN5ikiIiIm8xSRERkbfYJ5WCJk2aqPi2225Tcc+ePVVct27djM4/UV+Gy+3Tcu+zSFV56Wtwf+/J7Stw17t7H5V7P1vVqlVVfOmll6rY7Wvs2LGjit2+UN+Vl3bim86dO6t4ypQpKnbvuxo5cqSKr7vuuqzUKx72SRERUcFjkiIiIm8xSRERkbf47L4UuM9s+/Of/6xi9/4a91l/ie5jSvSsr88//1zFxx9/fGT5v/3tb5HjKbYvvvgiMk7V8OHDI8evX79exYXWB0V+cO+Tcvug3L7Ul156Ket1ygQeSRERkbeYpIiIyFtMUkRE5C32SWWQ+/tPrv/9738qTtRXkcg999yj4uXLl6c1PcoM9360Xr16RZZ/4oknslkdopiaNWum4s8++yw/FUmAR1JEROQtJikiIvIWkxQREXmLfVIZ5D4ry5Vqn1Hfvn1V3KBBAxXn+vdfKDl77723ig855JDI8ps2bcpmdahIufuDWrVqRZZ378fr06ePip955pnMVCzDeCRFRETeYpIiIiJvMUkREZG32CeVQatXr1ax+6y/s88+W8X16tVTcatWrVT83Xffqfiuu+5Kt4qUB+7vgLnxhAkTclgbKhZjx45Vsfu7Z65FixapeOjQoRmvUzbwSIqIiLzFJEVERN5ikiIiIm+xTyqD3Ptdli1bpuJ27bUl+bsAAAJWSURBVNqpuF+/fipO1AflPvuPCoP7Oz6utm3bqnjOnDnZrA4VqKuvvlrFp59+emT5ChX0Mcixxx6r4p9//jkzFcsyHkkREZG3mKSIiMhbTFJEROQt9kll0aRJk1Ts/t7UZZddpuLp06dnvU7knzp16uS7CpQHBx98sIq/+eYbFbu/Q9a/f38VJ+rrdJ/Ft2HDhlSr6AUeSRERkbeYpIiIyFtMUkRE5C1JdF4zozMTyd3MKOOMMZK4VPoKvZ1UrFhRxffcc4+KhwwZomL3d35mz56t4s6dO6t43bp16VYxq9hOktO0aVMVP/XUUyp2+6wqV66c0vRLSvy+5CDZdsIjKSIi8haTFBEReYtJioiIvOX3SUuiArR161YV33rrrSp2+6SqVaum4q+++krFmzdvzmDtyBdun1PHjh1VnOh6gR9++EHF1113XWYq5hkeSRERkbeYpIiIyFtMUkRE5C32SRFl2dKlS1Xs/s4PUTLuu+8+FT/44IMqLtbfm+OnhYiIvMUkRURE3mKSIiIib/HZfZQ0PpONksF2Qsngs/uIiKjgMUkREZG3mKSIiMhbTFJEROQtJikiIvIWkxQREXmLSYqIiLyV0/ukiIiIUsEjKSIi8haTFBEReYtJioiIvMUkRURE3mKSIiIibzFJERGRt5ikiIjIW0xSRETkLSYpIiLyFpMUERF5i0mKiIi8xSRFRETeYpIiIiJvMUkREZG3mKSIiMhbTFJEROQtJikiIvIWkxQREXmLSYqIiLzFJEVERN5ikiIiIm8xSRERkbeYpIiIyFv/D/mh9dor3Zp/AAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "interp.plot_top_losses(9, figsize=(7,7))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

top_losses[source]

\n", "\n", "> top_losses(`k`:`int`=`None`, `largest`=`True`)\n", "\n", "`k` largest(/smallest) losses and indexes, defaulting to all losses (sorted by `largest`). " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(ClassificationInterpretation.top_losses)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Returns tuple of *(losses,indices)*." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/plain": [ "(tensor([6.6163, 5.7370, 5.2444, 4.4769, 3.1993, 3.0553, 2.9016, 2.8053, 2.7020]),\n", " tensor([ 515, 1031, 1581, 326, 597, 1509, 877, 674, 1516]))" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "interp.top_losses(9)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

plot_confusion_matrix[source]

\n", "\n", "> plot_confusion_matrix(`normalize`:`bool`=`False`, `title`:`str`=`'Confusion matrix'`, `cmap`:`Any`=`'Blues'`, `norm_dec`:`int`=`2`, `slice_size`:`int`=`None`, `kwargs`)\n", "\n", "Plot the confusion matrix, with `title` and using `cmap`. " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(ClassificationInterpretation.plot_confusion_matrix)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If `normalize`, plots the percentages with `norm_dec` digits. `slice_size` can be used to avoid out of memory error if your set is too big. `kwargs` are passed to `plt.figure`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "interp.plot_confusion_matrix()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

confusion_matrix[source]

\n", "\n", "> confusion_matrix(`slice_size`:`int`=`None`)\n", "\n", "Confusion matrix as an `np.ndarray`. " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(ClassificationInterpretation.confusion_matrix)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[987, 23],\n", " [ 30, 998]])" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "interp.confusion_matrix()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

most_confused[source]

\n", "\n", "> most_confused(`min_val`:`int`=`1`, `slice_size`:`int`=`None`) → `Collection`\\[`Tuple`\\[`str`, `str`, `int`\\]\\]\n", "\n", "Sorted descending list of largest non-diagonal entries of confusion matrix " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(ClassificationInterpretation.most_confused)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Working with large datasets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When working with large datasets, memory problems can arise when computing the confusion matrix. For example, an error can look like this:\n", "\n", " RuntimeError: $ Torch: not enough memory: you tried to allocate 64GB. Buy new RAM! at /opt/conda/conda-bld/pytorch-nightly_1540719301766/work/aten/src/TH/THGeneral.cpp:204\n", "\n", "In this case it is possible to force [`ClassificationInterpretation`](/vision.learner.html#ClassificationInterpretation) to compute the confusion matrix for data slices and then aggregate the result by specifying slice_size parameter. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[987, 23],\n", " [ 30, 998]])" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "interp.confusion_matrix(slice_size=10)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "interp.plot_confusion_matrix(slice_size=10)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('7', '3', 30), ('3', '7', 23)]" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "interp.most_confused(slice_size=10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## GANs" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

gan_learner[source]

\n", "\n", "> gan_learner(`data`, `generator`, `discriminator`, `loss_funcD`=`None`, `loss_funcG`=`None`, `noise_size`:`int`=`None`, `wgan`:`bool`=`False`, `kwargs`)\n", "\n", "Create a [`GANLearner`](/vision.learner.html#GANLearner) from `data` with a `generator` and a `discriminator`. " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(gan_learner)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If `noise_size` is set, the GAN will generate fakes from a noise of this size, otherwise it'll use the inputs in data. If `wgan` is set to `True`, overrides the loss functions for a WGAN. `loss_funcD` and `loss_funcG` are used for discriminator and the generator. `kwargs` are passed to the `Learner` init." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": true }, "outputs": [ { "data": { "text/markdown": [ "

class GANLearner[source]

\n", "\n", "> GANLearner(`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`) :: [`Learner`](/basic_train.html#Learner)" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(GANLearner, title_level=3, doc_string=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Subclass of [`Learner`](/basic_train.html#Learner) to deal with `predict` and `show_results` for GANs." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Undocumented Methods - Methods moved below this line will intentionally be hidden" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/markdown": [ "

class GANLearner[source]

\n", "\n", "> GANLearner(`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`) :: [`Learner`](/basic_train.html#Learner)\n", "\n", "Train `model` using `data` to minimize `loss_func` with optimizer `opt_func`. " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(GANLearner)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/markdown": [ "

show_results[source]

\n", "\n", "> show_results(`rows`:`int`=`5`, `figsize`=`(10, 10)`)\n", "\n", "Show `rows` by `rows` fake images with `figsize`. " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(GANLearner.show_results)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/markdown": [ "

add_gan_trainer[source]

\n", "\n", "> add_gan_trainer(`cb`)" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(GANLearner.add_gan_trainer)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/markdown": [ "

predict[source]

\n", "\n", "> predict()\n", "\n", "Predict one batch of fake images. " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "show_doc(GANLearner.predict)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## New Methods - Please document or move to the undocumented section" ] } ], "metadata": { "jekyll": { "keywords": "fastai", "summary": "`Learner` support for computer vision", "title": "vision.learner" }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 2 }