{"cells":[{"metadata":{},"cell_type":"markdown","source":"<h1 style=\"font-family:verdana;\"> <center> RetinaNet 🎖</center> </h1>\n\n<h3><center style=\"color:#159364; font-family:cursive;\">💬 KICK-START this competition with RetinaNet</center></h3>\n\n<img src=\"https://lh3.googleusercontent.com/1TaNTTbCmw4E94xU7XKdTQ-CR6t7lnqA_YLgXosi2S3_1eDzehkcjv3qnzkxjKmUOzxKzxqHg45vql5G8wChVh4B6W91GjQTTnV3PZybyMAZSch2n6ckY0P9sqKUbrxOwrCnSq-J\">\n\n<br>\n\n📌  Special Thanks to\n* https://github.com/fizyr/keras-retinanet\n* https://www.kaggle.com/awsaf49 for the (.png) Dataset\n\n<hr>"},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\n\nimport numpy as np\nimport pandas as pd\n\nimport matplotlib.pyplot as plt\nimport cv2\n\nfrom sklearn.model_selection import StratifiedKFold\nimport warnings","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2 style=\"font-family:verdana;\"> <center>📂 Config File</center> </h2>\n\n<hr>"},{"metadata":{"trusted":true},"cell_type":"code","source":"class Cfg(object):\n  \n  def __init__(self):\n    super(Cfg, self).__init__()\n    self.dim = 512\n    self.batch= 8\n    self.steps= 500\n    self.epochs= 10\n    self.train_csv= '../input/vinbigdata-{}-image-dataset/vinbigdata/train.csv'.format(self.dim)\n    self.test_csv= '../input/vinbigdata-{}-image-dataset/vinbigdata/test.csv'.format(self.dim)\n    self.img_dir= '../input/vinbigdata-{}-image-dataset/vinbigdata/train/'.format(self.dim)\n    \n    self.git= 'https://github.com/fizyr/keras-retinanet.git'\n    self.model_url= ['https://github.com/fizyr/keras-retinanet/releases/download/0.5.1/resnet50_coco_best_v2.1.0.h5',\n               'https://github.com/fizyr/keras-retinanet/releases/download/0.5.1/resnet101_oid_v1.0.0.h5',\n               'https://github.com/fizyr/keras-retinanet/releases/download/0.5.1/resnet152_oid_v1.0.0.h5']\n    \n    self.color_code=   {'Cardiomegaly':(124,252,0), 'Aortic enlargement':(135,206,250),\n                        'Pleural thickening':(199,21,133),'ILD':(245,245,220), 'Nodule/Mass':(220,20,60),\n                        'Pulmonary fibrosis':(0,255,255), 'Lung Opacity':(128,128,0), 'Atelectasis':(255,0,255),\n                        'Other lesion':(176,224,230), 'Infiltration':(210,105,30),'Pleural effusion':(105,105,105),\n                        'Calcification':(138,43,226) ,'Consolidation':(250,240,230),'Pneumothorax':(100,149,237)}\n    \ncfg= Cfg()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2 style=\"font-family:verdana;\"> <center>📚 Data Processing for Retinanet</center> </h2>\n\n\n\n\n<hr>"},{"metadata":{"trusted":true},"cell_type":"code","source":"df= pd.read_csv(cfg.train_csv)\nprint(df.shape)\ndf= df[df.class_name != 'No finding']\ndisplay(df.head())\ndf.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_img(path):\n    img= cv2.imread(path)\n    img= cv2.resize(img, (cfg.dim, cfg.dim))\n    return img\n\ndef normalize_cod(df):\n    df.x_min= (df.x_min/ df.width)* cfg.dim\n    df.x_max= (df.x_max/ df.width)* cfg.dim\n    \n    df.y_min= (df.y_min/ df.height)* cfg.dim\n    df.y_max= (df.y_max/ df.height)* cfg.dim\n    return df\n\ndf= normalize_cod(df.copy())\ndf= df.reset_index(drop = True)\n\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"classes= df.class_name.unique()\nind= df.class_id.unique()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"##### Color-Code ########\ncolor= cfg.color_code\n\ndef show_bb(i):\n    df_mini= df[df.image_id==df.image_id[i]]\n    path= cfg.img_dir + df.image_id[i] + '.png'\n    img= load_img(path)\n    rep_class=[]\n    font = cv2.FONT_HERSHEY_SIMPLEX \n    for i, row in df_mini.iterrows():\n        class_n= row['class_name']\n        if class_n in rep_class:\n            continue                          # More generalization\n        rep_class.append(class_n)\n        x_min= int(row['x_min']); x_max= int(row['x_max'])\n        y_min= int(row['y_min']); y_max= int(row['y_max'])\n        img= cv2.rectangle(img, (x_min, y_min), (x_max, y_max), color[class_n], 2)\n        fontScale= (x_max- x_min)*2.5/img.shape[1]\n        img= cv2.putText(img, class_n, (x_min, y_min-5), font, fontScale, cv2.LINE_AA)\n    return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"f, ax= plt.subplots(2, 4, figsize=(26, 14))\nfor i in range(8):\n    ax[i//4][i%4].imshow(show_bb(i), aspect='auto')\n    ax[i//4][i%4].set_xticks([]); ax[i//4][i%4].set_yticks([])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<h2 style=\"font-family:verdana;\"> <center>Data Spliting</center> </h2>\n\n<hr>"},{"metadata":{"trusted":true},"cell_type":"code","source":"'''\nhttps://www.kaggle.com/backtracking/smart-data-split-train-eval-for-object-detection\n'''\n\nskf = StratifiedKFold(n_splits=6, shuffle=True, random_state=101)\ndf_folds = df[['image_id']].copy()\n\ndf_folds.loc[:, 'bbox_count'] = 1\ndf_folds = df_folds.groupby('image_id').count()\ndf_folds.loc[:, 'object_count'] = df.groupby('image_id')['class_id'].nunique()\n\ndf_folds.loc[:, 'stratify_group'] = np.char.add(\n    df_folds['object_count'].values.astype(str),\n    df_folds['bbox_count'].apply(lambda x: f'_{x // 15}').values.astype(str)\n)\n\ndf_folds.loc[:, 'fold'] = 0\nfor fold_number, (train_index, val_index) in enumerate(skf.split(X=df_folds.index, y=df_folds['stratify_group'])):\n    df_folds.loc[df_folds.iloc[val_index].index, 'fold'] = fold_number","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_folds.reset_index(inplace=True)\n\ndf_valid = pd.merge(df, df_folds[df_folds['fold'] == 0], on='image_id')\ndf_train = pd.merge(df, df_folds[df_folds['fold'] != 0], on='image_id')\n\ndf_train.shape, df_valid.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(20, 4))\nplt.hist(df_train['class_name'], label='Train Data Split')\nplt.hist(df_valid['class_name'], label='Test Data Split')\nplt.grid()\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Train set\ndf_train= df_train[['image_id','x_min', 'y_min', 'x_max', 'y_max', 'class_name']]\ndf_train.image_id= df_train.image_id.apply(lambda x: '../'+ cfg.img_dir+ x+ '.png')\ndf_train.iloc[:,1:-1]=df_train.iloc[:,1:-1].astype('int32')\n\n# validation set\ndf_valid= df_valid[['image_id','x_min', 'y_min', 'x_max', 'y_max', 'class_name']]\ndf_valid.image_id= df_valid.image_id.apply(lambda x: '../'+ cfg.img_dir+ x+ '.png')\ndf_valid.iloc[:,1:-1]=df_valid.iloc[:,1:-1].astype('int32')\n\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# just Sanity check stuff\n\n#df_train= df_train.drop(df_train[df_train.y_max== df_train.y_min].index[0])\ndf_valid= df_valid.drop(df_valid[df_valid.y_max== df_valid.y_min].index[0])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\n<h2 style=\"font-family:verdana;\"> <center>🏛 DRetinanet architecture</center> </h2>\n\n![00194_psisdg11321_113210f_page_2_1](https://user-images.githubusercontent.com/64481847/103896119-7d1bbe80-5117-11eb-893e-a0efbfa3fc31.jpg)\n\n\n<hr>"},{"metadata":{},"cell_type":"markdown","source":"<h2 style=\"font-family:verdana;\"> <center>⚙️ RetinaNet installation</center> </h2>\n\n\n<hr>\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"################## RETINANET #######################\n!git clone 'https://github.com/fizyr/keras-retinanet.git'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%capture\n\n%cd keras-retinanet/\n!pip install .","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%capture\n\n!python setup.py build_ext --inplace","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"####### Saving csv and classes files ##########\ndf_train.to_csv('annotations.csv', index=False, header=None)\ndf_valid.to_csv('annotations_test.csv', index=False)\n\n\nprint(classes)\n\nwith open(\"classes.csv\",\"w\") as file:\n    for i, cn in zip(ind, classes):\n        file.write('{},{}\\n'.format(cn, i))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow\nfrom keras_retinanet import models\nfrom keras_retinanet.utils.image import read_image_bgr ,preprocess_image, resize_image\nfrom keras_retinanet.utils.visualization import draw_box, draw_caption\nfrom keras_retinanet.utils.colors import label_color\n\nimport requests\nimport urllib","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pretrained_model = 'snapshots/pretrained_model_101.h5'\n\nmodel_url = cfg.model_url[1]\nurllib.request.urlretrieve(model_url, pretrained_model)\n\nprint(\"Downloaded pretrained model- {} to-'{}'\".format(model_url, pretrained_model))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%ls","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!keras_retinanet/bin/train.py --freeze-backbone \\\n  --random-transform \\\n  --workers 0 \\\n  --weights {pretrained_model} \\\n  --batch-size 6 \\\n  --steps 550 \\\n  --image-min-side 512\\\n  --image-max-side 512\\\n  --epochs 50 \\\n  csv annotations.csv classes.csv","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### More Parameters\nhttps://github.com/fizyr/keras-retinanet/blob/master/keras_retinanet/bin/train.py\n\n    oid_parser = subparsers.add_parser('oid')\n    oid_parser.add_argument('main_dir', help='Path to dataset directory.')\n    oid_parser.add_argument('--version',  help='The current dataset version is v4.', default='v4')\n    oid_parser.add_argument('--labels-filter',  help='A list of labels to filter.', type=csv_list, default=None)\n    oid_parser.add_argument('--annotation-cache-dir', help='Path to store annotation cache.', default='.')\n    oid_parser.add_argument('--parent-label', help='Use the hierarchy children of this label.', default=None)\n\n    csv_parser = subparsers.add_parser('csv')\n    csv_parser.add_argument('annotations', help='Path to CSV file containing annotations for training.')\n    csv_parser.add_argument('classes', help='Path to a CSV file containing class label mapping.')\n    csv_parser.add_argument('--val-annotations', help='Path to CSV file containing annotations for validation (optional).')\n\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument('--snapshot',          help='Resume training from a snapshot.')\n    group.add_argument('--imagenet-weights',  help='Initialize the model with pretrained imagenet weights. This is the default behaviour.', action='store_const', const=True, default=True)\n    group.add_argument('--weights',           help='Initialize the model with weights from a file.')\n    group.add_argument('--no-weights',        help='Don\\'t initialize the model with any weights.', dest='imagenet_weights', action='store_const', const=False)\n    parser.add_argument('--backbone',         help='Backbone model used by retinanet.', default='resnet50', type=str)\n    parser.add_argument('--batch-size',       help='Size of the batches.', default=1, type=int)\n    parser.add_argument('--gpu',              help='Id of the GPU to use (as reported by nvidia-smi).')\n    parser.add_argument('--multi-gpu',        help='Number of GPUs to use for parallel processing.', type=int, default=0)\n    parser.add_argument('--multi-gpu-force',  help='Extra flag needed to enable (experimental) multi-gpu support.', action='store_true')\n    parser.add_argument('--initial-epoch',    help='Epoch from which to begin the train, useful if resuming from snapshot.', type=int, default=0)\n    parser.add_argument('--epochs',           help='Number of epochs to train.', type=int, default=50)\n    parser.add_argument('--steps',            help='Number of steps per epoch.', type=int, default=10000)\n    parser.add_argument('--lr',               help='Learning rate.', type=float, default=1e-5)\n    parser.add_argument('--optimizer-clipnorm', help='Clipnorm parameter for  optimizer.', type=float, default=0.001)\n    parser.add_argument('--snapshot-path',    help='Path to store snapshots of models during training (defaults to \\'./snapshots\\')', default='./snapshots')\n    parser.add_argument('--tensorboard-dir',  help='Log directory for Tensorboard output', default='')  # default='./logs') => https://github.com/tensorflow/tensorflow/pull/34870\n    parser.add_argument('--tensorboard-freq', help='Update frequency for Tensorboard output. Values \\'epoch\\', \\'batch\\' or int', default='epoch')\n    parser.add_argument('--no-snapshots',     help='Disable saving snapshots.', dest='snapshots', action='store_false')\n    parser.add_argument('--no-evaluation',    help='Disable per epoch evaluation.', dest='evaluation', action='store_false')\n    parser.add_argument('--freeze-backbone',  help='Freeze training of backbone layers.', action='store_true')\n    parser.add_argument('--random-transform', help='Randomly transform image and annotations.', action='store_true')\n    parser.add_argument('--image-min-side',   help='Rescale the image so the smallest side is min_side.', type=int, default=800)\n    parser.add_argument('--image-max-side',   help='Rescale the image if the largest side is larger than max_side.', type=int, default=1333)\n    parser.add_argument('--no-resize',        help='Don''t rescale the image.', action='store_true')\n    parser.add_argument('--config',           help='Path to a configuration parameters .ini file.')\n    parser.add_argument('--weighted-average', help='Compute the mAP using the weighted average of precisions among classes.', action='store_true')\n    parser.add_argument('--compute-val-loss', help='Compute validation loss during training', dest='compute_val_loss', action='store_true')\n    parser.add_argument('--reduce-lr-patience', help='Reduce learning rate after validation loss decreases over reduce_lr_patience epochs', type=int, default=2)\n    parser.add_argument('--reduce-lr-factor', help='When learning rate is reduced due to reduce_lr_patience, multiply by reduce_lr_factor', type=float, default=0.1)\n    parser.add_argument('--group-method',     help='Determines how images are grouped together', type=str, default='ratio', choices=['none', 'random', 'ratio'])\n\n    # Fit generator arguments\n    parser.add_argument('--multiprocessing',  help='Use multiprocessing in fit_generator.', action='store_true')\n    parser.add_argument('--workers',          help='Number of generator workers.', type=int, default=1)\n    parser.add_argument('--max-queue-size',   help='Queue length for multiprocessing workers in fit_generator.', type=int, default=10)"},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\n\n## 🌄 Thanks for Reading\n\n![](https://i.gifer.com/7ImI.gif)\n\n\n\n<div class=\"alert alert-block alert-info\" style=\"font-size:20px; font-family:verdana;\">\n <a target=\"_blank\" style=\"color:orange;\">Do UPVOTE for more Motivation🤞</a>\n</div>\n\n\n\n<hr><hr><hr>\n\n<hr>"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Download all Working data \n\n%cd ..","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import shutil\nshutil.make_archive('Keras-Retinanet', 'zip', 'keras-retinanet')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"<a href=\"./Keras-Retinanet.zip\">DOWNLOAD ZIP FILE :-)</a>"},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}