{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"%%capture\n!pip install ../input/rsnapkgs/timm-0.2.2-py3-none-any.whl\n!pip install ../input/pytorch-transformers/pytorch_transformers-1.2.0-py3-none-any.whl\n!cp ../input/gdcm-conda-install/gdcm.tar .\n!tar -xvzf gdcm.tar\n!conda install --offline ./gdcm/gdcm-2.8.9-py37h71b2a6d_0.tar.bz2\nprint(\"done\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import sys\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport platform\nimport os\nimport gc\nimport glob\nimport gdcm\nimport pydicom\nfrom PIL import Image\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom pathlib import Path\nimport cv2\nfrom collections import defaultdict\nimport sys\nimport torch\nfrom torch.backends import cudnn\nfrom torch.nn import DataParallel\nfrom torch.utils.data import DataLoader\nfrom tqdm import tqdm\nimport torch.distributed as dist\nimport platform\nfrom torch.utils.data import Dataset\nfrom torch.utils.data.sampler import Sampler\nimport albumentations as A\nfrom albumentations.pytorch import ToTensor\nfrom torch import nn\nfrom torch.nn.modules.dropout import Dropout\nfrom torch.nn.modules.linear import Linear\nfrom torch.nn.modules.pooling import AdaptiveAvgPool2d\nfrom pytorch_transformers.modeling_bert import BertConfig, BertEncoder\nimport torch.nn.functional as F\nfrom torch import nn\nPATH = '../input/rsnasubcheck'\nsys.path.append(PATH)\n\nPATH = '../input/rsnastr/rsnastr-master'\nsys.path.append(PATH)\nnp. set_printoptions(suppress=True)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from utils.utils import ip_window\nfrom utils.logs import get_logger\nfrom training.tools.config import load_config\nfrom training.zoo import classifiers\nfrom training.zoo.sequence import SpatialDropout, LSTMNet\nfrom utils.utils import RSNAWEIGHTS, RSNA_CFG as CFG\nfrom consistency_check import clean_sub, check_consistency\n\n#from training.zoo import classifiers\nlogger = get_logger('Kaggle', 'INFO') ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"conf = load_config(f'{PATH}/configs/512/effnetb5_lr5e4_multi.json')\nclass args:\n    device = 'cuda' if torch.cuda.is_available() else 'cpu'\n    batchsize = 1\n    imgbatchsize = 128\n    folds = [0,1,2]\n    lstm_units = 512\n    dropout = 0.0\n    load_train = False\n    do_full = True\n    delta = False\n    \nclass cfg:\n    dropout=0.2\n    hidden_size=2048\n    intermediate_size=2048\n    max_position_embeddings=1536\n    nlayers=1\n    nheads=8    \n    device=args.device\n    seed=7","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#### DataLoader"},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_val_transforms():\n    return A.Compose([\n        A.Normalize(mean=conf['normalize']['mean'], \n                    std=conf['normalize']['std'], max_pixel_value=255.0, p=1.0),\n        ToTensor()\n    ])\n\nclass RSNAImageSequenceDataset(Dataset):\n\n    def __init__(self, \n                 datadf,\n                 folddf,\n                 transforms, \n                 mode=\"train\"):\n        self.mode = mode\n        self.transform = transforms\n        self.datadf = datadf\n        self.folddf = folddf\n        self.imgclasses = CFG['image_target_cols']\n        self.studyclasses = CFG['exam_target_cols']\n\n    def __len__(self):\n        return len(self.folddf)\n\n    def __getitem__(self, idx):\n        # idx = 1\n        studyidx = self.folddf.iloc[idx].StudyInstanceUID\n        seriesidx = self.folddf.iloc[idx].SeriesInstanceUID\n        studydf = self.datadf.query('StudyInstanceUID == @studyidx')\\\n                        .query('SeriesInstanceUID == @seriesidx')\n        \n        imgs = []\n        imgnames = []\n        imglabels = []\n        if self.mode == 'train':\n            studylabels = studydf[self.studyclasses].iloc[0].values\n        for i, samp in studydf.reset_index().iterrows():\n            if self.mode == 'train':\n                imglabels.append(samp['pe_present_on_image'])\n            sampkey, img_name = self.image_file(samp)\n            try:\n                #dicom_object = pydicom.dcmread(img_name)\n                dicom_object = pydicom.read_file(img_name)\n                img = ip_window(dicom_object)\n            except:\n                img = np.zeros(shape=(512,512,3), dtype=np.uint8)\n            '''\n            augmented = self.transform(image=img)\n            img = augmented['image'].half()\n            '''\n            imgs.append(img)\n            imgnames.append(sampkey)\n        #imgs = torch.stack(imgs)\n        imgs = np.stack(imgs)\n        if self.mode == 'train':\n            labels = torch.tensor(imglabels)\n            return {'img_name': imgnames, 'image': imgs, 'imglabels': imglabels, 'studylabels': studylabels}\n        return {'img_name': imgnames, 'image': imgs}\n    \n    def image_file(self, samp):\n        sampkey = '/'.join([samp.StudyInstanceUID, samp.SeriesInstanceUID,samp.SOPInstanceUID])\n        imgname = os.path.join('../input/rsna-str-pulmonary-embolism-detection', \n                                self.mode,\n                                sampkey) + '.dcm'\n        return sampkey, imgname\n\ndef collateimgfn(batch):\n    \n    maxlen = max([l['image'].shape[0] for l in batch])\n    for b in batch:\n        masklen = maxlen-len(b['image'])\n        b['mask'] = np.ones((maxlen))\n        b['mask'][:masklen] = 0\n    \n    outbatch = {'image': np.concatenate([b['image'] for b in batch], 0)}\n    outbatch['mask'] = torch.tensor(np.vstack([np.expand_dims(b['mask'], 0) \\\n                                                for b in batch])).float()\n    outbatch['img_name'] = []\n    for b in batch:\n        outbatch['img_name'] += b['img_name'] \n        \n    if 'imglabels' in batch[0]:\n        for b in batch:\n            masklen = maxlen-len(b['image'])\n            b['imglabelsout'] = np.ones((maxlen))*-1\n            b['imglabelsout'][masklen:] = b['imglabels']\n        outbatch['imglabels'] = torch.tensor(np.vstack([np.expand_dims(b['imglabelsout'], 0) \\\n                                                for b in batch])).long()\n        outbatch['studylabels'] = torch.tensor(np.vstack([np.expand_dims(b['studylabels'], 0) \\\n                                                for b in batch])).long()\n    return outbatch\n\nclass TransformerNet(nn.Module):\n    def __init__(self, \n                 cfg, \n                 nimgclasses = 1, \n                 nstudyclasses = 9):\n        super(TransformerNet, self).__init__()\n        \n        self.nimgclasses = nimgclasses\n        self.nstudyclasses = nstudyclasses\n        self.cfg = cfg\n\n        self.config = BertConfig( \n            3, # not used\n            hidden_size=cfg.hidden_size,\n            num_hidden_layers=cfg.nlayers,\n            num_attention_heads=cfg.nheads,\n            max_position_embeddings=cfg.max_position_embeddings, \n            intermediate_size=cfg.intermediate_size,\n            hidden_dropout_prob=cfg.dropout,\n            attention_probs_dropout_prob=cfg.dropout,\n        )\n        \n        self.encoder = BertEncoder(self.config).to(cfg.device)\n\n        self.img_linear_out = nn.Linear(cfg.hidden_size, self.nimgclasses)\n        self.study_linear_out = nn.Linear(cfg.hidden_size, self.nstudyclasses)\n        \n    def extended_mask(self, mask):\n        # Prep mask\n        extended_attention_mask = mask.unsqueeze(1).unsqueeze(2)\n        extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0\n        head_mask = [None] * self.cfg.nlayers\n        \n        return extended_attention_mask, head_mask\n        \n    def forward(self, x, mask, lengths=None):\n        \n        extended_attention_mask, head_mask =  extended_mask( mask )\n        \n        # Pass thru encoder\n        encoded_layers = encoder(x, extended_attention_mask, head_mask=head_mask)\n        sequence_output = encoded_layers[-1]\n        \n        # Pass output to a linear layer\n        img_output = self.img_linear_out(sequence_output).squeeze()\n        study_output = self.study_linear_out(sequence_output[:, -1]).squeeze()\n        \n        return study_output, img_output\n\ndef batchPredsfn(studypreds, imgpreds, imgnames):\n    preds = []\n    batchdf = pd.DataFrame([i.split('/') for i in imgnames], \n                           columns = ['StudyInstanceUID', 'SeriesInstanceUID','SOPInstanceUID'])\n    studies = batchdf.StudyInstanceUID.unique().tolist()\n    for study, row in zip(studies, studypreds):\n        for col, pred in zip(CFG['exam_target_cols'], row):\n            preds.append([f'{study}_{col}', pred])\n    for nm, pred in zip(batchdf.SOPInstanceUID, imgpreds):\n        preds.append([nm, pred])\n    return preds\n\ndef aug_batch(imgs, augfn = create_val_transforms()):\n    imgbatch = []\n    for i in imgs:\n        augmented = augfn(image=i)\n        i = augmented['image'].half()\n        imgbatch.append(i)\n    imgbatch = torch.stack(imgbatch)\n    return imgbatch\n\ndef aug_batch1(imgs, mean_, std_, device):\n    imgs = imgs.to(device).float()\n    return (((imgs / 255) - mean_) / std_).permute(0, 3, 1, 2).half()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!cp ../input/rsna-str-pulmonary-embolism-detection/sample_submission.csv submission.csv\nif args.load_train:\n    trndf = pd.read_csv('../input/rsna-str-pulmonary-embolism-detection/train.csv')\nif os.path.exists('../input/rsna-str-pulmonary-embolism-detection/train') and not args.do_full:\n    tstdf = pd.read_csv('../input/rsna-str-pulmonary-embolism-detection/test.csv').head(2000)\nelse:\n    tstdf = pd.read_csv('../input/rsna-str-pulmonary-embolism-detection/test.csv')\n\nkeycols = ['StudyInstanceUID', 'SeriesInstanceUID']\nDEBUG = (tstdf.shape[0]==146853)\nDEBUG","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"loaderargs = {'num_workers' : 4, 'pin_memory': False, 'drop_last': False, 'collate_fn' : collateimgfn}\nif args.load_train:\n    trndataset = RSNAImageSequenceDataset(mode = 'train', \n                                folddf = trndf[keycols].drop_duplicates().reset_index(drop=True), \n                                datadf = trndf, \n                                transforms = create_val_transforms())\n    trnloader = DataLoader(trndataset, batch_size=args.batchsize, shuffle=False, **loaderargs)\n    \ntstdataset = RSNAImageSequenceDataset(mode = 'test', \n                                folddf = tstdf[keycols].drop_duplicates().reset_index(drop=True), \n                                datadf = tstdf, \n                                transforms = create_val_transforms())\ntstloader = DataLoader(tstdataset, batch_size=args.batchsize, shuffle=False, **loaderargs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_image_model(wtsnm, device = args.device):\n    nclasses = len(conf[\"image_target_cols\"]) + len(conf['exam_target_cols'])\n    model = classifiers.__dict__[conf['network']](encoder=f\"{conf['encoder']}_infer\",\n                                                  nclasses = nclasses,\n                                                 infer = True)\n    checkpoint = torch.load(wtsnm, map_location=torch.device(device))\n    model.load_state_dict(checkpoint['state_dict'])\n    model = model.half().to(device)\n    model = model.eval()\n    return model\n\ndef load_exam_model(wtsnm, embed_size = 2048, device = args.device):\n    model = LSTMNet(embed_size, \n                       nimgclasses = len(CFG[\"image_target_cols\"]), \n                       nstudyclasses = len(CFG['exam_target_cols']),\n                       LSTM_UNITS=args.lstm_units, \n                       DO = args.dropout)\n    checkpoint = torch.load(wtsnm, map_location=torch.device(device))\n    model.load_state_dict(checkpoint)\n    model = model.half().to(device)\n    model = model.eval()\n    return model\n\n\ndef load_exam_modelx(wtsnm, cfg, device = args.device):\n    model = TransformerNet(cfg)\n    checkpoint = torch.load(wtsnm, map_location=torch.device(device))\n    model.load_state_dict(checkpoint)\n    model = model.half().to(device)\n    model = model.eval()\n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Load image model\nimgmodels = {}\nfor fold in args.folds:\n    wtsnm = f'../input/rsna512effnetb5/classifier_RSNAClassifier_tf_efficientnet_b5_ns_04d_{fold}__nclasses1_fold{fold}_epoch20'\n    wtsnm = f'../input/rsna512effnetb5examwts/classifier_RSNAClassifier_tf_efficientnet_b5_ns_04d_{fold}__nclasses10_size512_fold{fold}_epoch20'\n    logger.info(f'Load image model : {wtsnm}')\n    imgmodels[fold] = load_image_model(wtsnm, device = args.device)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Load image model\nexammodels = defaultdict(list)\nembed_size = 2048\nif args.delta:\n    embed_size *= 3\nfor fold in args.folds:\n    for epoch in [12]: #[10, 12]:\n        #wtsnm = '../input/rsnalstmb5x512dense/exam_lstm_classifier_RSNAClassifier_tf_efficientnet'\n        #wtsnm += f'_b5_ns_04d_{fold}__nclasses1_fold{fold}_epoch20__all_size512__epoch{epoch}.bin'\n        wtsnm = '../input/rsna512lstmb5examwts/exam_lstm_classifier_RSNAClassifier_tf_efficientnet'\n        wtsnm += f'_b5_ns_04d_{fold}__nclasses10_size512_fold{fold}_epoch20__all_size512__epoch{epoch}.bin'\n        logger.info(f'Load exam model : {wtsnm}')\n        exammodels[fold].append( load_exam_model(wtsnm, embed_size = embed_size, device = args.device) )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Load exam model\nexammodelsx = defaultdict(list)\nfor fold in args.folds:\n    for epoch in [12]:\n        #wtsnm = '../input/rsna512transformerb5accum/exam_transformer_classifier_RSNAClassifier_tf_efficientnet'\n        #wtsnm += f'_b5_ns_04d_{fold}__nclasses10_size512_accum4_fold{fold}_epoch15__all_size512__epoch{epoch}.bin'\n        wtsnm = '../input/rsna512lstmb5examwts/exam_transformer_classifier_RSNAClassifier_tf_efficientnet'\n        wtsnm += f'_b5_ns_04d_{fold}__nclasses10_size512_fold{fold}_epoch20__all_size512_nlayers1_hidden2048__epoch{epoch}.bin'\n        logger.info(f'Load exam model : {wtsnm}')\n        exammodelsx[fold].append( load_exam_modelx(wtsnm, cfg, device = args.device) )\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# sub = []\n# batch = next(iter(trnloader))\n\nsubdf =  pd.read_csv('../input/rsna-str-pulmonary-embolism-detection/sample_submission.csv')\nsubdf = subdf.set_index('id')\npbar = tqdm(enumerate(tstloader), total = 1 + len(tstdataset)//tstloader.batch_size, ncols=0)\nmean_ =  torch.tensor(conf['normalize']['mean'])[None, None, None, :].to(args.device)\nstd_  =  torch.tensor(conf['normalize']['std'])[None, None, None, :].to(args.device)\n\nfor step, batch in pbar:\n    try:\n        # Add in a loop here for dataloader\n        emb = defaultdict(list)\n        studypredsls = []\n        imgpredsls = []\n        embbatch = {}\n        imgs = torch.tensor(batch[\"image\"])\n        imgnames = batch['img_name']\n        mask = batch['mask'].half().to(args.device)\n        # Split the batch into chunks and infer all the images\n        for imgchunk in torch.split(imgs, args.imgbatchsize, dim=0):\n            # imgchunk = aug_batch(imgchunk.numpy())\n            imgchunk = aug_batch1(imgchunk, mean_, std_, args.device)\n            imgchunk = imgchunk.to(args.device)\n            with torch.no_grad():\n                for fold in args.folds:\n                    emb[fold].append(imgmodels[fold](imgchunk))\n        del imgchunk, imgs, batch\n        # Line up the embedding in single 2d array\n        for fold in args.folds:\n            emb[fold] = torch.cat(emb[fold], 0)\n            # Use the mask to populate in (batch, maxlen of images, emb dim)\n            embbatch[fold] = torch.zeros(len(mask.flatten()), emb[fold].shape[-1]).half().to(args.device)\n            embbatch[fold][mask.flatten()==1] = emb[fold]\n            embbatch[fold] = embbatch[fold].reshape((*mask.shape, emb[fold].shape[-1]))\n            del emb[fold]\n            for mod in exammodels[fold]:\n                with torch.no_grad():\n                    studylogits, imglogits = mod(embbatch[fold], mask)\n                # Unmask the images\n                imglogits = imglogits.flatten()[(mask==1).flatten()]\n                # Detach and create out sub\n                studypredsls.append( torch.sigmoid(studylogits).detach().cpu().numpy())\n                imgpredsls.append( torch.sigmoid(imglogits).detach().cpu().numpy())\n            try:\n                for mod in exammodelsx[fold]:\n                    with torch.no_grad():\n                        encoded_layers = mod.encoder(embbatch[fold], *mod.extended_mask(mask ))\n                        imglogits = mod.img_linear_out(encoded_layers[-1]).squeeze()\n                        studylogits = mod.study_linear_out(encoded_layers[-1][:, -1]).squeeze()\n                    # Unmask the images\n                    imglogits = imglogits.flatten()[(mask==1).flatten()]\n                    # Detach and create out sub\n                    studypredsls.append( torch.sigmoid(studylogits).detach().cpu().numpy())\n                    imgpredsls.append( torch.sigmoid(imglogits).detach().cpu().numpy())\n            except:\n                logger.info(f'Transformer failed ...{e}')\n            \n        # Bag the batch\n        studypreds = sum(studypredsls)/len(studypredsls)\n        imgpreds = sum(imgpredsls)/len(imgpredsls)\n        subbatch = batchPredsfn(studypreds, imgpreds, imgnames)\n        subbatch = pd.DataFrame(subbatch, columns = ['id', 'label'])\n        subdf.loc[subbatch.id, 'label'] = subbatch.label.values\n        del mask, embbatch, imglogits, studylogits\n    except Exception as e:\n        logger.info(f'Failed ...{e}')\n    if step % 1 == 0:\n        torch.cuda.empty_cache()\n    if step % 5 == 0:\n        gc.collect()\nsubdf = subdf.reset_index()\nsuborig = subdf.copy()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"tstdf = pd.read_csv('../input/rsna-str-pulmonary-embolism-detection/test.csv')\nsubdf = clean_sub(subdf, tstdf)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"errors = check_consistency(subdf, tstdf)\nif errors.shape[0] == 0:\n    subdf.to_csv('submission.csv', index = False)\nelse:\n    print(errors.broken_rule.value_counts())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(subdf.shape)\nsubdf.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"((subdf.label - suborig.label)!=0).value_counts()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"(subdf.label - suborig.label)[(subdf.label - suborig.label)!=0].hist(bins = 100)","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}