{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Lesson 1 - What's your pet" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Welcome to lesson 1! For those of you who are using a Jupyter Notebook for the first time, you can learn about this useful tool in a tutorial we prepared specially for you; click `File`->`Open` now and click `notebook_tutorial.ipynb`. \n", "\n", "In this lesson we will build our first image classifier from scratch, and see if we can achieve world-class results. Let's dive in!\n", "\n", "Every notebook starts with the following three lines; they ensure that any edits to libraries you make are reloaded here automatically, and also that any charts or images displayed are shown in this notebook." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%reload_ext autoreload\n", "%autoreload 2\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We import all the necessary packages. We are going to work with the [fastai V1 library](http://www.fast.ai/2018/10/02/fastai-ai/) which sits on top of [Pytorch 1.0](https://hackernoon.com/pytorch-1-0-468332ba5163). The fastai library provides many useful functions that enable us to quickly and easily build neural networks and train our models." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from fastai import *\n", "from fastai.vision import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Looking at the data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We are going to use the [Oxford-IIIT Pet Dataset](http://www.robots.ox.ac.uk/~vgg/data/pets/) by [O. M. Parkhi et al., 2012](http://www.robots.ox.ac.uk/~vgg/publications/2012/parkhi12a/parkhi12a.pdf) which features 12 cat breeds and 25 dogs breeds. Our model will need to learn to differentiate between these 37 distinct categories. According to their paper, the best accuracy they could get in 2012 was 59.21%, using a complex model that was specific to pet detection, with separate \"Image\", \"Head\", and \"Body\" models for the pet photos. Let's see how accurate we can be using deep learning!\n", "\n", "We are going to use the `untar_data` function to which we must pass a URL as an argument and which will download and extract the data." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "help(untar_data)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# DEBUG\n", "URLs.PETS" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "path = untar_data(URLs.PETS)\n", "path" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "path.ls()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "path_anno = path / 'annotations'\n", "path_img = path / 'images'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first thing we do when we approach a problem is to take a look at the data. We _always_ need to understand very well what the problem is and what the data looks like before we can figure out how to solve it. Taking a look at the data means understanding how the data directories are structured, what the labels are and what some sample images look like.\n", "\n", "The main difference between the handling of image classification datasets is the way labels are stored. In this particular dataset, labels are stored in the filenames themselves. We will need to extract them to be able to classify the images into the correct categories. Fortunately, the fastai library has a handy function made exactly for this, `ImageDataBunch.from_name_re` gets the labels from the filenames using a [regular expression](https://docs.python.org/3.6/library/re.html)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# DEBUG\n", "path_anno, path_img" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fnames = get_image_files(path_img)\n", "fnames[:5]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.random.seed(2)\n", "pat = r'/([^/]+)_\\d+.jpg$'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "data = ImageDataBunch.from_name_re(path_img, fnames, pat, ds_tfms=get_transforms(), size=224)\n", "data.normalize(imagenet_stats)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "data.show_batch(rows=3, figsize=(7,6))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(data.classes)\n", "len(data.classes), data.c # the number of classes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Training: resnet34" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we will start training our model. We will use a [convolutional neural network](http://cs231n.github.io/convolutional-networks/) backbone and a fully connected head with a single hidden layer as a classifier. Don't know what these things mean? Not to worry, we will dive deeper in the coming lessons. For the moment you need to know that we are building a model which will take images as input and will output the predicted probability for each of the categories (in this case, it will have 37 ouptuts).\n", "\n", "We will train for 5 epochs (5 cycles through all our data)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learn = ConvLearner(data, models.resnet34, metrics=error_rate)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learn.fit_one_cycle(4)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learn.save('stage-1')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Results" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's see what results we have got. \n", "\n", "We will first see which were the categories that the model most confused with one another. We will try to see if what the model predicted was reasonable or not. In this case the mistakes look reasonable (none of the mistakes seems obviously naive). This is an indicator that our classifier is working correctly. \n", "\n", "Furthermore, when we plot the confusion matrix, we can see that the distribution is heavily skewed: the model makes the same mistakes over and over again but it rarely confuses other categories. This suggests that it just finds it difficult to distinguish some specific categories between each other; this is normal behaviour." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "interp = ClassificationInterpretation.from_learner(learn)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "interp.plot_top_losses(9, figsize=(15,11))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "doc(interp.plot_top_losses)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "interp.plot_confusion_matrix(figsize=(12,12), dpi=60)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "interp.most_confused(min_val=2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Unfreezing, fine-tuning, and learning rates" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since our model is working as we expect it to, we will *unfreeze* our model and train some more." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learn.unfreeze()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learn.fit_one_cycle(1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learn.load('stage-1')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "learn.lr_find()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Fix the previous error by updating fastai library to the latest version today**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learn.lr_find()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learn.recorder.plot()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learn.unfreeze()\n", "learn.fit_one_cycle(2, max_lr=slice(1e-6, 1e-4))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "doc(learn.fit_one_cycle)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learn.recorder.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That's a pretty accurate model!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Training: resnet50" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we will train in the same way as before but with one caveat: instead of using resnet34 as our backbone we will use resnet50 (resnet34 is a 34 layer residual network while resnet50 has 50 layers. Later in the course you can learn the details in the [resnet paper](https://arxiv.org/pdf/1512.03385.pdf)).\n", "\n", "Basically, resnet50 usually performs better because it is a deeper network with more parameters. Let's see if we can achieve a higher performance here." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "data = ImageDataBunch.from_name_re(path_img, fnames, pat, ds_tfms=get_transforms(), size=299, bs=48)\n", "data.normalize(imagenet_stats)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learn = ConvLearner(data, models.resnet50, metrics=error_rate)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(HBox(children=(IntProgress(value=0, max=5), HTML(value='0.00% [0/5 00:00<00:00]'))), HTML(value…" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Total time: 17:07\n", "epoch train loss valid loss error_rate\n", "1 0.641380 0.236811 0.068556 (03:56)\n", "2 0.341766 0.211440 0.069875 (03:18)\n", "3 0.242888 0.207498 0.069875 (03:17)\n", "4 0.159888 0.167932 0.054054 (03:17)\n", "5 0.107927 0.163711 0.050758 (03:17)\n", "\n" ] } ], "source": [ "learn.fit_one_cycle(5)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "learn.save('stage-1-50')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It's astonishing that it's possible to recognize pet breeds so accurately! Let's see if full fine-tuning helps:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "scrolled": false }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(HBox(children=(IntProgress(value=0, max=1), HTML(value='0.00% [0/1 00:00<00:00]'))), HTML(value…" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Total time: 04:24\n", "epoch train loss valid loss error_rate\n", "1 0.103458 0.155929 0.051417 (04:24)\n", "\n" ] } ], "source": [ "learn.unfreeze()\n", "learn.fit_one_cycle(1, max_lr=slice(1e-6,1e-4))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this case it doesn't, so let's go back to our previous model." ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": [ "learn.load('stage-1-50')" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "HBox(children=(IntProgress(value=0, max=16), HTML(value='')))" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "HBox(children=(IntProgress(value=0, max=16), HTML(value='0.00% [0/16 00:00<00:00]')))" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "interp = ClassificationInterpretation.from_learner(learn)" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('Egyptian_Mau', 'Bengal', 7),\n", " ('american_bulldog', 'staffordshire_bull_terrier', 4),\n", " ('staffordshire_bull_terrier', 'american_bulldog', 4),\n", " ('boxer', 'american_bulldog', 4),\n", " ('Russian_Blue', 'British_Shorthair', 4),\n", " ('american_pit_bull_terrier', 'staffordshire_bull_terrier', 4),\n", " ('Ragdoll', 'Birman', 3)]" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "interp.most_confused(min_val=2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Other data formats" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Downloading http://files.fast.ai/data/examples/mnist_sample\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "e2eca45b5e3a4a01820ba9cd24f7a0fa", "version_major": 2, "version_minor": 0 }, "text/plain": [ "HBox(children=(IntProgress(value=0, max=3214948), HTML(value='')))" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "PosixPath('/home/ubuntu/.fastai/data/mnist_sample')" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "path = untar_data(URLs.MNIST_SAMPLE)\n", "path" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": [ "tfms = get_transforms(do_flip=False)\n", "data = ImageDataBunch.from_folder(path, ds_tfms=tfms, size=26)" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "image/png": "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jktftWpVG+NtAN8HAADefffdhL9XftCKVAghAikRK9JU07p1awDAiBEjbOzaa681zb0Rufchb0T7DfEJEybYGJedifzjV+6cJ/h///d/pjds2GCaVyt+hfL111/bWLIVKXcwShQwzGY4D5N7gfrSXF7Bc2/ejRs3muaV5VdffQUg3gd027ZtprlPKa9OOZiUG3PmzEl4/b5ElPNMuQw41YFhrUiFECIQGVIhhAikRPs23tXgBrB87AgfT8D5ZN61v+yyy2yMN6XZ/WM4aOTdfH6t35QH4rlpXKIocodLe717CMS79HATbb/9wg2+GXbp+DgYPiFW5DRDBuLPkc+55MbI7M6/8847pp977rlz3pfdaH5eeKusoPmbHIxs2bKl6USlqvwcpvqZ1IpUCCECkSEVQohASrRr708X5ebK3Mj16quvNs3uhS9v4zHO+0wGRy2bN28OABg8eLCNtW/f3jR3kOJm07t37871c7KdvLhdnNPro7W33367jbGruHDhwoSam4SLOImeB4648xYJf9cTwdswqaZdu3amubTbb1PwdgRnD7BOBVqRCiFEIDKkQggRSIl27X0EkKO1rVq1Ms3uHUdufcIvu3b8Hnw2kN8+AOLujj+H5pZbbrGxw4cPm+YzhVj7BGLuYiXyBm+tcITWF1ZwEj7PFX8POEGb5zbRcd3ZBhc8jB8/3rR3k1evXm1jXA7NLn9hwcUTPIfcEYzPlPIZNpz0zwUzXPSRCrQiFUKIQGRIhRAiEFeUnYmccyn9MO/q+eNigbjLx8t+rsP1HWrWr19vY+zas+bocCL3v1evXjbG3XM48XjTpk2m33vvPQDAM888Y2Nct3zmzJnc0weKCamez9zgc4Ieeugh04888giAeGNfdu25+xA3c16+fLnp7du3A4hvuaxYsSL4mqMoKjHzWalSJZvP7t2727h3pfnesJtfFNsinHh/9913m37wwQdN87HP3jZwZ6fnn3/eNGcd5Idk86kVqRBCBFKig02+6w8HjXiVwWVsvPL2QaG85LfxkQRcAupL0JYsWWJjnTp1Ms39TblP4rBhwwDE+5iyFsnp3bu36dtuu820zwvmPpU831z+y3m/gwYNMu3ze99//30b27Vrl+lsKCfl/N2PP/44jVfyIxxc5GevS5cuprk8nF+/ZcsWAMDs2bNtjINpqUYrUiGECESGVAgh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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "data.show_batch(rows=3, figsize=(5,5))" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(HBox(children=(IntProgress(value=0, max=2), HTML(value='0.00% [0/2 00:00<00:00]'))), HTML(value…" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Total time: 00:23\n", "epoch train loss valid loss accuracy\n", "1 0.114837 0.023115 0.993621 (00:12)\n", "2 0.067166 0.014504 0.995584 (00:10)\n", "\n" ] } ], "source": [ "learn = ConvLearner(data, models.resnet18, metrics=accuracy)\n", "learn.fit(2)" ] }, { "cell_type": "code", "execution_count": 45, "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", "
namelabel
0train/3/7463.png0
1train/3/21102.png0
2train/3/31559.png0
3train/3/46882.png0
4train/3/26209.png0
\n", "
" ], "text/plain": [ " name label\n", "0 train/3/7463.png 0\n", "1 train/3/21102.png 0\n", "2 train/3/31559.png 0\n", "3 train/3/46882.png 0\n", "4 train/3/26209.png 0" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.read_csv(path / 'labels.csv')\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "data = ImageDataBunch.from_csv(path, ds_tfms=tfms, size=28)" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1]" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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r+17boiWfj/tkRYUU/KTTjrJY3vttRcAO+20k8fiYy57FNapUyePffPNNwC8/PLLHnv99de9bY/raku57XHBpptu6rFddtkFyD/yGTBggLd33nnnGt/zmmuuAWDixIke05lNIiJNpCInm+JoIn7iXXrppUB+UsFGMHFSarvttvO2fdLFB9Q22oijjlLt+HPiaGXt2rU1vqf9/Llz53qsPg+pJc9GMJdddpnH+vbt6+14T0yp0WcpcYKqd+/e3radNjEr0cRT/cTf6RFHHJH7E4r3K/5ux48f7+133nkHgGOPPdZjtjvwsMMO85jtHAQ45JBDAFi0aJHH4vvf7mecsLRJ6Tgyjhmnvb/jaDlmMHXRiFREJJE6UhGRRBWZ2kdxyL755pvXiJWycOFCb9v6s1WrVnnMJoniA+5ly5Z521KGjz/+2GNxyG8THvGhul3b4sWLPWaPAGT94sSRpfGx+MvGG29c49/EtcL33XcfUKwJC3DGGWd423agde/evXEuWFx8jdv75vnnn/eYFSuZMWOGx/71r3952+5jTNNtR+CQIUM8FtNwa8dHPrEoirXrejwT+4QJEyYAcP/993ts3rx56/33kUakIiKJ1JGKiCSqyNQ+1ivcZ599vF1qdtaG7zb7B/nU4bnnngPya0utTmhM7T/88ENvL1iwAMin+9FFF10EFLeKRnPmzCn5b6R2cXb2rLPOAvL3JrKZ1Ljd88477wTg/fff95itRYTi6yausoizyPXdMiw1xfeVbemcOnWqx+x3/+KLL3ps+fLlNb7PQw895G17PBa/9x577OHtmMabuC3VtnbH/sL6iVhIKKbxN9xwA5BfafPVV1/V+Dm10YhURCRRRY5IY8mt008/3dulPons0+3ee+/1mI1QoDi6TD10Lla7t8mm9u3be8w+8WKhBVk/yzzOOeccjx199NE1/l6cNLj55psBuPHGGz1ma3fjLrhYUMZeTzHreOKJJ7wdRz7SMHGEN3369A3+PnGdtu1ciruZ+vfv721bHxrfkz//+c+9bTsKY6Zh9/i1117z2CWXXFLj6xtKI1IRkUTqSEVEElVkah8LVsRalCZOJNhkUpxgirULG4ttXYRi4YO4vvG9994D8mvTpKb4OMRS+pi22eObuD7RCs9AcZIpTizZ97RHLpCveWnrVJ988kmP/fOf/0z4X0hTKjUxFGv7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cOFCAHr27OmxPffcs8bfnTRpksceeughAN566y2PrVu3rsH/j0KhkNX9typDfe/nRhsVP6/jvfn2228BWLt2bSNfWeVoifezNavtfmpEKiKSSB2piEiiZl1H2hSpw6abbgoUU3jIp+z9+vUD4IgjjvDYXnvtBcAOO+zgsXbt2nl78eLFAGy//fYe23bbbb3dtu13T0TsEQDArFmzAJg2bZrH7r//fm+/8847QN3pfrWngjF1N3aPALp27ertXXfdFYDPPvvMY2vWrAGgTZs2Hott+7vvvfeex5YtW9bga28u1X4/K0V8PGRtex9C/jVij/ni477YNvZoCeDrr78G4KuvvvJYqb5Rqb2ISBOpyhFpHD3aiPOPf/yjx3r06OFtG6nGkZJ9epX6lEoVR0c33nijt2+44QYA3n///fX++2odwdjvcpdddvGvd+zYESjeI4DDDz/c25tvvjkAn376qcesvc0223jsgAMO8LZlBjEbsAzi3Xff9diSJUu8/cYbbwAwe/Zsjy1fvryu/16jqNb7WU6WwcSMsU+fPt627HLw4MEe23nnnb29vhFpvO+WRQJMnjwZgLvvvttjH330UY1r04hURKSJqCMVEUlUlYffxTWdw4cPB/JD/zhJFB9IN4ett97a26NHj/b2U089BcCHH37osfiwuxrFCQBLw8aMGVMjZpN7kE/zLYWL98gm47744guPffPNN97+/PPPAejUqZPHbNIqPlaIad2jjz4KwNVXX+2xJ598so7/nTQnW9sNMGrUKACOO+44j+20007etntvj44gP6G5PltttZW3d9xxR2/vt99+ACxatMhjzz77LAArVqyo8/tqRCoikqiqRqQ2SRQnk+xTK44Em3sUGsVlGHGE1L17dwCmTp3a7NfUHGwkGUcJ/fv3B/ITAXEXkz34j8ufZs78ruzk6tXFkyXi6NLitlwFihlK/H3H0X7v3r2BfIYQaXRafp07d/b2oYceCuQnJjfeeOMa/yYuVfrggw+8bRONCxYs8Ji9xuLrM+52tD7FRsPxe77wwgt1Xr9GpCIiidSRiogkqvjUPqZ1tu4wrjHs1q0bUHroH8X1staO6V9MOVeu/O402E8++cRjMY2wFDI+uLZ1qvF6Y5pvE2BNsXa1XOLvz35n48eP99ibb74J5HedxXW0lqbHdcEff/wxkF+PG3/3S5cuBfK/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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "data.show_batch(rows=3, figsize=(5,5))\n", "data.classes" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1]" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data = ImageDataBunch.from_df(path, df, ds_tfms=tfms, size=24)\n", "data.classes" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[PosixPath('/home/ubuntu/.fastai/data/mnist_sample/train/3/7463.png'),\n", " PosixPath('/home/ubuntu/.fastai/data/mnist_sample/train/3/21102.png')]" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fn_paths = [path / name for name in df['name']]; fn_paths[:2]" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['3', '7']" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pat = r\"/(\\d)/\\d+\\.png$\"\n", "data = ImageDataBunch.from_name_re(path, fn_paths, pat=pat, ds_tfms=tfms, size=24)\n", "data.classes" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['3', '7']" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data = ImageDataBunch.from_name_func(path, fn_paths, ds_tfms=tfms, size=24,\n", " label_func = lambda x: '3' if '/3/' in str(x) else '7')\n", "data.classes" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['3', '3', '3', '3', '3']" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "labels = [('3' if '/3/' in str(x) else '7') for x in fn_paths]\n", "labels[:5]" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['3', '7']" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data = ImageDataBunch.from_lists(path, fn_paths, labels=labels, ds_tfms=tfms, size=24)\n", "data.classes" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.6" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": false, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }