{"cells":[{"metadata":{},"cell_type":"markdown","source":"# importing libraries"},{"metadata":{"trusted":true},"cell_type":"code","source":"timm_path = \"../input/timm-pytorch-image-models/pytorch-image-models-master\"\nimport sys\nsys.path.append(timm_path)\nimport timm\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport sklearn\nimport os\nfrom tqdm.notebook import tqdm\n\nimport cv2\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset,DataLoader\nfrom torch import optim\n\nimport warnings\nwarnings.filterwarnings('ignore')\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"OUTPUT_DIR = './'\nif not os.path.exists(OUTPUT_DIR):\n    os.makedirs(OUTPUT_DIR)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train  =  pd.read_csv(\"../input/vinbigdata-chest-xray-abnormalities-detection/train.csv\") \nis_normal_df = train.groupby(\"image_id\")[\"class_id\"].agg(lambda s: (s == 14).sum()).reset_index().rename({\"class_id\": \"num_normal_annotations\"}, axis=1)\nis_normal_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"To understand this piece of code above go to the awesome notebook of @corochann https://www.kaggle.com/corochann/vinbigdata-2-class-classifier-complete-pipeline/notebook, this peice of code was taken from his notebook."},{"metadata":{"trusted":true},"cell_type":"code","source":"def change(x):\n    if (x==3):\n        x=1\n    return x\nis_normal_df['target'] = is_normal_df['num_normal_annotations'].apply(lambda x: change(x))\ndf = is_normal_df[[\"image_id\",\"target\"]]\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# splitting"},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import StratifiedKFold\nskf  =  StratifiedKFold(n_splits = 5, random_state = 42,shuffle = True)\nfolds = df.copy()\nfor f,(tr_idx,val_idx) in enumerate(skf.split(folds,folds.target)):\n    folds.loc[val_idx,'fold'] = int(f)\nfolds['fold'] = folds['fold'].astype(int)    \n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"folds.image_id=folds.image_id+\".png\"\nimg_path = \"../input/vinbigdata-chest-xray-resized-png-1024x1024/train\"\ndf_paths = [os.path.join(img_path,x) for x in folds.image_id]\nfolds['path'] = df_paths\nfolds.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Transforms"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_aug = A.Compose(\n    [  \n\n        A.Resize(300,300,p=1.0),\n        A.CLAHE(clip_limit=4.0, p=0.85),\n\n        A.Normalize(\n            p=1.0),\n        A.RandomCrop(width=250, height=250),\n        A.Rotate(limit=40, p=0.9),\n        A.HorizontalFlip(p=0.5),\n        A.VerticalFlip(p=0.5),\n        A.RGBShift(r_shift_limit=25, g_shift_limit=25, b_shift_limit=25),\n        A.OneOf(\n                [\n                 A.Blur(blur_limit=3, p=0.5),\n                 A.ColorJitter(p=0.5)\n                ], p=1.0),\n        A.Normalize(\n            p=1.0),\n        ToTensorV2(p=1.0)\n    ])\n\nval_aug = A.Compose(\n    [\n         A.Resize(300,300,p=1.0),\n         A.HorizontalFlip(p=0.5),\n         A.Normalize(\n            p=1.0),\n         ToTensorV2(p=1.0)\n    ]\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Xray(Dataset):\n    def __init__(self,df,augs=None):\n        self.df = df\n        self.augs = augs\n    def __len__(self):\n        return(len(self.df))\n    def __getitem__(self,idx):\n        img_src = self.df.loc[idx,'path']\n        image = cv2.imread(img_src)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.uint8)\n        \n        target = self.df.loc[idx,'target']\n        \n        if (self.augs):\n            transformed = self.augs(image=image)\n            image = transformed['image']\n        \n        return image,torch.tensor(target) \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data = Xray(folds,augs = train_aug)\nload = DataLoader(data,batch_size = 1)\nimg,target = next(iter(load))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.imshow(img.squeeze(0).permute(1,2,0))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Efficientnet b3 noisy student Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"model1=timm.create_model('resnext50d_32x4d', pretrained=True) # set pretrained=True to use the pretrained weights\nnum_features = model1.fc.in_features\nmodel1.fc = nn.Linear(num_features, 1)\nmodel1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model2=timm.create_model('resnext101_32x4d', pretrained=True) # set pretrained=True to use the pretrained weights\nnum_features = model2.fc.in_features\nmodel2.fc = nn.Linear(num_features, 1)\nmodel2","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model3=timm.create_model('inception_resnet_v2', pretrained=True) # set pretrained=True to use the pretrained weights\nnum_features = model3.classif.in_features\nmodel3.classif = nn.Linear(num_features, 1)\nmodel3","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model4=timm.create_model('resnet18', pretrained=True) # set pretrained=True to use the pretrained weights\nnum_features = model4.fc.in_features\nmodel4.fc = nn.Linear(num_features, 1)\nmodel4","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ss=F.sigmoid(model1(torch.randn(3,3,300,300)))\nss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ss=F.sigmoid(model2(torch.randn(3,3,300,300)))\nss","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ss=F.sigmoid(model3(torch.randn(3,3,300,300)))\nss","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Helping Functions"},{"metadata":{"trusted":true},"cell_type":"code","source":"class AverageMeter(object):\n    \"\"\"Computes and stores the average and current value\"\"\"\n    def __init__(self):\n        self.reset()\n\n    def reset(self):\n        self.val = 0\n        self.avg = 0\n        self.sum = 0\n        self.count = 0\n\n    def update(self, val, n=1):\n        self.val = val\n        self.sum += val * n\n        self.count += n\n        self.avg = self.sum / self.count","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def train_one_epoch(train_loader,model,optimizer,criterion,e,epochs):\n    losses = AverageMeter()\n    scores = AverageMeter()\n    model.train()\n    global_step = 0\n    loop = tqdm(enumerate(train_loader),total = len(train_loader))\n    \n    for step,(image,labels) in loop:\n        image = image.to(device)\n        labels = labels.unsqueeze(1)\n        labels= labels.to(device)\n        output = model(image)\n        batch_size = labels.size(0)\n        loss = criterion(output,labels.float())\n        \n        out = F.sigmoid(output)\n        outputs = out.cpu().detach().numpy()\n        targets = labels.cpu().detach().numpy()\n        try:\n            auc = sklearn.metrics.roc_auc_score(targets, outputs)\n            losses.update(loss.item(), batch_size)\n            scores.update(auc.item(), batch_size)\n            loss.backward()\n            optimizer.step()\n            optimizer.zero_grad()\n            global_step += 1\n        \n            loop.set_description(f\"Epoch {e+1}/{epochs}\")\n            loop.set_postfix(loss = loss.item(), auc = auc.item(), stage = 'train')\n        \n            \n        except ValueError:\n            pass\n        \n        \n       \n        \n    return losses.avg,scores.avg","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def val_one_epoch(loader,model,optimizer,criterion):\n    losses = AverageMeter()\n    scores = AverageMeter()\n    model.eval()\n    global_step = 0\n    loop = tqdm(enumerate(loader),total = len(loader))\n    \n    for step,(image,labels) in loop:\n        image = image.to(device)\n        labels = labels.unsqueeze(1)\n        labels = labels.to(device)\n        batch_size = labels.size(0)\n        with torch.no_grad():\n            output = model(image)\n        loss = criterion(output,labels.float())\n        \n        out = F.sigmoid(output)\n        outputs = out.cpu().detach().numpy()\n        targets = labels.cpu().detach().numpy()\n        try:\n            auc = sklearn.metrics.roc_auc_score(targets, outputs)\n            losses.update(loss.item(), batch_size)\n            scores.update(auc.item(), batch_size)\n            loop.set_postfix(loss = loss.item(), auc = auc.item(), stage = 'valid')\n            optimizer.step()\n            optimizer.zero_grad()\n            global_step += 1\n        except ValueError:\n            pass\n        \n        \n        \n        \n        \n    \n        \n    return losses.avg,scores.avg","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Training loop"},{"metadata":{"trusted":true},"cell_type":"code","source":"def fit(model,fold_n,training_batch_size=8,validation_batch_size=64):\n    \n    train_data=folds[folds.fold != fold_n]\n    val_data=folds[folds.fold == fold_n]\n    train_data= Xray(train_data.reset_index(drop=True),augs = train_aug)\n    val_data= Xray(val_data.reset_index(drop=True),augs = val_aug)\n    \n    \n    train_loader = DataLoader(train_data,\n                             shuffle=True,\n                        num_workers=0,\n                        batch_size=training_batch_size)\n    valid_loader = DataLoader(val_data,\n                             shuffle=False,\n                        num_workers=0,\n                        batch_size=validation_batch_size) \n    model = model\n    model.to(device)\n    criterion=nn.BCEWithLogitsLoss()\n    optimizer = optim.Adam(model.parameters(), lr=0.001)\n    scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer,patience = 3,verbose = True)\n    epochs= 1\n    \n    best_acc = 0\n    loop = range(epochs)\n    for e in loop:\n        \n        train_loss,train_auc = train_one_epoch(train_loader,model,optimizer,criterion,e,epochs) \n         ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fit(model1,0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fit(model2,0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fit(model3,0)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fit(model4,0)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Not training further epochs due to GPU constraints\n#To get a idea of this full pipeline, head over to https://www.kaggle.com/mrinath/another-simple-and-fast-pytorch-pipeline\n#say_my_name"},{"metadata":{},"cell_type":"markdown","source":"# Prediction:"},{"metadata":{"trusted":true},"cell_type":"code","source":"# test_meta = pd.read_csv('../input/vinbigdata-testmeta/test_meta.csv')\n\n# folds_test = test_meta.copy()\n# folds_test.image_id=folds.image_id+\".png\"\n# img_path = \"../input/vinbigdata-chest-xray-resized-png-1024x1024/train\"\n# df_paths = [os.path.join(img_path,x) for x in folds.image_id]\n# folds['path'] = df_paths\n# folds.head()\n\n# #dataset_dicts_test = get_vinbigdata_dicts_test(imgdir, test_meta, debug=debug)\n# test_dataset = Xray(test_data.reset_index(drop=True),augs = test_aug)\n# test_loader = DataLoader(\n#     test_dataset,\n#     batch_size=flags.valid_batchsize,\n#     num_workers=flags.num_workers,\n#     shuffle=False,\n#     pin_memory=True,\n# )\n# test_pred = classifier.predict_proba(test_loader).cpu().numpy()\n# test_pred_df = pd.DataFrame({\n#     \"image_id\": [d[\"image_id\"] for d in dataset_dicts_test],\n#     \"class0\": test_pred[:, 0],\n#     \"class1\": test_pred[:, 1]\n# })\n# test_pred_df.to_csv(outdir/\"test_pred.csv\", index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport cv2\nimport os\nimport re\nimport pydicom\nimport warnings\n\nfrom PIL import Image\n\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\n\nimport torch\nimport torchvision\n\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection import FasterRCNN\nfrom torchvision.models.detection.rpn import AnchorGenerator\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.utils.data.sampler import SequentialSampler\n\nfrom matplotlib import pyplot as plt\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df = pd.read_csv('../input/vinbigdata-chest-xray-abnormalities-detection/sample_submission.csv')\ntest_df.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class VinBigTestDataset(Dataset):\n    \n    def __init__(self, dataframe, image_dir, transforms=None):\n        super().__init__()\n        \n        self.image_ids = dataframe[\"image_id\"].unique()\n        self.df = dataframe\n        self.image_dir = image_dir\n        self.transforms = transforms\n        \n    def __getitem__(self, index):\n        \n        image_id = self.image_ids[index]\n        records = self.df[(self.df['image_id'] == image_id)]\n        records = records.reset_index(drop=True)\n\n        dicom = pydicom.dcmread(f\"{self.image_dir}/{image_id}.dicom\")\n        \n        image = dicom.pixel_array\n        \n        intercept = dicom.RescaleIntercept if \"RescaleIntercept\" in dicom else 0.0\n        slope = dicom.RescaleSlope if \"RescaleSlope\" in dicom else 1.0\n        if slope != 1:\n            image = slope * image.astype(np.float64)\n            image = image.astype(np.int16)\n            \n        image += np.int16(intercept)        \n        \n        image = np.stack([image, image, image])\n        image = image.astype('float32')\n        image = image - image.min()\n        image = image / image.max()\n        image = image * 255.0\n        image = image.transpose(1,2,0)\n       \n        if self.transforms:\n            sample = {\n                'image': image,\n            }\n            sample = self.transforms(**sample)\n            image = sample['image']\n        return image, image_id\n    \n    def __len__(self):\n        return self.image_ids.shape[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_test_transform():\n    return A.Compose([\n        A.Normalize(mean=(0, 0, 0), std=(1, 1, 1), max_pixel_value=255.0, p=1.0),\n        ToTensorV2(p=1.0)\n    ])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#get number of input features for the classifier\n#in_features = model1.roi_heads.box_predictor.cls_score.in_features","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DIR_TEST = '../input/vinbigdata-chest-xray-abnormalities-detection/test'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def collate_fn(batch):\n    return tuple(zip(*batch))\n\ntest_dataset = VinBigTestDataset(test_df, DIR_TEST, get_test_transform())\n\ntest_data_loader = DataLoader(\n    test_dataset,\n    batch_size=8,\n    shuffle=False,\n    num_workers=4,\n    drop_last=False,\n    collate_fn=collate_fn\n)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def format_prediction_string(labels, boxes, scores):\n    pred_strings = []\n    for j in zip(labels, scores, boxes):\n        pred_strings.append(\"{0} {1:.4f} {2} {3} {4} {5}\".format(\n            j[0], j[1], j[2][0], j[2][1], j[2][2], j[2][3]))\n\n    return \" \".join(pred_strings)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"detection_threshold = 0.5\nresults1 = []\nfor images, image_ids in test_data_loader:\n    images = torch.Tensor(list(image.to(device) for image in images))\n    outputs = model1(images)\n\nfor i, image in enumerate(images):\n    image_id = image_ids[i]\n\n    result1 = {\n        'image_id': image_id,\n        'PredictionString': '14 1.0 0 0 1 1'\n        }\n    boxes = outputs[i]['boxes'].data.cpu().numpy()\n    labels = outputs[i]['labels'].data.cpu().numpy()\n    scores = outputs[i]['scores'].data.cpu().numpy()\n    if len(boxes) > 0:\n\n        labels = labels - 1\n        labels[labels == -1] = 14\n        selected = scores >= detection_threshold\n        boxes = boxes[selected].astype(np.int32)\n        scores = scores[selected]\n        labels = labels[selected]\n    if len(boxes) > 0:\n        result1 = {\n            'image_id': image_id,\n            'PredictionString': format_prediction_string(labels, boxes, scores)\n        }\n    results1.append(result)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"detection_threshold = 0.5\nresults2 = [] \nwith torch.no_grad():\n    for images, image_ids in test_data_loader:\n\n        images = list(image.to(device) for image in images)\n        outputs = model2(images)\n\n        for i, image in enumerate(images):\n            image_id = image_ids[i]\n\n            result2 = {\n                'image_id': image_id,\n                'PredictionString': '14 1.0 0 0 1 1'\n            }\n            boxes = outputs[i]['boxes'].data.cpu().numpy()\n            labels = outputs[i]['labels'].data.cpu().numpy()\n            scores = outputs[i]['scores'].data.cpu().numpy()\n            if len(boxes) > 0:\n\n                labels = labels - 1\n                labels[labels == -1] = 14\n                selected = scores >= detection_threshold\n                boxes = boxes[selected].astype(np.int32)\n                scores = scores[selected]\n                labels = labels[selected]\n                if len(boxes) > 0:\n                    result2 = {\n                        'image_id': image_id,\n                        'PredictionString': format_prediction_string(labels, boxes, scores)\n                    }\n            results2.append(result)     ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"detection_threshold = 0.5\nresults3 = []\nwith torch.no_grad():\n    for images, image_ids in test_data_loader:\n\n        images = list(image.to(device) for image in images)\n        outputs = model3(images)\n\n        for i, image in enumerate(images):\n            image_id = image_ids[i]\n\n            result3 = {\n                'image_id': image_id,\n                'PredictionString': '14 1.0 0 0 1 1'\n            }\n            boxes = outputs[i]['boxes'].data.cpu().numpy()\n            labels = outputs[i]['labels'].data.cpu().numpy()\n            scores = outputs[i]['scores'].data.cpu().numpy()\n            if len(boxes) > 0:\n\n                labels = labels - 1\n                labels[labels == -1] = 14\n                selected = scores >= detection_threshold\n                boxes = boxes[selected].astype(np.int32)\n                scores = scores[selected]\n                labels = labels[selected]\n                if len(boxes) > 0:\n                    result3 = {\n                        'image_id': image_id,\n                        'PredictionString': format_prediction_string(labels, boxes, scores)\n                    }\n            results3.append(result)     ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"detection_threshold = 0.5\nresults4 = []\nwith torch.no_grad():\n    for images, image_ids in test_data_loader:\n\n        images = list(image.to(device) for image in images)\n        outputs = model4(images)\n\n        for i, image in enumerate(images):\n            image_id = image_ids[i]\n\n            result4 = {\n                'image_id': image_id,\n                'PredictionString': '14 1.0 0 0 1 1'\n            }\n            boxes = outputs[i]['boxes'].data.cpu().numpy()\n            labels = outputs[i]['labels'].data.cpu().numpy()\n            scores = outputs[i]['scores'].data.cpu().numpy()\n            if len(boxes) > 0:\n\n                labels = labels - 1\n                labels[labels == -1] = 14\n                selected = scores >= detection_threshold\n                boxes = boxes[selected].astype(np.int32)\n                scores = scores[selected]\n                labels = labels[selected]\n                if len(boxes) > 0:\n                    result4 = {\n                        'image_id': image_id,\n                        'PredictionString': format_prediction_string(labels, boxes, scores)\n                    }\n            results4.append(result)     ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pred = 0.25*result1 + 0.25*result2 + 0.25*result3 + 0.25*result4","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df = pd.DataFrame(pred, columns=['image_id', 'PredictionString'])\ntest_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df.to_csv('submission.csv', index=False)","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}