{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# MNİST Classification With FASTAİ","metadata":{}},{"cell_type":"markdown","source":"First, we need to install the Fastbook library and import it with other necessary libraries.","metadata":{}},{"cell_type":"code","source":"!pip install -Uqq fastbook\nfrom fastai.vision.all import *\nfrom fastbook import *\nimport torch","metadata":{"execution":{"iopub.status.busy":"2021-06-05T18:17:29.487475Z","iopub.execute_input":"2021-06-05T18:17:29.488226Z","iopub.status.idle":"2021-06-05T18:17:45.021262Z","shell.execute_reply.started":"2021-06-05T18:17:29.488103Z","shell.execute_reply":"2021-06-05T18:17:45.020411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"And then, we need to get pathway to our MNIST data with `untar_data()`","metadata":{}},{"cell_type":"code","source":"path = untar_data(URLs.MNIST)\nprint(path)","metadata":{"execution":{"iopub.status.busy":"2021-06-05T18:17:45.022786Z","iopub.execute_input":"2021-06-05T18:17:45.023139Z","iopub.status.idle":"2021-06-05T18:18:02.853660Z","shell.execute_reply.started":"2021-06-05T18:17:45.023094Z","shell.execute_reply":"2021-06-05T18:18:02.852807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's check what do we have in this path.","metadata":{}},{"cell_type":"code","source":"path.ls()","metadata":{"execution":{"iopub.status.busy":"2021-06-05T18:18:02.855366Z","iopub.execute_input":"2021-06-05T18:18:02.855607Z","iopub.status.idle":"2021-06-05T18:18:02.865620Z","shell.execute_reply.started":"2021-06-05T18:18:02.855582Z","shell.execute_reply":"2021-06-05T18:18:02.864905Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As we can see there are two folders in this path. Training and testing folders. And since we want to use training folder for both training and validation, we will set our base path like this:","metadata":{}},{"cell_type":"code","source":"Path.base = path/'training'","metadata":{"execution":{"iopub.status.busy":"2021-06-05T18:18:02.869162Z","iopub.execute_input":"2021-06-05T18:18:02.869733Z","iopub.status.idle":"2021-06-05T18:18:03.065354Z","shell.execute_reply.started":"2021-06-05T18:18:02.869697Z","shell.execute_reply":"2021-06-05T18:18:03.064356Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's check what we have in our base path.","metadata":{}},{"cell_type":"code","source":"Path.base.ls()","metadata":{"execution":{"iopub.status.busy":"2021-06-05T18:18:03.066496Z","iopub.execute_input":"2021-06-05T18:18:03.068260Z","iopub.status.idle":"2021-06-05T18:18:03.075362Z","shell.execute_reply.started":"2021-06-05T18:18:03.068222Z","shell.execute_reply":"2021-06-05T18:18:03.074319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"You can see we have subfolders representing all digits from **0-9**. And we have images of handwritten digits in these folders. Now, we'll load our data and we also want to separate our dataset into two parts; **_Training_** and **_Validation_**. To do that, we set the `valid_pct` parameter to **0.2**. And this will set **80%** of the data as a training set and **20%** of the data as a validation set. And we set the seed to 10, which is an arbitrary number so that every time we separate the data we can get the same sets.","metadata":{}},{"cell_type":"code","source":"data = ImageDataLoaders.from_folder(path, valid_pct = 0.2, seed = 10, bs = 64)","metadata":{"execution":{"iopub.status.busy":"2021-06-05T18:18:03.076593Z","iopub.execute_input":"2021-06-05T18:18:03.077080Z","iopub.status.idle":"2021-06-05T18:18:12.938430Z","shell.execute_reply.started":"2021-06-05T18:18:03.077029Z","shell.execute_reply":"2021-06-05T18:18:12.937487Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Fastai's `ImageDataLoaders` also loads the data in batches and by default all batches have 64 items(images). Let's see some images in one of those batches with `show_batch()` method","metadata":{}},{"cell_type":"code","source":"data.show_batch()","metadata":{"execution":{"iopub.status.busy":"2021-06-05T18:18:12.939728Z","iopub.execute_input":"2021-06-05T18:18:12.940052Z","iopub.status.idle":"2021-06-05T18:18:13.666971Z","shell.execute_reply.started":"2021-06-05T18:18:12.940017Z","shell.execute_reply":"2021-06-05T18:18:13.666033Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now, we loaded our data and we're ready to train our Convolutional Neural Network. We'll use **_ResNet34_**, which is a very famous pre-trained model, and accuracy metric for evaluation.","metadata":{}},{"cell_type":"markdown","source":"And we will fine_tune our model for **2** epochs and use learning rate $10^{-3}$","metadata":{}},{"cell_type":"code","source":"learn = cnn_learner(data, resnet34, metrics=accuracy)\nlearn.fine_tune(2, base_lr = 1e-3)","metadata":{"execution":{"iopub.status.busy":"2021-06-05T18:18:13.670638Z","iopub.execute_input":"2021-06-05T18:18:13.670984Z","iopub.status.idle":"2021-06-05T18:24:58.489691Z","shell.execute_reply.started":"2021-06-05T18:18:13.670948Z","shell.execute_reply":"2021-06-05T18:24:58.488824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Let's check if our model overfits.","metadata":{}},{"cell_type":"code","source":"learn.recorder.plot_loss()","metadata":{"execution":{"iopub.status.busy":"2021-06-05T18:24:58.493355Z","iopub.execute_input":"2021-06-05T18:24:58.493614Z","iopub.status.idle":"2021-06-05T18:24:58.674435Z","shell.execute_reply.started":"2021-06-05T18:24:58.493582Z","shell.execute_reply":"2021-06-05T18:24:58.673642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"And to investigate our model in detail we can get a confusion matrix.","metadata":{}},{"cell_type":"code","source":"interp = ClassificationInterpretation.from_learner(learn)\ninterp.plot_confusion_matrix(figsize=(12,12), dpi=60)","metadata":{"execution":{"iopub.status.busy":"2021-06-05T18:24:58.675750Z","iopub.execute_input":"2021-06-05T18:24:58.676018Z","iopub.status.idle":"2021-06-05T18:25:15.788050Z","shell.execute_reply.started":"2021-06-05T18:24:58.675993Z","shell.execute_reply":"2021-06-05T18:25:15.787211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"And using `plot_top_losses` method we can investigate our models' distortions","metadata":{}},{"cell_type":"code","source":"interp.plot_top_losses(6, nrows=1)","metadata":{"execution":{"iopub.status.busy":"2021-06-05T18:25:15.789549Z","iopub.execute_input":"2021-06-05T18:25:15.790150Z","iopub.status.idle":"2021-06-05T18:25:16.060321Z","shell.execute_reply.started":"2021-06-05T18:25:15.790106Z","shell.execute_reply":"2021-06-05T18:25:16.059304Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Finally, let's use an image from our test folder to see if our model can predict.","metadata":{}},{"cell_type":"code","source":"learn.predict(path/'testing/8/179.png')","metadata":{"execution":{"iopub.status.busy":"2021-06-05T18:25:16.061656Z","iopub.execute_input":"2021-06-05T18:25:16.062024Z","iopub.status.idle":"2021-06-05T18:25:16.136957Z","shell.execute_reply.started":"2021-06-05T18:25:16.061984Z","shell.execute_reply":"2021-06-05T18:25:16.135979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}