{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Baseline VggNet\nThis competition has sparked debates over how the CT images  can be efficiently handled by deep learning models such as whether or not to use Windowing or the usage of good preprocessing technique. In this kernel, an attempt is made to describe the output based on more older and smaller VggNet19 with batch normalization. The rationale behind this is to assess the model performance over different parallel techniques without burning out GPU kernel time. I would like to thank @braquino from where most of the code base is derived."},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd \nfrom glob import glob\nfrom tqdm import tqdm\nfrom sklearn.metrics import precision_score, recall_score\nimport gc\n\n# Imaging libraries\nimport seaborn as sns; sns.set()\nimport pydicom\nimport matplotlib.pyplot as plt\nimport cv2\n\n# Deep learning libraries\nimport torch.optim as optim\nimport torch \nimport torchvision.models as models\nfrom torch.utils.data import Dataset","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"BASE_PATH = '/kaggle/input/rsna-intracranial-hemorrhage-detection/'\nTRAIN_DIR = 'stage_1_train_images/'\nTEST_DIR = 'stage_1_test_images/'\n\nTRAIN_CSV = 'stage_1_train.csv'\nTEST_CSV = 'stage_1_sample_submission.csv'\n\nMODEL_PATH = '/kaggle/input/baseline-vggnet/vggNet19.pth'\nTRAIN_CSV_PATH = os.path.join(BASE_PATH, TRAIN_CSV)\nTEST_CSV_PATH = os.path.join(BASE_PATH, TEST_CSV)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Prepare the training data"},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train = pd.read_csv(TRAIN_CSV_PATH)\ndf_train[['id', 'img', 'subtype']] = df_train['ID'].str.split('_', n=3, expand=True)\ndf_train['img'] = 'ID_' + df_train['img'] \n\ndf_train.drop_duplicates(inplace=True)\ndf_train = df_train.pivot(index='img', columns='subtype', values='Label').reset_index()\ndf_train['path'] = os.path.join(BASE_PATH, TRAIN_DIR) + df_train['img'] + '.dcm'\n\n# Only include valid images\nlegit_images = pd.read_csv('/kaggle/input/true-imagescsv/legit-images.csv')\ndf_train = df_train.merge(legit_images, left_on='img', right_on='0')\ndf_train.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Prepare the test data"},{"metadata":{"trusted":true},"cell_type":"code","source":"df_test = pd.read_csv(TEST_CSV_PATH)\ndf_test[['id','img','subtype']] = df_test['ID'].str.split('_', expand=True)\ndf_test['img'] = 'ID_' + df_test['img']\ndf_test = df_test[['img', 'Label']]\ndf_test['path'] = os.path.join(BASE_PATH, TEST_DIR) + df_test['img'] + '.dcm'\ndf_test.drop_duplicates(inplace=True)\n\ndf_test = df_test.reset_index(drop=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class RSNADataset(Dataset):\n  def __init__(self, df, labels):\n        self.data = df\n        self.labels = labels\n\n  def __len__(self):\n        return len(self.data)\n\n  def __getitem__(self, index):\n        \n        img_name = self.data.loc[index, 'path']   \n        img = pydicom.read_file(img_name).pixel_array.astype('float32')\n        img = cv2.resize(img, (224,224))\n\n        img = np.stack((img,)*3, axis=-1)\n        img = np.transpose(img, (2, 1, 0))\n    \n                \n        if self.labels:        \n            labels = torch.tensor(\n                self.data.loc[index, ['epidural', 'intraparenchymal', 'intraventricular', 'subarachnoid', 'subdural', 'any']])\n            return {'image': img, 'labels': labels}   \n        else:\n            return {'image': img}\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"params = {'batch_size': 64,\n          'shuffle': False,\n          'num_workers': 4}\n\ntrain_dataset = RSNADataset(df= df_train, labels=True)\ntest_dataset = RSNADataset(df= df_test, labels=False)\n\ndata_train_generator = torch.utils.data.DataLoader(train_dataset, **params)\ndata_test_generator = torch.utils.data.DataLoader(test_dataset,**params)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"batch = next(iter(data_train_generator))\nfig, axs = plt.subplots(1, 3, figsize=(15,5))\n\nfor i in np.arange(3):\n    \n    axs[i].imshow(batch['image'][i][0].numpy(), cmap=plt.cm.bone)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Model and training"},{"metadata":{"trusted":true},"cell_type":"code","source":"device = torch.device(\"cuda:0\")\nmodel0 = models.vgg19_bn()\n\nmodel = torch.nn.Sequential(model0, torch.nn.Linear(1000, 6) ) \n\nmodel = model.to(device)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"n_epochs = 3\ncriterion = torch.nn.BCEWithLogitsLoss()\noptimizer = optim.Adam(model.parameters(), lr=2e-5)\n\ndef weights_init_uniform_rule(m):\n    classname = m.__class__.__name__\n    # for every Linear layer in a model..\n    if classname.find('Linear') != -1:\n        # get the number of the inputs\n        n = m.in_features\n        y = 1.0/np.sqrt(n)\n        m.weight.data.uniform_(-y, y)\n        m.bias.data.fill_(0)\n\n# Load weights of the last trained model or create a new model with random weights \ntry:\n    model.load_state_dict(torch.load(MODEL_PATH))\n    print(f'loaded the model at {MODEL_PATH}')\nexcept Exception as e:\n    model = model.apply(weights_init_uniform_rule)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for epoch in range(1, n_epochs+1):\n    \n    print('Epoch {}/{}'.format(epoch, n_epochs))\n    print('-' * 10)\n\n    model.train()    \n    tr_loss = 0\n    \n    tk0 = tqdm(data_train_generator, desc=\"Iteration\")\n    \n    for step, batch in enumerate(tk0):\n        \n        inputs = batch[\"image\"]\n        labels = batch[\"labels\"]\n\n        inputs = inputs.to(device, dtype=torch.float)\n        labels = labels.to(device, dtype=torch.float)\n\n        outputs = model(inputs)\n        loss = criterion(outputs, labels)\n\n        loss.backward()\n\n        tr_loss += loss.item()\n\n        optimizer.step()\n        optimizer.zero_grad()\n            \n\n    epoch_loss = tr_loss / len(data_train_generator)\n    print('Training Loss: {:.4f}'.format(epoch_loss))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Saving the model\ntorch.save(model.state_dict(), 'vggNet19-1.pth') ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for param in model.parameters():\n    param.requires_grad = False\n\nmodel.eval()\n\ntest_pred = np.zeros((len(test_dataset) * 6, 1))\n\nfor i, batch_ in enumerate(tqdm(data_test_generator)):\n    batch_ = batch_[\"image\"]\n    batch_ = batch_.to(device, dtype=torch.float)\n    \n    with torch.no_grad():\n        \n        pred = model(batch_)\n        \n        test_pred[(i * 64 * 6):((i + 1) * 64 * 6)] = torch.sigmoid(\n            pred).detach().cpu().reshape((len(batch_) * 6, 1))  ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Preparing the submission"},{"metadata":{"trusted":true},"cell_type":"code","source":"submission =  pd.read_csv(TEST_CSV_PATH)\nsubmission = pd.concat([submission.drop(columns=['Label']), pd.DataFrame(test_pred)], axis=1)\nsubmission.columns = ['ID', 'Label']\n\nsubmission.to_csv('submission-1.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":1}