{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"!pip install pretrainedmodels","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"from PIL import Image\nimport shutil\n\nimport numpy as np\nimport matplotlib.pyplot as plot\nimport pandas as pd\n\nimport torch\nimport fastai\nfrom fastai import vision\n\nimport pretrainedmodels as pm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def set_seed(seed):\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    torch.backends.cudnn.deterministic = True\n\nset_seed(42)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Creating Pseudo-Labels for the Extra Images"},{"metadata":{"trusted":true},"cell_type":"code","source":"transform_kwargs = {\"do_flip\": True,\n                    \"flip_vert\": True,\n                    \"max_rotate\": 180,\n                    \"max_zoom\": 1.1,\n                    \"max_lighting\": 0.2,\n                    \"max_warp\": 0.2,\n                    \"p_affine\": 0.75,\n                    \"p_lighting\": 0.7}\n        \ntransforms = vision.get_transforms(**transform_kwargs)\n\ndata_bunch_kwargs = {\"path\": \"../input/cassava-disease/train\",\n                     \"train\": \"train\",\n                     \"valid_pct\": 0.1,\n                     \"size\": 448,\n                     \"bs\": 16,\n                     \"ds_tfms\": transforms,\n                     \"test\": \"../extraimages/extraimages\"}\n\nimage_data_bunch = (vision.ImageDataBunch\n                          .from_folder(**data_bunch_kwargs)\n                          .normalize())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"shutil.copytree(\"../input/cassava-disease-classification/models/\", \"./models\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Use our pretrained model to predict the labels for our extra images"},{"metadata":{"trusted":true},"cell_type":"code","source":"_base_arch = lambda arg: pm.se_resnext101_32x4d(num_classes=5, pretrained=None)\nlearner = vision.cnn_learner(image_data_bunch, base_arch=_base_arch, pretrained=False, metrics=vision.error_rate, model_dir=\"/kaggle/working/models/se-resnext101-32x4d\")\n_ = learner.load(\"best-model-stage-2\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predicted_probabilities, _ = learner.TTA(ds_type=fastai.basic_data.DatasetType.Test)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predicted_class_probabilities, _predicted_classes = predicted_probabilities.max(dim=1)\nclass_labels = np.array(['cbb','cbsd','cgm','cmd','healthy'])\npredicted_class_labels = class_labels[_predicted_classes]\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Creating a new training data set\n\nOnce we have the pseudo-labels and predicted probabilities that these pseudo-labels are correct we need to decide which of the extra images we want to include in our new, larger training data set. Basic idea is to choose a decision threshold and then only include the extra images where our original model was highly confident in the predicted pseduo-label."},{"metadata":{"trusted":true},"cell_type":"code","source":"shutil.copytree(\"../input/cassava-disease/train/train/\", \"./data/train\")\nshutil.copytree(\"../input/cassava-disease/test/test/\", \"./data/test\")\n\nthreshold = 0.95  # only include pseudo-labeled images where model is sufficiently confident in its prediction\nfilenames = [item.name for item in learner.data.test_ds.items]\nfor predicted_class_label, predicted_class_probability, filename in zip(predicted_class_labels, predicted_class_probabilities, filenames):\n    if predicted_class_probability > threshold:\n        shutil.copy(f\"../input/cassava-disease/extraimages/extraimages/{filename}\", f\"./data/train/{predicted_class_label}/{filename}\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"transform_kwargs = {\"do_flip\": True,\n                    \"flip_vert\": True,\n                    \"max_rotate\": 180,\n                    \"max_zoom\": 1.1,\n                    \"max_lighting\": 0.2,\n                    \"max_warp\": 0.2,\n                    \"p_affine\": 0.75,\n                    \"p_lighting\": 0.7}\n        \ntransforms = vision.get_transforms(**transform_kwargs)\n\ndata_bunch_kwargs = {\"path\": \"./data/train\",\n                     \"train\": \"train\",\n                     \"valid_pct\": 0.1,\n                     \"size\": 448,\n                     \"bs\": 16,\n                     \"ds_tfms\": transforms,\n                     \"test\": \"../test\"}\n\nimage_data_bunch = (vision.ImageDataBunch\n                          .from_folder(**data_bunch_kwargs)\n                          .normalize())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Train the model on new training data set"},{"metadata":{"trusted":true},"cell_type":"code","source":"_base_arch = lambda arg: pm.se_resnext101_32x4d(num_classes=5, pretrained=None)\nlearner = vision.cnn_learner(image_data_bunch, base_arch=_base_arch, pretrained=False, metrics=vision.error_rate, model_dir=\"/kaggle/working/models/se-resnext101-32x4d\")\n_ = learner.load(\"best-model-stage-2\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learner.lr_find()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"(learner.recorder\n        .plot())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"_save_model_kwargs = {\"every\": \"improvement\",\n                      \"monitor\": \"valid_loss\",\n                      \"name\": \"best-model-stage-3\"}\n_save_model = (fastai.callbacks\n                     .SaveModelCallback(learner, **_save_model_kwargs))\nlearner.fit_one_cycle(15, max_lr=slice(None, 1e-6, None), callbacks=[_save_model])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Make predictions using TTA"},{"metadata":{"trusted":true},"cell_type":"code","source":"predicted_probabilities, _ = learner.TTA(ds_type=fastai.basic_data.DatasetType.Test)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Create a submission"},{"metadata":{"trusted":true},"cell_type":"code","source":"_, _predicted_classes = predicted_probabilities.max(dim=1)\n_predicted_class_labels = class_labels[_predicted_classes]\n\n_filenames = np.array([item.name for item in image_data_bunch.test_ds.items])\n\nsubmission = (pd.DataFrame\n                .from_dict({'Category': _predicted_class_labels,'Id': _filenames}))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission.to_csv('submission-using-pseudo-labels.csv', header=True, index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"shutil.rmtree(\"./data\") # remove unnecessary output files!","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}