{"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":"code","source":"!pip install -Uqq fastbook\nimport fastbook","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from fastbook import *","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install fastai==2.6","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import fastai","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(fastai.__version__)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from fastai.vision.all import *","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:19.123899Z","iopub.status.busy":"2022-04-26T11:52:19.123632Z","iopub.status.idle":"2022-04-26T11:52:21.868499Z","shell.execute_reply":"2022-04-26T11:52:21.867721Z","shell.execute_reply.started":"2022-04-26T11:52:19.123871Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport matplotlib as mpl\nimport seaborn as sns\nimport tqdm\nimport warnings\nwarnings.filterwarnings('ignore')\nmpl.rcParams[\"figure.figsize\"] = (18, 12)","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:21.872923Z","iopub.status.busy":"2022-04-26T11:52:21.87234Z","iopub.status.idle":"2022-04-26T11:52:21.935425Z","shell.execute_reply":"2022-04-26T11:52:21.934778Z","shell.execute_reply.started":"2022-04-26T11:52:21.872891Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd.set_option('display.max_columns', 150)\npd.set_option('display.max_rows', 150)","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:21.938816Z","iopub.status.busy":"2022-04-26T11:52:21.938603Z","iopub.status.idle":"2022-04-26T11:52:21.942532Z","shell.execute_reply":"2022-04-26T11:52:21.941809Z","shell.execute_reply.started":"2022-04-26T11:52:21.93879Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.cuda.set_device(0)","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:21.954026Z","iopub.status.busy":"2022-04-26T11:52:21.95233Z","iopub.status.idle":"2022-04-26T11:52:21.958799Z","shell.execute_reply":"2022-04-26T11:52:21.957984Z","shell.execute_reply.started":"2022-04-26T11:52:21.953923Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seed_everything(seed=0):\n    \"\"\"Initialize the random number generator.\n\n    Parameters:\n    seed (int): any number\n\n    Returns:\n    int:null\n\n   \"\"\"\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n\n\nseed_everything()","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:22.230372Z","iopub.status.busy":"2022-04-26T11:52:22.230023Z","iopub.status.idle":"2022-04-26T11:52:22.237194Z","shell.execute_reply":"2022-04-26T11:52:22.236481Z","shell.execute_reply.started":"2022-04-26T11:52:22.230332Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path = Path('./sorghum-id-fgvc-9')\npath.ls()","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:23.750918Z","iopub.status.busy":"2022-04-26T11:52:23.750628Z","iopub.status.idle":"2022-04-26T11:52:23.764396Z","shell.execute_reply":"2022-04-26T11:52:23.76367Z","shell.execute_reply.started":"2022-04-26T11:52:23.750886Z"}},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data exploration","metadata":{}},{"cell_type":"code","source":"sorghum_df = pd.read_csv(path/'train_cultivar_mapping.csv')\nsorghum_df.head()","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:25.097685Z","iopub.status.busy":"2022-04-26T11:52:25.096981Z","iopub.status.idle":"2022-04-26T11:52:25.145858Z","shell.execute_reply":"2022-04-26T11:52:25.145167Z","shell.execute_reply.started":"2022-04-26T11:52:25.097646Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"allowed_image = []\nfor i in (path/'train_images').ls():\n    va = i.name in sorghum_df.image.to_list()\n    if va:\n        allowed_image.append(i.name)","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:25.632342Z","iopub.status.busy":"2022-04-26T11:52:25.632012Z","iopub.status.idle":"2022-04-26T11:52:35.351043Z","shell.execute_reply":"2022-04-26T11:52:35.350304Z","shell.execute_reply.started":"2022-04-26T11:52:25.632305Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sorghum_df = sorghum_df[sorghum_df.image.isin(allowed_image)]","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:35.352942Z","iopub.status.busy":"2022-04-26T11:52:35.352699Z","iopub.status.idle":"2022-04-26T11:52:35.371078Z","shell.execute_reply":"2022-04-26T11:52:35.370471Z","shell.execute_reply.started":"2022-04-26T11:52:35.352907Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sorghum_df.cultivar.value_counts().plot(kind='bar')","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:35.372602Z","iopub.status.busy":"2022-04-26T11:52:35.372353Z","iopub.status.idle":"2022-04-26T11:52:36.772726Z","shell.execute_reply":"2022-04-26T11:52:36.770948Z","shell.execute_reply.started":"2022-04-26T11:52:35.372569Z"}},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataLoaders","metadata":{}},{"cell_type":"code","source":"dls = ImageDataLoaders.from_df(\n    sorghum_df,\n    path/'train_images',\n    valid_pct=0.10,\n    item_tfms=Resize(460),\n    batch_tfms=[\n        *aug_transforms(size=224, min_scale=0.75),\n        Normalize.from_stats(*imagenet_stats)\n    ],\n    bs=64,\n    num_workers=4,\n    label_col=\"cultivar\")","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:36.775381Z","iopub.status.busy":"2022-04-26T11:52:36.774881Z","iopub.status.idle":"2022-04-26T11:52:41.441649Z","shell.execute_reply":"2022-04-26T11:52:41.440883Z","shell.execute_reply.started":"2022-04-26T11:52:36.775342Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dls.show_batch()","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:41.443139Z","iopub.status.busy":"2022-04-26T11:52:41.442803Z","iopub.status.idle":"2022-04-26T11:52:43.878877Z","shell.execute_reply":"2022-04-26T11:52:43.878238Z","shell.execute_reply.started":"2022-04-26T11:52:41.443099Z"}},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create the Learner","metadata":{}},{"cell_type":"code","source":"learn = cnn_learner(\n    dls,\n    resnet50,\n    metrics=[error_rate, accuracy],\n    model_dir=\"/tmp/model/\").to_fp16()","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:43.889673Z","iopub.status.busy":"2022-04-26T11:52:43.8889Z","iopub.status.idle":"2022-04-26T11:52:53.06712Z","shell.execute_reply":"2022-04-26T11:52:53.066305Z","shell.execute_reply.started":"2022-04-26T11:52:43.889635Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def find_appropriate_lr(model:Learner, lr_diff:int = 15, loss_threshold:float = .05, adjust_value:float = 1, plot:bool = False) -> float:\n    \"\"\"Method that automates the selection of a Learning Rate in Fast.ai\n\n    Parameters:\n    model (Learner): The learner\n    lr_diff (int): The interval distance by units of the “index of LR” (log transform of LRs) between the right and left bound\n    loss_threshold (float): The maximum difference between the left and right bound’s loss values to stop the shift\n    adjust_value (float): A coefficient to the final learning rate for pure manual adjustment\n    plot (bool): A boolean to show two plots\n\n    Returns:\n    float: Best learning rate value to use\n\n   \"\"\"\n    model.lr_find()\n    \n    losses = np.array(model.recorder.losses)\n    assert(lr_diff < len(losses))\n    loss_grad = np.gradient(losses)\n    lrs = model.recorder.lrs\n    \n    r_idx = -1\n    l_idx = r_idx - lr_diff\n    while (l_idx >= -len(losses)) and (abs(loss_grad[r_idx] - loss_grad[l_idx]) > loss_threshold):\n        local_min_lr = lrs[l_idx]\n        r_idx -= 1\n        l_idx -= 1\n\n    lr_to_use = local_min_lr * adjust_value\n    \n    if plot:\n        plt.plot(loss_grad)\n        plt.plot(len(losses)+l_idx, loss_grad[l_idx],markersize=10,marker='o',color='red')\n        plt.ylabel(\"Loss\")\n        plt.xlabel(\"Index of LRs\")\n        plt.show()\n\n        plt.plot(np.log10(lrs), losses)\n        plt.ylabel(\"Loss\")\n        plt.xlabel(\"Log 10 Transform of Learning Rate\")\n        loss_coord = np.interp(np.log10(lr_to_use), np.log10(lrs), losses)\n        plt.plot(np.log10(lr_to_use), loss_coord, markersize=10,marker='o',color='red')\n        plt.show()\n        \n    return lr_to_use","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:53.069066Z","iopub.status.busy":"2022-04-26T11:52:53.068765Z","iopub.status.idle":"2022-04-26T11:52:53.080929Z","shell.execute_reply":"2022-04-26T11:52:53.079872Z","shell.execute_reply.started":"2022-04-26T11:52:53.069026Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%time lr_to_use = find_appropriate_lr(learn)","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:52:53.08305Z","iopub.status.busy":"2022-04-26T11:52:53.082692Z","iopub.status.idle":"2022-04-26T11:54:31.041231Z","shell.execute_reply":"2022-04-26T11:54:31.040461Z","shell.execute_reply.started":"2022-04-26T11:52:53.082999Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lr_to_use","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:56:09.963228Z","iopub.status.busy":"2022-04-26T11:56:09.962734Z","iopub.status.idle":"2022-04-26T11:56:09.969335Z","shell.execute_reply":"2022-04-26T11:56:09.968223Z","shell.execute_reply.started":"2022-04-26T11:56:09.963182Z"}},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training","metadata":{}},{"cell_type":"code","source":"%time learn.fine_tune(20, lr_to_use)","metadata":{"execution":{"iopub.execute_input":"2022-04-26T11:56:09.984424Z","iopub.status.busy":"2022-04-26T11:56:09.983884Z","iopub.status.idle":"2022-04-26T13:29:20.893168Z","shell.execute_reply":"2022-04-26T13:29:20.891981Z","shell.execute_reply.started":"2022-04-26T11:56:09.984387Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.show_results()","metadata":{"execution":{"iopub.execute_input":"2022-04-26T15:04:51.691606Z","iopub.status.busy":"2022-04-26T15:04:51.691021Z","iopub.status.idle":"2022-04-26T15:04:53.613192Z","shell.execute_reply":"2022-04-26T15:04:53.612447Z","shell.execute_reply.started":"2022-04-26T15:04:51.691558Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"interp = ClassificationInterpretation.from_learner(learn)","metadata":{"execution":{"iopub.execute_input":"2022-04-26T15:39:35.196062Z","iopub.status.busy":"2022-04-26T15:39:35.195746Z","iopub.status.idle":"2022-04-26T15:40:39.321886Z","shell.execute_reply":"2022-04-26T15:40:39.321113Z","shell.execute_reply.started":"2022-04-26T15:39:35.196028Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"interp.plot_top_losses(9, figsize=(15, 10))","metadata":{"execution":{"iopub.execute_input":"2022-04-26T15:41:43.025434Z","iopub.status.busy":"2022-04-26T15:41:43.025013Z","iopub.status.idle":"2022-04-26T15:41:44.552717Z","shell.execute_reply":"2022-04-26T15:41:44.549475Z","shell.execute_reply.started":"2022-04-26T15:41:43.025395Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"interp.plot_confusion_matrix(figsize=(20, 20))","metadata":{"execution":{"iopub.execute_input":"2022-04-26T15:41:46.134103Z","iopub.status.busy":"2022-04-26T15:41:46.133636Z","iopub.status.idle":"2022-04-26T15:43:26.329779Z","shell.execute_reply":"2022-04-26T15:43:26.329141Z","shell.execute_reply.started":"2022-04-26T15:41:46.134068Z"}},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predictions","metadata":{}},{"cell_type":"code","source":"test_dl = dls.test_dl(get_image_files(path/'test'))","metadata":{"execution":{"iopub.execute_input":"2022-04-26T15:45:06.82861Z","iopub.status.busy":"2022-04-26T15:45:06.828221Z","iopub.status.idle":"2022-04-26T15:45:33.081903Z","shell.execute_reply":"2022-04-26T15:45:33.081007Z","shell.execute_reply.started":"2022-04-26T15:45:06.828573Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"log_preds_test = learn.get_preds(dl=test_dl)\nlog_preds_test = np.argmax(log_preds_test[0], axis=1)\npreds_classes = [dls.vocab[i] for i in log_preds_test]\nprobs = np.exp(log_preds_test)","metadata":{"execution":{"iopub.execute_input":"2022-04-26T15:48:26.233373Z","iopub.status.busy":"2022-04-26T15:48:26.232518Z","iopub.status.idle":"2022-04-26T16:04:53.25497Z","shell.execute_reply":"2022-04-26T16:04:53.254009Z","shell.execute_reply.started":"2022-04-26T15:48:26.23332Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.DataFrame({ 'filename': os.listdir(path/'test'), 'cultivar': preds_classes })","metadata":{"execution":{"iopub.execute_input":"2022-04-26T16:08:40.952063Z","iopub.status.busy":"2022-04-26T16:08:40.951441Z","iopub.status.idle":"2022-04-26T16:08:40.977307Z","shell.execute_reply":"2022-04-26T16:08:40.976446Z","shell.execute_reply.started":"2022-04-26T16:08:40.952023Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission","metadata":{"execution":{"iopub.execute_input":"2022-04-26T16:08:43.879604Z","iopub.status.busy":"2022-04-26T16:08:43.878668Z","iopub.status.idle":"2022-04-26T16:08:43.901141Z","shell.execute_reply":"2022-04-26T16:08:43.900464Z","shell.execute_reply.started":"2022-04-26T16:08:43.87956Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.execute_input":"2022-04-26T16:08:47.804927Z","iopub.status.busy":"2022-04-26T16:08:47.804224Z","iopub.status.idle":"2022-04-26T16:08:47.866188Z","shell.execute_reply":"2022-04-26T16:08:47.865495Z","shell.execute_reply.started":"2022-04-26T16:08:47.804891Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}