{"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":"package_paths = ['../input/timm-module']\nimport sys;\nfor pth in package_paths:\n    sys.path.append(pth)\n\nimport os\nimport pandas as pd\nimport torch\nimport timm\nimport albumentations as A\nimport matplotlib.pyplot as plt\nimport wandb\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport glob\nimport cv2\n\nfrom torch.utils.data import Dataset, DataLoader\nfrom albumentations.pytorch import ToTensorV2\nfrom sklearn.metrics import multilabel_confusion_matrix\nfrom timm import *\nfrom fastai.vision.learner import _add_norm\nfrom fastai.vision.all import *\nfrom fastai.vision.learner import _update_first_layer\nfrom fastai.callback.wandb import *","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:23:20.571541Z","iopub.execute_input":"2021-07-27T07:23:20.571943Z","iopub.status.idle":"2021-07-27T07:23:27.682380Z","shell.execute_reply.started":"2021-07-27T07:23:20.571851Z","shell.execute_reply":"2021-07-27T07:23:27.681472Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\ndef seed_everything(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n\n    if device == 'cuda:0':\n        torch.cuda.manual_seed(seed)\n        torch.backends.cudnn.deterministic = True","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:23:42.854532Z","iopub.execute_input":"2021-07-27T07:23:42.854851Z","iopub.status.idle":"2021-07-27T07:23:42.862692Z","shell.execute_reply.started":"2021-07-27T07:23:42.854820Z","shell.execute_reply":"2021-07-27T07:23:42.861842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Config:\n    seed_val = 111\n    seed_everything(seed_val)\n    fold_num = 0\n    job = 1\n    num_classes = 4\n    input_dims = 512\n    model_arch = 'tf_efficientnetv2_m_in21ft1k'\n    batch_size = 3\n    num_workers = 0\n    kfold = 5\n    loss_func = nn.BCEWithLogitsLoss()  # CrossEntropyLossFlat() or LabelSmoothingCrossEntropyFlat() for multi-class\n    metrics = [accuracy_multi, RocAucMulti(average='macro'), F1ScoreMulti(average='macro')]\n    job_name = f'{model_arch}_fold{fold_num}_job{job}'\n    print(\"Job Name:\", job_name)\n\n    wandb_project = 'SIIM_classifier_public'\n    wandb_run_name = job_name\n\n    if str(device) == 'cuda:0':\n        fp16 = True\n    else:\n        fp16 = False\n\n\ncfg = Config()\nconfig_dict = dict(vars(Config))\nconfig_dict = {k:(v if type(v)==int else str(v)) for (k,v) in config_dict.items() if '__' not in k}","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:23:44.625517Z","iopub.execute_input":"2021-07-27T07:23:44.625828Z","iopub.status.idle":"2021-07-27T07:23:44.634452Z","shell.execute_reply.started":"2021-07-27T07:23:44.625799Z","shell.execute_reply":"2021-07-27T07:23:44.633597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_timm_body(arch:str, pretrained=True, cut=None, n_in=3):\n    \"Creates a body from any model in the `timm` library.\"\n    model = create_model(arch, pretrained=pretrained, num_classes=0, global_pool='')\n    _update_first_layer(model, n_in, pretrained)\n    if cut is None:\n        ll = list(enumerate(model.children()))\n        cut = next(i for i,o in reversed(ll) if has_pool_type(o))\n    if isinstance(cut, int): return nn.Sequential(*list(model.children())[:cut])\n    elif callable(cut): return cut(model)\n    else: raise NamedError(\"cut must be either integer or function\")\n\n\ndef create_timm_model(arch: str, n_out, cut=None, pretrained=True, n_in=3,\n                      init=nn.init.kaiming_normal_, custom_head=None,\n                      concat_pool=True, **kwargs):\n    \"Create custom architecture using `arch`, `n_in` and `n_out` from the `timm` library\"\n    body = create_timm_body(arch, pretrained, None, n_in)\n    if custom_head is None:\n        nf = num_features_model(nn.Sequential(*body.children()))\n        head = create_head(nf, n_out, concat_pool=concat_pool, **kwargs)\n    else:\n        head = custom_head\n    model = nn.Sequential(body, head)\n    if init is not None: apply_init(model[1], init)\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:23:48.313923Z","iopub.execute_input":"2021-07-27T07:23:48.314360Z","iopub.status.idle":"2021-07-27T07:23:48.323101Z","shell.execute_reply.started":"2021-07-27T07:23:48.314320Z","shell.execute_reply":"2021-07-27T07:23:48.322264Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PlantDataset(Dataset):\n    def __init__(self, df, transform=None):\n        self.image_id = df['study_id'].values\n        self.transform = transform\n        self.path = df['image_path'].values\n\n    def __len__(self):\n        return len(self.image_id)\n\n    def __getitem__(self, idx):\n        image_id = self.image_id[idx]\n        image_name = image_id\n\n        image_path = self.path[idx]\n        image = cv2.imread(image_path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n\n        augmented = self.transform(image=image)\n        image = augmented['image']\n        return image, image_name\n\n\ndef get_transform():\n        return A.Compose([A.Resize(cfg.input_dims, cfg.input_dims, p=1.0), ToTensorV2()], p=1.0)","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:23:51.022576Z","iopub.execute_input":"2021-07-27T07:23:51.022898Z","iopub.status.idle":"2021-07-27T07:23:51.029822Z","shell.execute_reply.started":"2021-07-27T07:23:51.022861Z","shell.execute_reply":"2021-07-27T07:23:51.028824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class PlantPredictor():\n    def __init__(self, net, test_df, df_labels_idx, dataloaders, device):\n        self.net = net\n        self.df_labels_idx = df_labels_idx\n        self.dataloaders = dataloaders\n        self.df_submit = pd.DataFrame(columns = ['id', 'labels'])\n        self.device = device\n        self.net.to(self.device)\n    \n    \n    def inference(self):\n        self.net.eval()\n        labels_pre = []\n        image_name_all = []\n        for inputs, image_name in self.dataloaders:\n            # torch.cuda.empty_cache()\n            pre_list = []\n            image_name_all.append(image_name)\n            inputs = inputs.float()\n            inputs = inputs.to(self.device)\n\n            with torch.no_grad():\n                out = self.net(inputs)\n            out = out.cpu()\n            pre_list.append(out.detach().sigmoid().numpy() > 0.41)\n            pre_list = pd.DataFrame(np.concatenate(pre_list).astype(np.int), columns=labels)\n            multi_labels = pre_list.columns\n            for i, row in pre_list.iterrows():\n                if ((row['negative'] == 1) or row.sum() == 0):\n                    tmp = multi_labels[np.argmax(torch.nn.functional.softmax(out[i].reshape(1, len(out[i])), dim=1)).item()]\n                else:\n                    tmp = ' '.join(multi_labels[row==row.max()])\n                labels_pre.append(tmp + ' 1 0 0 1 1')\n        image_name_list = np.concatenate(image_name_all)\n        self.df_submit['id'] = image_name_list\n        self.df_submit['labels'] = labels_pre","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:23:53.194370Z","iopub.execute_input":"2021-07-27T07:23:53.194691Z","iopub.status.idle":"2021-07-27T07:23:53.205444Z","shell.execute_reply.started":"2021-07-27T07:23:53.194661Z","shell.execute_reply":"2021-07-27T07:23:53.204404Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"net =  create_timm_model(arch=cfg.model_arch, n_out=4, pretrained=False, n_in=3)\nnet.load_state_dict({k.replace('', ''): v for k, v in torch.load('../input/efficientnet0/e43ae05e11713613365669a4e1cb010d.pth').items()})\n\nsub_df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\n\n# Form study and image dataframes\nsub_df['level'] = sub_df.id.map(lambda idx: idx[-5:])\nstudy_df = sub_df[sub_df.level=='study'].rename({'id':'study_id'}, axis=1)\nimage_df = sub_df[sub_df.level=='image'].rename({'id':'image_id'}, axis=1)\n\ndcm_path = glob.glob('/kaggle/input/siim-covid19-detection/test/**/*dcm', recursive=True)\ntest_meta = pd.DataFrame({'dcm_path':dcm_path})\ntest_meta['image_id'] = test_meta.dcm_path.map(lambda x: x.split('/')[-1].replace('.dcm', '')+'_image')\ntest_meta['study_id'] = test_meta.dcm_path.map(lambda x: x.split('/')[-3].replace('.dcm', '')+'_study')\n\nstudy_df = study_df.merge(test_meta, on='study_id', how='left')\nimage_df = image_df.merge(test_meta, on='image_id', how='left')\n\n# Remove duplicates study_ids from study_df\nstudy_df.drop_duplicates(subset=\"study_id\",keep='first', inplace=True)\nstudy_dir = '../input/siim-covid19-images-metadata-256-512-768/images_metadata_256_512_768/test_512x512'\nstudy_df['image_path'] = study_dir+'/'+study_df['image_id']+'.png'\n\nlabels = ['negative', 'typical', 'indeterminate', 'atypical']\nlabels_n = [1, 2, 3, 4]\ndf_labels_idx = pd.DataFrame({'labels_n':labels_n, 'labels':labels})\ntest_dataset = PlantDataset(study_df, transform=get_transform())\ntest_loader =  DataLoader(test_dataset, batch_size=2, shuffle=False)\npre = PlantPredictor(net, study_df, df_labels_idx, test_loader,device)\npre.inference()\ndf_submit = pre.df_submit.copy()","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:23:56.196461Z","iopub.execute_input":"2021-07-27T07:23:56.196861Z","iopub.status.idle":"2021-07-27T07:25:08.972035Z","shell.execute_reply.started":"2021-07-27T07:23:56.196826Z","shell.execute_reply":"2021-07-27T07:25:08.971190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TEST_PATH = '/kaggle/input/siimcovid19resizedto256pxjpg/test/'\nMODEL_PATH = '/kaggle/input/yolov5/YOLOV5.pt'","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:25:33.696865Z","iopub.execute_input":"2021-07-27T07:25:33.697232Z","iopub.status.idle":"2021-07-27T07:25:33.701527Z","shell.execute_reply.started":"2021-07-27T07:25:33.697198Z","shell.execute_reply":"2021-07-27T07:25:33.700392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"shutil.copytree('/kaggle/input/kaggle/tmp/yolov5', '/kaggle/working/yolov5')\nos.chdir('/kaggle/working/yolov5')","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:25:35.592183Z","iopub.execute_input":"2021-07-27T07:25:35.592536Z","iopub.status.idle":"2021-07-27T07:25:36.121029Z","shell.execute_reply.started":"2021-07-27T07:25:35.592503Z","shell.execute_reply":"2021-07-27T07:25:36.120040Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_SIZE = 256\n!python detect.py --weights {MODEL_PATH} \\\n                  --source {TEST_PATH} \\\n                  --img {IMG_SIZE} \\\n                  --conf 0.281 \\\n                  --iou-thres 0.5 \\\n                  --max-det 3 \\\n                  --save-txt \\\n                  --save-conf","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:25:37.996782Z","iopub.execute_input":"2021-07-27T07:25:37.997150Z","iopub.status.idle":"2021-07-27T07:26:25.774966Z","shell.execute_reply.started":"2021-07-27T07:25:37.997100Z","shell.execute_reply":"2021-07-27T07:26:25.774063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"PRED_PATH = 'runs/detect/exp/labels'\n# %cat /kaggle/working/yolov5/runs/detect/exp/labels/c6c9bf98487a.txt\nprediction_files = os.listdir(PRED_PATH)\n","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:26:28.034043Z","iopub.execute_input":"2021-07-27T07:26:28.034420Z","iopub.status.idle":"2021-07-27T07:26:28.039411Z","shell.execute_reply.started":"2021-07-27T07:26:28.034384Z","shell.execute_reply":"2021-07-27T07:26:28.038468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def correct_bbox_format(bboxes):\n    correct_bboxes = []\n    for b in bboxes:\n        xc, yc = int(np.round(b[0]*IMG_SIZE)), int(np.round(b[1]*IMG_SIZE))\n        w, h = int(np.round(b[2]*IMG_SIZE)), int(np.round(b[3]*IMG_SIZE))\n\n        xmin = xc - int(np.round(w/2))\n        xmax = xc + int(np.round(w/2))\n        ymin = yc - int(np.round(h/2))\n        ymax = yc + int(np.round(h/2))\n        \n        correct_bboxes.append([xmin, xmax, ymin, ymax])\n        \n    return correct_bboxes\n\n# Read the txt file generated by YOLOv5 during inference and extract \n# confidence and bounding box coordinates.\ndef get_conf_bboxes(file_path):\n    confidence = []\n    bboxes = []\n    with open(file_path, 'r') as file:\n        for line in file:\n            preds = line.strip('\\n').split(' ')\n            preds = list(map(float, preds))\n            confidence.append(preds[-1])\n            bboxes.append(preds[1:-1])\n    return confidence, bboxes","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:26:30.450134Z","iopub.execute_input":"2021-07-27T07:26:30.450477Z","iopub.status.idle":"2021-07-27T07:26:30.459850Z","shell.execute_reply.started":"2021-07-27T07:26:30.450447Z","shell.execute_reply":"2021-07-27T07:26:30.458409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm import tqdm\nsub_df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\nsub_df.tail()","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:26:34.101320Z","iopub.execute_input":"2021-07-27T07:26:34.101645Z","iopub.status.idle":"2021-07-27T07:26:34.125617Z","shell.execute_reply.started":"2021-07-27T07:26:34.101616Z","shell.execute_reply":"2021-07-27T07:26:34.124673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = []\n\nfor i in tqdm(range(len(sub_df))):\n    row = sub_df.loc[i]\n    id_name = row.id.split('_')[0]\n    id_level = row.id.split('_')[-1]\n    \n    if id_level == 'study':\n        # do study-level classification\n\n        predictions.append(df_submit.loc[df_submit['id'] == row.id].labels.tolist()[0]) # dummy prediction\n        \n        \n    elif id_level == 'image':\n        # we can do image-level classification here.\n        # also we can rely on the object detector's classification head.\n        # for this example submisison we will use YOLO's classification head. \n        # since we already ran the inference we know which test images belong to opacity.\n        if f'{id_name}.txt' in prediction_files:\n            # opacity label\n            confidence, bboxes = get_conf_bboxes(f'{PRED_PATH}/{id_name}.txt')\n            bboxes = correct_bbox_format(bboxes)\n            pred_string = ''\n            for j, conf in enumerate(confidence):\n                pred_string += f'opacity {conf} ' + ' '.join(map(str, bboxes[j])) + ' '\n            predictions.append(pred_string[:-1]) \n        else:\n            predictions.append(\"None 1 0 0 1 1\")","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:26:35.924152Z","iopub.execute_input":"2021-07-27T07:26:35.924492Z","iopub.status.idle":"2021-07-27T07:26:37.194922Z","shell.execute_reply.started":"2021-07-27T07:26:35.924460Z","shell.execute_reply":"2021-07-27T07:26:37.193823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df['PredictionString'] = predictions\nsub_df.to_csv('/kaggle/working/submission.csv',index = False)  \nsub_df.tail()","metadata":{"execution":{"iopub.status.busy":"2021-07-27T07:26:40.391515Z","iopub.execute_input":"2021-07-27T07:26:40.391830Z","iopub.status.idle":"2021-07-27T07:26:40.414810Z","shell.execute_reply.started":"2021-07-27T07:26:40.391800Z","shell.execute_reply":"2021-07-27T07:26:40.414072Z"},"trusted":true},"execution_count":null,"outputs":[]}]}