{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":112899,"databundleVersionId":13449579,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":601445,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":450725,"modelId":467076},{"sourceId":601486,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":450725,"modelId":467076}],"dockerImageVersionId":31154,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# <p style = \"background-color:#4A6274; text-align: center; font-weight: bolder; color: #F9DDD2 \"><br>Thoracic Disease Pridiction <br><br><p>","metadata":{}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nfrom PIL import Image\n\nimport warnings\nwarnings.filterwarnings('ignore')\npd.set_option('display.max_columns', None)\n\n# /kaggle/input/grand-xray-slam-division-a/sample_submission_1.csv\n# /kaggle/input/grand-xray-slam-division-a/train1.csv","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:28.986815Z","iopub.execute_input":"2025-10-09T11:53:28.987119Z","iopub.status.idle":"2025-10-09T11:53:31.881151Z","shell.execute_reply.started":"2025-10-09T11:53:28.987091Z","shell.execute_reply":"2025-10-09T11:53:31.880351Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CFG:\n    test  = \"/kaggle/input/grand-xray-slam-division-a/test1/\"\n    train = \"/kaggle/input/grand-xray-slam-division-a/train1/\"\n    modv1 = \"/kaggle/input/chexnet14/pytorch/v-01/1/model.pth.tar\"\n    modv2 = \"/kaggle/input/chexnet14/pytorch/v-01/2/model.pth\"\n    EPOCHS = 500\n    n_classes = 14\n    diseases = [\n        'Atelectasis', 'Cardiomegaly', 'Consolidation', 'Edema',\n        'Enlarged Cardiomediastinum', 'Fracture', 'Lung Lesion',\n        'Lung Opacity','No Finding', 'Pleural Effusion', 'Pleural Other',\n        'Pneumonia', 'Pneumothorax', 'Support Devices'\n    ]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:31.881969Z","iopub.execute_input":"2025-10-09T11:53:31.882302Z","iopub.status.idle":"2025-10-09T11:53:31.888467Z","shell.execute_reply.started":"2025-10-09T11:53:31.882274Z","shell.execute_reply":"2025-10-09T11:53:31.88777Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/grand-xray-slam-division-a/train1.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:31.891794Z","iopub.execute_input":"2025-10-09T11:53:31.892138Z","iopub.status.idle":"2025-10-09T11:53:32.278101Z","shell.execute_reply.started":"2025-10-09T11:53:31.892111Z","shell.execute_reply":"2025-10-09T11:53:32.277167Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train.head(2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:32.279005Z","iopub.execute_input":"2025-10-09T11:53:32.279241Z","iopub.status.idle":"2025-10-09T11:53:32.392774Z","shell.execute_reply.started":"2025-10-09T11:53:32.279221Z","shell.execute_reply":"2025-10-09T11:53:32.391975Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Exploratory Data Analysis","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize = (10, 5))\nsns.distplot(train['Age']);\nplt.title(\"Age Distribution\", loc = 'center', pad = 10, fontdict = {\"size\" : 15, 'weight': 'bold', 'color': \"#c9a02c\"})\nplt.show();","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:32.394116Z","iopub.execute_input":"2025-10-09T11:53:32.394476Z","iopub.status.idle":"2025-10-09T11:53:33.189128Z","shell.execute_reply.started":"2025-10-09T11:53:32.394443Z","shell.execute_reply":"2025-10-09T11:53:33.188132Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"j = iter([[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6],\n          [1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6]])\n\nfig, axes = plt.subplots(nrows=2, ncols=7, figsize=(30, 7));\nfig.suptitle('Age Distribution on each Disease', fontsize=20)\n\nfor i in CFG.diseases:\n    index = next(j)\n    sns.boxplot(data = train, y = 'Age', x = i, ax = axes[*index]);\n    axes[*index].set_title(i)\n    axes[*index].set_xlabel(None)\n    axes[*index].legend().remove()\n    \nplt.subplots_adjust(top=0.9)\nplt.show();","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:33.190297Z","iopub.execute_input":"2025-10-09T11:53:33.190744Z","iopub.status.idle":"2025-10-09T11:53:35.044006Z","shell.execute_reply.started":"2025-10-09T11:53:33.190721Z","shell.execute_reply":"2025-10-09T11:53:35.043144Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sns.histplot(train['Sex'], color = '#526958');\nplt.title(\"Sex Distribution\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:35.044962Z","iopub.execute_input":"2025-10-09T11:53:35.045214Z","iopub.status.idle":"2025-10-09T11:53:35.327425Z","shell.execute_reply.started":"2025-10-09T11:53:35.045193Z","shell.execute_reply":"2025-10-09T11:53:35.326471Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"j = iter([[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6],\n          [1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6]])\n\nfig, axes = plt.subplots(nrows=2, ncols=7, figsize=(30, 7));\nfig.suptitle('Normalized Stacked Barplot for Sex distribution', fontsize=20)\n\ndef normalize(i):\n    temp = pd.DataFrame(train[['Sex', i]].groupby(by = ['Sex', i]).size(), columns = ['values']).reset_index()\n    temp_tot = (temp['values'][0] +  temp['values'][1])\n    temp['values'][0] = temp['values'][0]/temp_tot\n    temp['values'][1] = temp['values'][1]/temp_tot\n    temp_tot = (temp['values'][2] +  temp['values'][3])\n    temp['values'][2] = temp['values'][2]/temp_tot\n    temp['values'][3] = temp['values'][3]/temp_tot\n    return temp\n\nfor i in CFG.diseases:\n    index = next(j)\n    temp = normalize(i)\n    sns.histplot(data = temp, x = 'Sex', hue = i, weights = 'values', ax = axes[*index], multiple = 'stack');\n    axes[*index].set_title(i)\n    axes[*index].set_xlabel(None)\n    axes[*index].legend().remove()\n    \nplt.subplots_adjust(top=0.9)\nplt.show();\n\n# There is no influence of Gender in getting the Disease","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:35.328385Z","iopub.execute_input":"2025-10-09T11:53:35.328779Z","iopub.status.idle":"2025-10-09T11:53:37.569991Z","shell.execute_reply.started":"2025-10-09T11:53:35.328757Z","shell.execute_reply":"2025-10-09T11:53:37.569095Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# How many patients are suffering from each Disease?\ntrain.drop_duplicates(subset = ['Patient_ID'], keep = 'last')[CFG.diseases].sum(axis = 0)\n\n# Note: `Pnuemothorax` and `Pleural Other` are rare disease and hard to classify","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:37.572599Z","iopub.execute_input":"2025-10-09T11:53:37.572847Z","iopub.status.idle":"2025-10-09T11:53:37.589697Z","shell.execute_reply.started":"2025-10-09T11:53:37.572827Z","shell.execute_reply":"2025-10-09T11:53:37.58897Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# How many patients are there with more than on Disease?\ntrain.drop_duplicates(subset = ['Patient_ID'], keep = 'last')[CFG.diseases].sum(axis = 1).value_counts().sort_index()\n\n# Note: Multi-label classification is needed because there are patients suffering with more than one disease","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:37.59043Z","iopub.execute_input":"2025-10-09T11:53:37.59065Z","iopub.status.idle":"2025-10-09T11:53:37.615107Z","shell.execute_reply.started":"2025-10-09T11:53:37.590631Z","shell.execute_reply":"2025-10-09T11:53:37.61438Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def print_img(i):\n    img = Image.open(f'{CFG.train}{i}');\n    plt.imshow(img);","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:37.616004Z","iopub.execute_input":"2025-10-09T11:53:37.61623Z","iopub.status.idle":"2025-10-09T11:53:37.620887Z","shell.execute_reply.started":"2025-10-09T11:53:37.616212Z","shell.execute_reply":"2025-10-09T11:53:37.620099Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print_img(train['Image_name'][0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:37.621666Z","iopub.execute_input":"2025-10-09T11:53:37.621883Z","iopub.status.idle":"2025-10-09T11:53:38.927605Z","shell.execute_reply.started":"2025-10-09T11:53:37.621866Z","shell.execute_reply":"2025-10-09T11:53:38.926674Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Load Model","metadata":{}},{"cell_type":"code","source":"import os\n\nimport torch\nimport torch.nn as nn\nimport torchvision\nimport torchvision.transforms as transforms\nfrom torch.utils.data import Dataset, DataLoader\nimport torch.backends.cudnn as cudnn\n\nfrom sklearn.model_selection import train_test_split\n\n\nfrom torchinfo import summary","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:38.928534Z","iopub.execute_input":"2025-10-09T11:53:38.928754Z","iopub.status.idle":"2025-10-09T11:53:46.726042Z","shell.execute_reply.started":"2025-10-09T11:53:38.928736Z","shell.execute_reply":"2025-10-09T11:53:46.72526Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img = Image.open(f\"{CFG.train}{train['Image_name'][0]}\").convert(\"RGB\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:46.727166Z","iopub.execute_input":"2025-10-09T11:53:46.727727Z","iopub.status.idle":"2025-10-09T11:53:46.85132Z","shell.execute_reply.started":"2025-10-09T11:53:46.727698Z","shell.execute_reply":"2025-10-09T11:53:46.850445Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(img);","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:46.852169Z","iopub.execute_input":"2025-10-09T11:53:46.852664Z","iopub.status.idle":"2025-10-09T11:53:48.828279Z","shell.execute_reply.started":"2025-10-09T11:53:46.852636Z","shell.execute_reply":"2025-10-09T11:53:48.827185Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## DataLoader","metadata":{}},{"cell_type":"code","source":"class cdataset(Dataset):\n    def __init__(self, X, y):\n        self.X = X\n        self.y = y\n    def __len__(self):\n        return len(self.X)        \n    def __getitem__(self, index):\n        img = Image.open(f\"{CFG.train}{self.X.iloc[index]}\").convert(\"RGB\")\n        transform = transforms.Compose([\n            transforms.Resize((224, 224)),\n            transforms.ToTensor(),\n        ])\n        img_tensor = transform(img) #.unsqueeze(0)\n        return img_tensor, self.y[index]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:48.82942Z","iopub.execute_input":"2025-10-09T11:53:48.82972Z","iopub.status.idle":"2025-10-09T11:53:48.837302Z","shell.execute_reply.started":"2025-10-09T11:53:48.829696Z","shell.execute_reply":"2025-10-09T11:53:48.836335Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train, X_test, y_train, y_test = train_test_split(train['Image_name'], train[CFG.diseases], test_size = 0.2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:48.83836Z","iopub.execute_input":"2025-10-09T11:53:48.838761Z","iopub.status.idle":"2025-10-09T11:53:48.920985Z","shell.execute_reply.started":"2025-10-09T11:53:48.838735Z","shell.execute_reply":"2025-10-09T11:53:48.920021Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_train = torch.from_numpy(y_train.to_numpy().astype(np.float32))\ny_test  = torch.from_numpy(y_test.to_numpy().astype(np.float32))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:48.921902Z","iopub.execute_input":"2025-10-09T11:53:48.922208Z","iopub.status.idle":"2025-10-09T11:53:48.92889Z","shell.execute_reply.started":"2025-10-09T11:53:48.922174Z","shell.execute_reply":"2025-10-09T11:53:48.928028Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset = cdataset(X_train, y_train)\ntest_dataset = cdataset(X_test, y_test)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:48.929823Z","iopub.execute_input":"2025-10-09T11:53:48.930229Z","iopub.status.idle":"2025-10-09T11:53:48.942715Z","shell.execute_reply.started":"2025-10-09T11:53:48.930176Z","shell.execute_reply":"2025-10-09T11:53:48.941773Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dl_train = DataLoader(train_dataset, batch_size=8, shuffle=True,)\ndl_test  = DataLoader( test_dataset, batch_size=8, shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:48.943697Z","iopub.execute_input":"2025-10-09T11:53:48.94401Z","iopub.status.idle":"2025-10-09T11:53:48.959187Z","shell.execute_reply.started":"2025-10-09T11:53:48.943983Z","shell.execute_reply":"2025-10-09T11:53:48.958127Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class DenseNet121(nn.Module):\n    \"\"\"\n    Model modified.\n    ``````````````\n    The architecture of our model is the same as standard DenseNet121\n    except the classifier layer which has an additional sigmoid function.\n\n    \"\"\"\n    def __init__(self, out_size):\n        super(DenseNet121, self).__init__()\n        self.densenet121 = torchvision.models.densenet121(pretrained=False)\n        num_ftrs = self.densenet121.classifier.in_features\n        self.densenet121.classifier = nn.Sequential(\n            nn.Linear(num_ftrs, out_size),\n            nn.Sigmoid()\n        )\n\n    def forward(self, x):\n        x = self.densenet121(x)\n        return x","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:48.960291Z","iopub.execute_input":"2025-10-09T11:53:48.960716Z","iopub.status.idle":"2025-10-09T11:53:48.975383Z","shell.execute_reply.started":"2025-10-09T11:53:48.960687Z","shell.execute_reply":"2025-10-09T11:53:48.974433Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:48.976266Z","iopub.execute_input":"2025-10-09T11:53:48.976562Z","iopub.status.idle":"2025-10-09T11:53:49.048247Z","shell.execute_reply.started":"2025-10-09T11:53:48.976537Z","shell.execute_reply":"2025-10-09T11:53:49.047152Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cudnn.benchmark = True\n\n# initialize and load the model\nmodel = DenseNet121(CFG.n_classes).cuda()\nmodel = torch.nn.DataParallel(model).cuda()\n\nif os.path.isfile(CFG.modv1):\n    print(\"=> loading checkpoint\")\n    checkpoint = torch.load(CFG.modv1)\n    model.load_state_dict(checkpoint['state_dict'], strict = False)\n    print(\"=> loaded checkpoint\")\nelse:\n    print(\"=> no checkpoint found\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:49.049393Z","iopub.execute_input":"2025-10-09T11:53:49.049726Z","iopub.status.idle":"2025-10-09T11:53:50.607986Z","shell.execute_reply.started":"2025-10-09T11:53:49.049704Z","shell.execute_reply":"2025-10-09T11:53:50.606739Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"summary(model, input_size = (1, 3, 224, 224))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:50.608919Z","iopub.execute_input":"2025-10-09T11:53:50.609247Z","iopub.status.idle":"2025-10-09T11:53:52.151387Z","shell.execute_reply.started":"2025-10-09T11:53:50.609222Z","shell.execute_reply":"2025-10-09T11:53:52.150574Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"$$\n\\ell(x, y) = L = \\{l_1,\\dots,l_N\\}^\\top, \\quad\n    l_n = - w_n \\left[ y_n \\cdot \\log \\sigma(x_n)\n    + (1 - y_n) \\cdot \\log (1 - \\sigma(x_n)) \\right]\n$$","metadata":{}},{"cell_type":"code","source":"criterion = nn.BCEWithLogitsLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=1e-4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:52.152141Z","iopub.execute_input":"2025-10-09T11:53:52.152369Z","iopub.status.idle":"2025-10-09T11:53:52.157655Z","shell.execute_reply.started":"2025-10-09T11:53:52.152352Z","shell.execute_reply":"2025-10-09T11:53:52.156913Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# for epoch in range(CFG.EPOCHS):\n#     total_epoch_loss = 0\n#     for batch_features, batch_labels in dl_train:\n#         batch_features, batch_labels = batch_features.to(device), batch_labels.to(device)\n#         output = model(batch_features)\n#         loss = criterion(output, batch_labels)\n#         optimizer.zero_grad()\n#         loss.backward()\n#         optimizer.step()\n#         total_epoch_loss = total_epoch_loss + loss.item()\n#     avg_loss = total_epoch_loss/len(dl_train)\n#     if (epoch+1)%5 == 0:\n#         print(f'Epoch: {epoch + 1} , Loss: {avg_loss}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:53:52.158373Z","iopub.execute_input":"2025-10-09T11:53:52.158685Z","iopub.status.idle":"2025-10-09T11:54:01.548654Z","shell.execute_reply.started":"2025-10-09T11:53:52.158661Z","shell.execute_reply":"2025-10-09T11:54:01.547296Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# for epoch in range(CFG.EPOCHS):\n#     total_epoch_loss = 0\n#     for batch_features, batch_labels in dl_train:\n#         batch_features, batch_labels = batch_features.to(device), batch_labels.to(device)\n#         output = model(batch_features)\n#         loss = criterion(output, batch_labels)\n#         optimizer.zero_grad()\n#         loss.backward()\n#         optimizer.step()\n#         total_epoch_loss = total_epoch_loss + loss.item()\n#     avg_loss = total_epoch_loss/len(dl_train)\n#     if (epoch+1)%10 == 0:\n#         print(f'Epoch: {epoch + 1} , Loss: {avg_loss}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-09T11:54:01.549316Z","iopub.status.idle":"2025-10-09T11:54:01.549698Z","shell.execute_reply.started":"2025-10-09T11:54:01.549514Z","shell.execute_reply":"2025-10-09T11:54:01.549534Z"}},"outputs":[],"execution_count":null}]}