diff --git a/fastai2/_nbdev.py b/fastai2/_nbdev.py index bcc74cf9..614059c5 100644 --- a/fastai2/_nbdev.py +++ b/fastai2/_nbdev.py @@ -775,6 +775,9 @@ "CaptumInterpretation": "73_callback.captum.ipynb", "CaptumInterpretation.insights": "73_callback.captum.ipynb", "CutMix": "74_callback.cutmix.ipynb", + "BSFinder": "75_callback.bs_finder.ipynb", + "Recorder.plot_bs_find": "75_callback.bs_finder.ipynb", + "Learner.bs_find": "75_callback.bs_finder.ipynb", "synth_dbunch": "97_test_utils.ipynb", "RegModel": "97_test_utils.ipynb", "synth_learner": "97_test_utils.ipynb", @@ -831,6 +834,7 @@ "callback/neptune.py", "callback/captum.py", "callback/cutmix.py", + "callback/bs_finder.py", "test_utils.py", "_pytorch_doc.py"] diff --git a/fastai2/callback/bs_finder.py b/fastai2/callback/bs_finder.py new file mode 100644 index 00000000..77e7799d --- /dev/null +++ b/fastai2/callback/bs_finder.py @@ -0,0 +1,151 @@ +# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/75_callback.bs_finder.ipynb (unless otherwise specified). + +__all__ = ['BSFinder'] + +# Cell +from ..basics import * + +# Cell +# Linear combination for the moving average +def _lin_comb(v1, v2, beta): return beta*v1 + (1-beta)*v2 + + +def _ema_with_debias(avg, beta, yi, i): + "Exponential moving average with debiasing" + if avg is None: avg=0 + avg = _lin_comb(avg, yi, beta) + return avg, avg/(1-beta**(i+1)) + + +def _get_flatten_grads(model): + parameters = L(model.parameters()) + grads = [param.grad.flatten().view(-1,1) for param in parameters if not type(param.grad) == type(None)] + grad = torch.cat(grads) + return grad + +# Cell +class BSFinder(Callback): + "A `Callback` that implements \"An Empirical Model of Large-Batch Training\" (https://arxiv.org/abs/1812.06162)" + run_after=Recorder + + def __init__(self, num_it:int=None, n_batch=5, beta=0.99, simulate_multi_gpus=True): + store_attr(self, 'num_it, n_batch, beta, simulate_multi_gpus') + + def begin_fit(self): + # Save original model + self.learn.save('_tmp') + + if not self.num_it: self.num_it = len(self.dls.train) * (self.n_batch if self.simulate_multi_gpus else 1) + + self.running_scale = None + self.running_noise = None + + # Use python list instead L fastai list as torch.cat doesn't understand the former + self.stored_grads = [] + + # Here, we will store the results + self.stats = L() + self.count=0 + + def begin_validate(self): raise CancelValidException() + + def after_backward(self): + if self.train_iter >= self.num_it: raise CancelFitException() + + # Get gradients and store them + self.stored_grads.append(_get_flatten_grads(self.model)) + + self.count += 1 + if self.count != len(self.stored_grads): + breakpoint() + + if self.simulate_multi_gpus and len(self.stored_grads) < self.n_batch: + self.opt.zero_grad() # Zero gradients to avoid acumulate them between batches + #print('a', self.count, self.train_iter, learn.model.embeds[0].weight[0][:3].tolist()) + raise CancelBatchException() #skip weight update + + if len(self.stored_grads) == self.n_batch: + self.count=0 + #print('b', self.count, self.train_iter, learn.model.embeds[0].weight[0][:3].tolist()) + # We have enough batches to compute Simple Noise Scale ratio. + + # We concatenate the batches and empty the buffer + stored_grads = torch.cat(self.stored_grads, dim=1) + self.stored_grads.clear() + + acc_grads = stored_grads.mean(dim = 1) + + # The original implementation uses .mean() although in the original article didn't do it. However, averaging g_big and g_small doesn't affect to noise_scale ratio + if self.simulate_multi_gpus: g_small = (stored_grads ** 2).sum(dim=0).mean() + else: g_small = (stored_grads[:,-1] ** 2).sum() # .mean() + + # print((stored_grads ** 2).sum(dim=0).mean().item(), (stored_grads[:,-1] ** 2).sum().item(), (stored_grads ** 2).sum(dim=0).tolist()) + + g_big = (acc_grads ** 2).sum() # .mean() + + bs = find_bs(self.yb) # or self.dls.train.bs + b_small, b_big = bs, bs * self.n_batch + + noise = (b_big * g_big - b_small * g_small) / (b_big - b_small) + scale = (g_small - g_big) / ((1 / b_small) - (1 / b_big)) + + self.running_scale, scale = _ema_with_debias(self.running_scale,self.beta,scale,self.iter) + self.running_noise, noise = _ema_with_debias(self.running_noise,self.beta,noise,self.iter) + + scale = scale.item() + noise = noise.item() + noise_scale = (scale / noise) + + # Save results + self.stats.append(dict(n_iter=(len(self.stats)) * (1 if self.simulate_multi_gpus else self.n_batch), + noise=noise, scale=scale, noise_scale=noise_scale)) + + def after_fit(self): + if self.train_iter < self.num_it: warn(f"Fitting was too short to complete all expectediterations. Please, increase the number of epochs") + + tmp_f = self.path/self.model_dir/'_tmp.pth' + if tmp_f.exists(): + self.learn.load('_tmp') + os.remove(tmp_f) + + if hasattr(self.learn, 'recorder'): + # index = pd.Index(torch.arange(1, len(self.stats)+1)*self.n_batch, name='n_iter') + df = pd.DataFrame(self.stats)#, index=index) + df.set_index('n_iter', inplace=True) + self.recorder.bs_find_stats = df + + _docs = {"begin_fit": "Initialize container for search results and auxiliary variables and save the model", + "after_fit": "Record hyper-parameters of this batch and potentially stop training", + "after_backward": "Store gradients and compute Simple Noise Scale", + "begin_validate": "Skip the validation part of training"} + + +# Cell +@patch +def plot_bs_find(self:Recorder): + "Plot the result of an BS Finder test (won't work if you didn't do `learn.bs_find()` before)" + fig, ax = plt.subplots(1,1) + stats = self.bs_find_stats + ax.plot(stats.index, stats.noise_scale) + ax.set_ylabel("Simple Noise Scale") + ax.set_xlabel("# iteration") + +# Cell +@delegates(BSFinder) +@patch +def bs_find(self:Learner, lr, num_it=None, n_batch=5, simulate_multi_gpus=True, show_plot=True, **kwargs): + """ + Launch a mock training to find a good batch size to minimaze training time. + However, it may not be a good batch size to minimize the validation loss. + + A good batch size is where the Simple Noise Scale converge ignoring the small growing trend + with the number of iterations if exists. The optimal batch size is about an order the magnitud + where Simple Noise scale converge. Typically, the optimial batch size in image classification + problems will be 2-3 times lower where + """ + num_it = num_it if num_it else len(self.dls.train) + num_it *= n_batch if simulate_multi_gpus else 1 + n_epoch = num_it//len(self.dls.train) + cb=BSFinder(num_it=num_it, n_batch=n_batch, simulate_multi_gpus=simulate_multi_gpus, **kwargs) + with self.no_logging(): self.fit(n_epoch, lr, cbs=cb) + if show_plot: self.recorder.plot_bs_find() \ No newline at end of file diff --git a/nbs/75_callback.bs_finder.ipynb b/nbs/75_callback.bs_finder.ipynb new file mode 100644 index 00000000..2b960a9f --- /dev/null +++ b/nbs/75_callback.bs_finder.ipynb @@ -0,0 +1,1123 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#default_exp callback.bs_finder" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#export\n", + "from fastai2.basics import *" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from nbdev.showdoc import *" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Batch size finder callback\n", + "> Callback to apply [An Empirical Model of Large-Batch Training](https://arxiv.org/pdf/1812.06162.pdf) to find the optimal batch size to minimaze the training time. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Be aware that this batch size may not be a the best one to minimize the validation loss. From the paper:\n", + "> Some papers have reported a “generalizaion gap” in which large batch sizes lead to good training loss but cause a degradation in test loss, apparently unrelated to overfitting. \n", + "\n", + "Althought, also from the paper:\n", + "> ... but recent work has found no evidence of a generalization gap when hyperparameters are properly tuned.\n", + "\n", + "See section 2.4 \"Assumptions and Caveats\" from the research paper for more caveats of this method. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Helper functions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#export\n", + "# Linear combination for the moving average\n", + "def _lin_comb(v1, v2, beta): return beta*v1 + (1-beta)*v2\n", + "\n", + "\n", + "def _ema_with_debias(avg, beta, yi, i):\n", + " \"Exponential moving average with debiasing\"\n", + " if avg is None: avg=0\n", + " avg = _lin_comb(avg, yi, beta)\n", + " return avg, avg/(1-beta**(i+1))\n", + "\n", + "\n", + "def _get_flatten_grads(model):\n", + " parameters = L(model.parameters())\n", + " grads = [param.grad.flatten().view(-1,1) for param in parameters if not type(param.grad) == type(None)]\n", + " grad = torch.cat(grads)\n", + " return grad " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The callback itself" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#export\n", + "class BSFinder(Callback):\n", + " \"A `Callback` that implements \\\"An Empirical Model of Large-Batch Training\\\" (https://arxiv.org/abs/1812.06162)\"\n", + " run_after=Recorder\n", + " \n", + " def __init__(self, num_it:int=None, n_batch=5, beta=0.99, simulate_multi_gpus=True): \n", + " store_attr(self, 'num_it, n_batch, beta, simulate_multi_gpus')\n", + "\n", + " def begin_fit(self):\n", + " # Save original model\n", + " self.learn.save('_tmp')\n", + " \n", + " if not self.num_it: self.num_it = len(self.dls.train) * (self.n_batch if self.simulate_multi_gpus else 1)\n", + " \n", + " self.running_scale = None\n", + " self.running_noise = None\n", + " \n", + " # Use python list instead L fastai list as torch.cat doesn't understand the former\n", + " self.stored_grads = []\n", + "\n", + " # Here, we will store the results\n", + " self.stats = L()\n", + " self.count=0\n", + "\n", + " def begin_validate(self): raise CancelValidException()\n", + " \n", + " def after_backward(self): \n", + " if self.train_iter >= self.num_it: raise CancelFitException()\n", + " \n", + " # Get gradients and store them\n", + " self.stored_grads.append(_get_flatten_grads(self.model))\n", + " \n", + " self.count += 1\n", + " if self.count != len(self.stored_grads):\n", + " breakpoint()\n", + "\n", + " if self.simulate_multi_gpus and len(self.stored_grads) < self.n_batch: \n", + " self.opt.zero_grad() # Zero gradients to avoid acumulate them between batches\n", + " #print('a', self.count, self.train_iter, learn.model.embeds[0].weight[0][:3].tolist())\n", + " raise CancelBatchException() #skip weight update\n", + " \n", + " if len(self.stored_grads) == self.n_batch: \n", + " self.count=0\n", + " #print('b', self.count, self.train_iter, learn.model.embeds[0].weight[0][:3].tolist())\n", + " # We have enough batches to compute Simple Noise Scale ratio.\n", + " \n", + " # We concatenate the batches and empty the buffer\n", + " stored_grads = torch.cat(self.stored_grads, dim=1)\n", + " self.stored_grads.clear()\n", + " \n", + " acc_grads = stored_grads.mean(dim = 1)\n", + " \n", + " # The original implementation uses .mean() although in the original article didn't do it. However, averaging g_big and g_small doesn't affect to noise_scale ratio \n", + " if self.simulate_multi_gpus: g_small = (stored_grads ** 2).sum(dim=0).mean() \n", + " else: g_small = (stored_grads[:,-1] ** 2).sum() # .mean()\n", + " \n", + " # print((stored_grads ** 2).sum(dim=0).mean().item(), (stored_grads[:,-1] ** 2).sum().item(), (stored_grads ** 2).sum(dim=0).tolist())\n", + " \n", + " g_big = (acc_grads ** 2).sum() # .mean()\n", + " \n", + " bs = find_bs(self.yb) # or self.dls.train.bs\n", + " b_small, b_big = bs, bs * self.n_batch\n", + " \n", + " noise = (b_big * g_big - b_small * g_small) / (b_big - b_small)\n", + " scale = (g_small - g_big) / ((1 / b_small) - (1 / b_big))\n", + "\n", + " self.running_scale, scale = _ema_with_debias(self.running_scale,self.beta,scale,self.iter)\n", + " self.running_noise, noise = _ema_with_debias(self.running_noise,self.beta,noise,self.iter)\n", + "\n", + " scale = scale.item()\n", + " noise = noise.item()\n", + " noise_scale = (scale / noise)\n", + " \n", + " # Save results\n", + " self.stats.append(dict(n_iter=(len(self.stats)) * (1 if self.simulate_multi_gpus else self.n_batch),\n", + " noise=noise, scale=scale, noise_scale=noise_scale))\n", + " \n", + " def after_fit(self):\n", + " if self.train_iter < self.num_it: warn(f\"Fitting was too short to complete all expectediterations. Please, increase the number of epochs\")\n", + " \n", + " tmp_f = self.path/self.model_dir/'_tmp.pth'\n", + " if tmp_f.exists():\n", + " self.learn.load('_tmp')\n", + " os.remove(tmp_f)\n", + " \n", + " if hasattr(self.learn, 'recorder'): \n", + " # index = pd.Index(torch.arange(1, len(self.stats)+1)*self.n_batch, name='n_iter')\n", + " df = pd.DataFrame(self.stats)#, index=index)\n", + " df.set_index('n_iter', inplace=True)\n", + " self.recorder.bs_find_stats = df\n", + " \n", + " _docs = {\"begin_fit\": \"Initialize container for search results and auxiliary variables and save the model\",\n", + " \"after_fit\": \"Record hyper-parameters of this batch and potentially stop training\",\n", + " \"after_backward\": \"Store gradients and compute Simple Noise Scale\",\n", + " \"begin_validate\": \"Skip the validation part of training\"}\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "add_docs(BSFinder, **BSFinder._docs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "

BSFinder.begin_fit[source]

\n", + "\n", + "> BSFinder.begin_fit()\n", + "\n", + "Initialize container for search results and auxiliary variables and save the model" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "show_doc(BSFinder.begin_fit)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "

BSFinder.after_fit[source]

\n", + "\n", + "> BSFinder.after_fit()\n", + "\n", + "Record hyper-parameters of this batch and potentially stop training" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "show_doc(BSFinder.after_fit)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "

BSFinder.after_backward[source]

\n", + "\n", + "> BSFinder.after_backward()\n", + "\n", + "Store gradients and compute Simple Noise Scale" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "show_doc(BSFinder.after_backward)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "

BSFinder.begin_validate[source]

\n", + "\n", + "> BSFinder.begin_validate()\n", + "\n", + "Skip the validation part of training" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "show_doc(BSFinder.begin_validate)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Methods for `Recorder` and `Learner` classes related to `BSFinder` callback. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#export\n", + "@patch\n", + "def plot_bs_find(self:Recorder):\n", + " \"Plot the result of an BS Finder test (won't work if you didn't do `learn.bs_find()` before)\"\n", + " fig, ax = plt.subplots(1,1)\n", + " stats = self.bs_find_stats\n", + " ax.plot(stats.index, stats.noise_scale)\n", + " ax.set_ylabel(\"Simple Noise Scale\")\n", + " ax.set_xlabel(\"# iteration\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#export\n", + "@delegates(BSFinder)\n", + "@patch\n", + "def bs_find(self:Learner, lr, num_it=None, n_batch=5, simulate_multi_gpus=True, show_plot=True, **kwargs):\n", + " \"\"\"\n", + " Launch a mock training to find a good batch size to minimaze training time. \n", + " However, it may not be a good batch size to minimize the validation loss. \n", + " \n", + " A good batch size is where the Simple Noise Scale converge ignoring the small growing trend \n", + " with the number of iterations if exists. The optimal batch size is about an order the magnitud\n", + " where Simple Noise scale converge. Typically, the optimial batch size in image classification \n", + " problems will be 2-3 times lower where \n", + " \"\"\" \n", + " num_it = num_it if num_it else len(self.dls.train)\n", + " num_it *= n_batch if simulate_multi_gpus else 1\n", + " n_epoch = num_it//len(self.dls.train)\n", + " cb=BSFinder(num_it=num_it, n_batch=n_batch, simulate_multi_gpus=simulate_multi_gpus, **kwargs)\n", + " with self.no_logging(): self.fit(n_epoch, lr, cbs=cb)\n", + " if show_plot: self.recorder.plot_bs_find()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "

class BSFinder[source]

\n", + "\n", + "> BSFinder(**`num_it`**:`int`=*`None`*, **`n_batch`**=*`5`*, **`beta`**=*`0.99`*, **`simulate_multi_gpus`**=*`True`*) :: [`Callback`](/callback.core#Callback)\n", + "\n", + "A [`Callback`](/callback.core#Callback) that implements \"An Empirical Model of Large-Batch Training\" (https://arxiv.org/abs/1812.06162)" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "show_doc(BSFinder)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`num_it` is the number of batches you want to process. It can be set to `None` and it will automatically train during one epoch (or `n_batch` if `simulate_multi_gpus` is set to `True`). `n_batch` is the number of batches you want to store before computing the Simple Noise Scale. 5 to 20 seems to work well across different tasks.\n", + "\n", + "`beta` is the beta parameter for an exponential moving average to compute the sum of variances, and the scale of the gradient. If the plot is too irregular, try increasing to 0.999 or more if needed, or increase the `n_batch` parameter.\n", + "\n", + "`simulate_multi_gpus` controls if multi GPU setup is simulated with `n_batch` gpus to match with the original research paper implementation. The multi GPU setup is done by running `n_batch` batches without updating the model weights. Setting it to `False` use [DanyWind aproximation](https://towardsdatascience.com/implementing-a-batch-size-finder-in-fastai-how-to-get-a-4x-speedup-with-better-generalization-813d686f6bdf). It's faster but numerically more inestable and finds a Simple Noise Scale smaller than the original Simple Noise Scale. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ¿How to select a good the batch size with `BSFinder` to speed up the training?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "1. First, let's quickly create the `dls` where we can use a very big batch size. Here, it doesn't matter which batch size we use\n", + "2. Second, find a good learning rate with `Learner.lr_find`.\n", + "3. Third, find a good batch size with `Learner.bs_find`. **Remember** that this batch size is optimized for training speed but **not** necessarily to minimaze validation error. Regardless, it gives you a reference to the max batch size to use.\n", + "4. Fourth, recreate `dls` with the batch size\n", + "5. Fifth, find again a good learning rate with `Learner.lr_find` as usually the best lr depends on the batch size. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from fastai2.tabular.all import *" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create the `dls`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "path = untar_data(URLs.ADULT_SAMPLE)\n", + "df = pd.read_csv(path/'adult.csv')\n", + "\n", + "cat_names = ['workclass', 'education', 'marital-status', 'occupation', 'relationship', 'race']\n", + "cont_names = ['age', 'fnlwgt', 'education-num']\n", + "\n", + "procs = [Categorify, FillMissing, Normalize]\n", + "y_names = 'salary'\n", + "y_block = CategoryBlock()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "to = TabularPandas(df, procs=procs, cat_names=cat_names, cont_names=cont_names,\n", + " y_names=y_names, y_block=CategoryBlock(), splits=RandomSplitter()(range_of(df)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "dls = to.dataloaders()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
workclasseducationmarital-statusoccupationrelationshipraceeducation-num_naagefnlwgteducation-numsalary
0Federal-govSome-collegeMarried-civ-spouseAdm-clericalHusbandWhiteFalse61.000000136786.99969110.0>=50k
1PrivateHS-gradWidowedOther-serviceUnmarriedWhiteFalse42.000000153160.0012839.0<50k
2State-govBachelorsMarried-civ-spouseExec-managerialHusbandWhiteFalse44.000000175696.00041113.0>=50k
3PrivateBachelorsSeparatedAdm-clericalUnmarriedBlackFalse40.000000289403.00207113.0<50k
4PrivateBachelorsDivorcedProf-specialtyUnmarriedWhiteFalse54.99999980167.00411113.0<50k
5Private7th-8thMarried-civ-spouseCraft-repairHusbandWhiteFalse25.000000294400.0022684.0<50k
6PrivateHS-gradMarried-civ-spouseHandlers-cleanersHusbandBlackFalse43.000000477983.0074149.0<50k
7PrivateMastersNever-marriedProf-specialtyNot-in-familyWhiteFalse30.000000426431.00660614.0>=50k
8Local-govMastersMarried-civ-spouseProf-specialtyHusbandWhiteFalse51.000000108435.00061914.0>=50k
9PrivateSome-collegeNever-marriedSalesOwn-childWhiteFalse19.000001389142.99869910.0<50k
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "dls.show_batch()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The default batch size is:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "64" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dls.bs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Find a good learning rate" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "learn = tabular_learner(dls, [200,100], metrics=accuracy)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [], + "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.lr_find(show_plot=False)\n", + "learn.recorder.plot_lr_find(skip_end=10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Find a good batch size." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [], + "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.bs_find(1e-3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also access in the recorder with `Learner.recorder.plot_bs_find()` or access to the raw stats with `Learner.recorder.bs_find_stats`. Here we only show the first rows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
noisescalenoise_scale
n_iter
00.96715295.02965598.257166
10.74873095.985123128.197203
20.67157485.072830126.676711
30.56401684.955147150.625408
40.49414186.296661174.639852
\n", + "
" + ], + "text/plain": [ + " noise scale noise_scale\n", + "n_iter \n", + "0 0.967152 95.029655 98.257166\n", + "1 0.748730 95.985123 128.197203\n", + "2 0.671574 85.072830 126.676711\n", + "3 0.564016 84.955147 150.625408\n", + "4 0.494141 86.296661 174.639852" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "learn.recorder.bs_find_stats.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A good batch size is were Simple Noise Scale converge. It's expected to exist a small growing trend with the number of iterations. In case that Simple Noise Scale doesn't converge, try to increase `n_batch`. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this case, Simple Noise Scale has converged around 2000 or 2500. So a good batch size will be 2048 as they are powers of 2. Again, remember that this batch size is optimized for training speed but **not** to necessarily minimaze validation error. So, it gives you a reference to the max batch size to use." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we recreate the dataloaders with the good batch size." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "learn.dls = to.dataloaders(bs=2048)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Lastly, find a good learning rate for this batch size." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "SuggestedLRs(lr_min=0.025118863582611083, lr_steep=0.0030199517495930195)" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "learn.lr_find()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "See some comparisons in the training speed. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
epochtrain_lossvalid_lossaccuracytime
00.5583740.6251990.76658500:00
10.4628990.5169870.77641300:00
20.4196760.4673840.79453300:00
30.3965230.4390860.81019700:00
40.3829780.4112330.82616700:00
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "learn.fit_one_cycle(5, 1e-3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the optimized batch size, training is almost instantaneous." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In contrast, with default batch size:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
epochtrain_lossvalid_lossaccuracytime
00.3696080.3584640.83369200:04
10.3472420.3586080.83507400:04
20.3479590.3518340.83922000:04
30.3430890.3469790.84229100:04
40.3331520.3471570.84213800:04
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "learn.dls = dls\n", + "learn.fit_one_cycle(5, 1e-3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have an infinite speed increase :D" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Just remember, this batch size is optimized for training speed but may not minimaze the validation error. Regardless, it gives you a reference to the max batch size to use." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}