{"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":"import cv2\nimport os\nimport numpy as np\nimport pandas as pd\nfrom glob import glob\nfrom PIL import Image\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom skimage.io import imread\n\n# Pytorch Libraries\nimport torch\nimport torchvision\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\n\nfrom torch.optim import lr_scheduler\nfrom torchvision import models, transforms\nfrom torchvision.datasets import ImageFolder\nfrom torch.utils.data import TensorDataset, DataLoader, Dataset\n\nfrom sklearn.model_selection import train_test_split, GridSearchCV\nfrom sklearn.calibration import CalibratedClassifierCV\nfrom sklearn.ensemble import BaggingClassifier\nfrom sklearn.metrics import confusion_matrix, roc_curve, roc_auc_score\nfrom sklearn.metrics import classification_report, roc_curve, roc_auc_score, confusion_matrix, precision_recall_curve, auc\nfrom sklearn.metrics import plot_roc_curve, plot_confusion_matrix\nfrom sklearn.metrics import precision_score\nfrom sklearn.metrics import recall_score\nfrom sklearn.metrics import f1_score\nfrom sklearn.svm import SVC\n\nsns.set()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-04-28T02:17:55.116669Z","iopub.execute_input":"2023-04-28T02:17:55.117003Z","iopub.status.idle":"2023-04-28T02:18:01.005631Z","shell.execute_reply.started":"2023-04-28T02:17:55.116967Z","shell.execute_reply":"2023-04-28T02:18:01.004519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"meta_data = pd.read_csv('/kaggle/input/histopathologic-cancer-detection/train_labels.csv')\nmeta_data = meta_data.groupby('label', group_keys=False).apply(lambda x: x.sample(15000))\nmeta_data.reset_index(drop=True, inplace=True)\nmeta_data.shape","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:28:26.916306Z","iopub.execute_input":"2023-04-28T03:28:26.917436Z","iopub.status.idle":"2023-04-28T03:28:27.121480Z","shell.execute_reply.started":"2023-04-28T03:28:26.917394Z","shell.execute_reply":"2023-04-28T03:28:27.120162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"meta_data.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-28T02:18:15.803476Z","iopub.execute_input":"2023-04-28T02:18:15.803990Z","iopub.status.idle":"2023-04-28T02:18:15.823363Z","shell.execute_reply.started":"2023-04-28T02:18:15.803947Z","shell.execute_reply":"2023-04-28T02:18:15.822090Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_dir = os.path.join('..', 'input/histopathologic-cancer-detection/train')\n\nimageid_path_dict = {os.path.splitext(os.path.basename(x))[0]: x \n                     for x in glob(os.path.join(base_dir,'*.tif'))}\n\nmeta_data['path'] = meta_data['id'].map(imageid_path_dict.get)\nmeta_data.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:28:30.096773Z","iopub.execute_input":"2023-04-28T03:28:30.097414Z","iopub.status.idle":"2023-04-28T03:28:31.773536Z","shell.execute_reply.started":"2023-04-28T03:28:30.097375Z","shell.execute_reply":"2023-04-28T03:28:31.772261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_samples = 6\nn_classes = len(meta_data['label'].unique())\ndf = meta_data.sort_values(['label']).groupby('label')\nfig, axs = plt.subplots(n_classes, n_samples, figsize = (10, 4))\nfor ax, (type_, rows) in zip(axs, df):\n    ax[0].set_title('Class: '+ str(type_), fontsize=15)\n    for sub_ax, (_, subset) in zip(ax, rows.sample(n_samples).iterrows()):\n        img = imread(subset['path'])\n        sub_ax.imshow(img)\n        sub_ax.axis('off')","metadata":{"execution":{"iopub.status.busy":"2023-04-28T02:18:24.415986Z","iopub.execute_input":"2023-04-28T02:18:24.416562Z","iopub.status.idle":"2023-04-28T02:18:26.068893Z","shell.execute_reply.started":"2023-04-28T02:18:24.416464Z","shell.execute_reply":"2023-04-28T02:18:26.066556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = []\noutliers = []\nfor path in meta_data['path']:\n    img = cv2.imread(path)\n        \n    avgR = np.mean(img[:,:,2])\n    avgG = np.mean(img[:,:,1])\n    avgB = np.mean(img[:,:,0])\n    RGB = np.mean([avgR, avgG, avgB])\n    \n    data.append([avgR, avgG, avgB, RGB])\n    \n    if ((RGB <= 45) or (RGB >= 245)) : outliers.append(meta_data.loc[meta_data['path'] == path].index[0])\n    \nrgb = pd.DataFrame(data, columns=['Red Channel Mean','Green Channel Mean','Blue Channel Mean', 'RGB Mean'])\n\nmeta_data = pd.concat([meta_data.reset_index(drop=True), rgb], axis=1)","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:28:37.041340Z","iopub.execute_input":"2023-04-28T03:28:37.042080Z","iopub.status.idle":"2023-04-28T03:31:18.323888Z","shell.execute_reply.started":"2023-04-28T03:28:37.042041Z","shell.execute_reply":"2023-04-28T03:31:18.322663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"g = sns.pairplot(meta_data[['Red Channel Mean', 'Green Channel Mean', 'Blue Channel Mean', 'RGB Mean', 'label']],\n             hue='label', plot_kws = {'alpha': 0.3})\n\ng.fig.set_size_inches(12,8)","metadata":{"execution":{"iopub.status.busy":"2023-04-28T02:20:46.948897Z","iopub.execute_input":"2023-04-28T02:20:46.949357Z","iopub.status.idle":"2023-04-28T02:21:07.002285Z","shell.execute_reply.started":"2023-04-28T02:20:46.949317Z","shell.execute_reply":"2023-04-28T02:21:07.001262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(outliers)","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:38:43.251618Z","iopub.execute_input":"2023-04-28T03:38:43.252914Z","iopub.status.idle":"2023-04-28T03:38:43.260682Z","shell.execute_reply.started":"2023-04-28T03:38:43.252871Z","shell.execute_reply":"2023-04-28T03:38:43.259411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"extremely_low_pxl_img = meta_data[meta_data['RGB Mean'] <= 45]\nextremely_high_pxl_img = meta_data[meta_data['RGB Mean'] >= 245]","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:38:45.547199Z","iopub.execute_input":"2023-04-28T03:38:45.548194Z","iopub.status.idle":"2023-04-28T03:38:45.561198Z","shell.execute_reply.started":"2023-04-28T03:38:45.548141Z","shell.execute_reply":"2023-04-28T03:38:45.559970Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_samples = 5\ndf = extremely_high_pxl_img.sort_values(['label']).groupby('label')\nfig, axs = plt.subplots(2, n_samples, figsize = (10, 4))\nfor ax, (type_, rows) in zip(axs, df):\n    ax[0].set_title('Class: '+ str(type_), fontsize=15)\n    for sub_ax, (_, subset) in zip(ax, rows.sample(n_samples, replace = True).iterrows()):\n        img = imread(subset['path'])\n        sub_ax.imshow(img)\n        sub_ax.axis('off')","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:38:48.484258Z","iopub.execute_input":"2023-04-28T03:38:48.485419Z","iopub.status.idle":"2023-04-28T03:38:49.750428Z","shell.execute_reply.started":"2023-04-28T03:38:48.485348Z","shell.execute_reply":"2023-04-28T03:38:49.749199Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_samples = 5\ndf = extremely_low_pxl_img.sort_values(['label']).groupby('label')\nfig, axs = plt.subplots(2, n_samples, figsize = (10, 4))\nfor ax, (type_, rows) in zip(axs, df):\n    ax[0].set_title('Class: '+ str(type_), fontsize=15)\n    for sub_ax, (_, subset) in zip(ax, rows.sample(n_samples, replace = True).iterrows()):\n        img = imread(subset['path'])\n        sub_ax.imshow(img)\n        sub_ax.axis('off')","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:38:58.242466Z","iopub.execute_input":"2023-04-28T03:38:58.242856Z","iopub.status.idle":"2023-04-28T03:38:59.570569Z","shell.execute_reply.started":"2023-04-28T03:38:58.242823Z","shell.execute_reply":"2023-04-28T03:38:59.567814Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"meta_data = meta_data.drop(outliers)\nmeta_data['label'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:39:02.643748Z","iopub.execute_input":"2023-04-28T03:39:02.644119Z","iopub.status.idle":"2023-04-28T03:39:02.660847Z","shell.execute_reply.started":"2023-04-28T03:39:02.644086Z","shell.execute_reply":"2023-04-28T03:39:02.659306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CustomDataset(Dataset):\n    def __init__(self, data_df, transform=None):\n        self.data_df = data_df\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.data_df)\n\n    def __getitem__(self, index):\n        img_path = self.data_df.iloc[index]['path']\n        label = self.data_df.iloc[index]['label']\n        \n        # Load image from file\n        img = Image.open(img_path).convert('RGB')\n        \n        if self.transform is not None:\n            img = self.transform(img)\n        \n        return img, label\n\n# Split data into train and test sets\ntrain_df, test_df = train_test_split(meta_data, test_size=0.2, random_state=42)","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:39:09.393743Z","iopub.execute_input":"2023-04-28T03:39:09.394394Z","iopub.status.idle":"2023-04-28T03:39:09.408388Z","shell.execute_reply.started":"2023-04-28T03:39:09.394354Z","shell.execute_reply":"2023-04-28T03:39:09.407261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the batch size\nbatch_size = 32","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:39:10.845940Z","iopub.execute_input":"2023-04-28T03:39:10.846373Z","iopub.status.idle":"2023-04-28T03:39:10.851801Z","shell.execute_reply.started":"2023-04-28T03:39:10.846336Z","shell.execute_reply":"2023-04-28T03:39:10.850294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the data transforms for training and testing datasets\ntrain_transforms = transforms.Compose([\n    transforms.RandomResizedCrop(size=256, scale=(0.8, 1.0)),\n    transforms.RandomRotation(degrees=15),\n    transforms.RandomHorizontalFlip(),\n    transforms.CenterCrop(size=224),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                         std=[0.229, 0.224, 0.225])\n])\n\ntest_transforms = transforms.Compose([\n    transforms.Resize(size=256),\n    transforms.CenterCrop(size=224),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                         std=[0.229, 0.224, 0.225])\n])\n\n# Load the data\ntrain_dataset = CustomDataset(train_df, transform=train_transforms)\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\n\ntest_dataset = CustomDataset(test_df, transform=test_transforms)\ntest_loader = DataLoader(test_dataset, batch_size=batch_size)","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:39:12.816154Z","iopub.execute_input":"2023-04-28T03:39:12.817290Z","iopub.status.idle":"2023-04-28T03:39:12.827810Z","shell.execute_reply.started":"2023-04-28T03:39:12.817237Z","shell.execute_reply":"2023-04-28T03:39:12.826588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def evaluate1(model, loader, criterion):\n    correct = 0\n    total = 0\n    total_loss = 0\n    \n    model.eval()\n    with torch.no_grad():\n        for data in loader:\n            images, labels = data\n            images = images.to(device)\n            labels = labels.to(device)\n            outputs = model(images)\n            loss = criterion(outputs.squeeze(), labels.float())\n            total_loss += loss.item()\n            predicted = torch.round(torch.sigmoid(outputs))\n            total += labels.size(0)\n            correct += (predicted == labels.unsqueeze(1)).sum().item()\n\n    acc = correct / total\n    avg_loss = total_loss / len(loader)\n    model.train()\n    return acc, avg_loss","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:39:16.377431Z","iopub.execute_input":"2023-04-28T03:39:16.378470Z","iopub.status.idle":"2023-04-28T03:39:16.387677Z","shell.execute_reply.started":"2023-04-28T03:39:16.378412Z","shell.execute_reply":"2023-04-28T03:39:16.386306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# define hyperparameters\nlearning_rate = 0.001\nnum_epochs = 20\nroc_aucs = []\n\n# define binary cross entropy loss\ncriterion = nn.BCEWithLogitsLoss()\n\n# define ResNet50, VGG19, Inception, and DenseNet121 models\nmodels_dict = {'VGG19': models.vgg19(weights='DEFAULT'),\n               'VGG16': models.vgg16(weights='DEFAULT'),\n               'ResNet50': models.resnet50(weights='DEFAULT'),\n               'DenseNet121': models.densenet121(weights='DEFAULT')}\n\n# define empty lists to store accuracy and loss\naccs = []\nlosses = []\n\n# loop over models\nfor model_name, model in models_dict.items():\n    \n    print('Training', model_name, 'model')\n    \n    if (model_name == 'VGG19') | (model_name == 'VGG16'):\n        num_features = model.classifier[-1].in_features\n        model.classifier[-1] = nn.Linear(num_features, 512)\n        model.classifier.add_module('bn1', nn.BatchNorm1d(512))\n        model.classifier.add_module('relu1', nn.ReLU(inplace=True))\n        model.classifier.add_module('dropout1', nn.Dropout())\n        model.classifier.add_module('fc2', nn.Linear(512, 256))\n        model.classifier.add_module('bn2', nn.BatchNorm1d(256))\n        model.classifier.add_module('relu2', nn.ReLU(inplace=True))\n        model.classifier.add_module('dropout2', nn.Dropout())\n        model.classifier.add_module('fc3', nn.Linear(256, 1))\n    else:\n        if model_name == 'DenseNet121':\n            num_ftrs = model.classifier.in_features\n            model.classifier = nn.Sequential(\n                nn.Linear(num_ftrs, 512),\n                nn.BatchNorm1d(512),\n                nn.ReLU(inplace=True),\n                nn.Dropout(),\n                nn.Linear(512, 256),\n                nn.BatchNorm1d(256),\n                nn.ReLU(inplace=True),\n                nn.Dropout(),\n                nn.Linear(256, 1)\n            )\n        else:\n            num_ftrs = model.fc.in_features\n            model.fc = nn.Sequential(\n                nn.Linear(num_ftrs, 512),\n                nn.BatchNorm1d(512),\n                nn.ReLU(inplace=True),\n                nn.Dropout(),\n                nn.Linear(512, 256),\n                nn.BatchNorm1d(256),\n                nn.ReLU(inplace=True),\n                nn.Dropout(),\n                nn.Linear(256, 1)\n            )\n\n    model.to(device)\n    \n    # define optimizer\n    optimizer = optim.Adam(model.parameters(), lr=learning_rate)\n    scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=3)\n    \n    # define empty lists to store predictions and labels\n    y_preds = []\n    y_trues = []\n    # train the model\n    for epoch in range(num_epochs):\n        \n        running_loss = 0.0\n        total = 0\n        correct = 0\n        \n        for i, (inputs, labels) in enumerate(train_loader):\n            inputs, labels = inputs.to(device), labels.to(device)\n            \n            # zero the parameter gradients\n            optimizer.zero_grad()\n\n            # forward + backward + optimize\n            outputs = model(inputs)\n            loss = criterion(outputs, labels.float().unsqueeze(1))\n            loss.backward()\n            nn.utils.clip_grad_norm_(model.parameters(), max_norm=0.9)\n            optimizer.step()\n\n            # calculate accuracy\n            total += labels.size(0)\n            predicted = torch.round(torch.sigmoid(outputs))\n            correct += (predicted == labels.unsqueeze(1)).sum().item()\n            acc = correct / total\n\n            # append accuracy and loss to the lists\n            accs.append(acc)\n            losses.append(loss.item())\n\n            # append predictions and labels to the lists\n            y_preds += predicted.cpu().detach().numpy().tolist()\n            y_trues += labels.cpu().detach().numpy().tolist()\n\n        print('Epoch [{}/{}], Loss: {:.4f}, Accuracy: {:.2f}%'\n              .format(epoch+1, num_epochs, loss.item(), acc*100))\n        \n        # calculate validation accuracy and loss\n        val_acc, val_loss = evaluate1(model, test_loader, criterion)\n        print('Accuracy of the network on the validation set: %d %%' % (100 * val_acc))\n\n        # adjust learning rate based on validation loss\n        scheduler.step(val_loss)\n        \n    torch.save(model.state_dict(), model_name + '.pt')\n\n# Plot AUC ROC Curve\nfig, axs = plt.subplots(2, 2, figsize=(10, 8))\naxs = axs.ravel()\nfor i, (name, model) in enumerate(models_dict.items()):\n    model.eval()\n    y_score = []\n    y_true = []\n    with torch.no_grad():\n        for inputs, labels in test_loader:\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n            model = model.to(device)\n            outputs = model(inputs)\n            outputs = torch.sigmoid(outputs)\n            y_score.extend(outputs.cpu().numpy()[:, 0])\n            y_true.extend(labels.cpu().numpy())\n\n    fpr, tpr, _ = roc_curve(y_true, y_score)\n    roc_auc = auc(fpr, tpr)\n\n    axs[i].plot(fpr, tpr, label=f'ROC curve (AUC = {roc_auc:.2f})')\n    axs[i].plot([0, 1], [0, 1], 'k--')\n    axs[i].set_xlabel('False Positive Rate')\n    axs[i].set_ylabel('True Positive Rate')\n    axs[i].set_title(name)\n    axs[i].legend(loc=\"lower right\")\n    plt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-28T03:39:18.725081Z","iopub.execute_input":"2023-04-28T03:39:18.725611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Plot Confusion Matrix\nfig, axs = plt.subplots(2, 2, figsize=(10, 8))\naxs = axs.ravel()\n\n# Loop through each model and plot its confusion matrix in a subplot\nfor i, (name, model) in enumerate(models_dict.items()):\n    model.eval()\n    y_pred = []\n    y_true = []\n    threshold = 0.5\n    with torch.no_grad():\n        for inputs, labels in test_loader:\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n            model = model.to(device)\n            outputs = model(inputs)\n            outputs = torch.sigmoid(outputs)\n            output_numpy = outputs.cpu().numpy()\n            lab = (output_numpy >= threshold).astype(int)\n            y_pred.extend(lab.tolist())\n            y_true.extend(labels.cpu().numpy())\n            \n    y_pred = list(np.array(y_pred).flat)\n    ax = axs[i]\n    cm = confusion_matrix(y_true, y_pred)\n    sns.heatmap(cm, annot=True, cmap=\"Blues\", ax=ax, fmt=\"g\")\n    ax.set_title(\"Confusion Matrix - {}\".format(name))\n    ax.set_xlabel(\"Predicted Labels\")\n    ax.set_ylabel(\"True Labels\")\n\n# Adjust spacing between subplots\nplt.subplots_adjust(hspace=0.3, wspace=0.3)\n\n# Show the plot\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-25T18:49:17.392566Z","iopub.execute_input":"2023-04-25T18:49:17.393614Z","iopub.status.idle":"2023-04-25T18:49:39.477181Z","shell.execute_reply.started":"2023-04-25T18:49:17.393574Z","shell.execute_reply":"2023-04-25T18:49:39.476238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Ensemble Model","metadata":{}},{"cell_type":"code","source":"def evaluate(model, loader, criterion):\n    correct = 0\n    total = 0\n    total_loss = 0\n    \n    model.eval()\n    with torch.no_grad():\n        for data in loader:\n            images, labels = data\n            images = images.to(device)\n            labels = labels.to(device)\n            outputs = model(images)\n            loss = criterion(outputs.squeeze(), labels.float())\n            total_loss += loss.item()\n            predicted = torch.round(outputs) # round the outputs to 0 or 1\n            total += labels.size(0)\n            correct += (predicted == labels.unsqueeze(1)).sum().item()\n\n    acc = correct / total\n    avg_loss = total_loss / len(loader)\n    model.train()\n    return acc, avg_loss","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Ensemble(nn.Module):\n    def __init__(self, models_dict):\n        super(Ensemble, self).__init__()\n        self.models_dict = models_dict\n        \n    def forward(self, x):\n        count = 0\n        for model_name, model in self.models_dict.items():\n            if model_name == 'VGG19':\n                count += 0.225*torch.sigmoid(model(x))\n            if model_name == 'VGG16':\n                count += 0.225*torch.sigmoid(model(x))\n            if model_name == 'ResNet50':\n                count += 0.275*torch.sigmoid(model(x))\n            if model_name == 'DenseNet121':\n                count += 0.275*torch.sigmoid(model(x))\n\n        return torch.tensor(count, dtype=torch.float32)\n        \n    \nensemble = Ensemble(models_dict)\n\nensemble.to(device)\n\nval_acc, val_loss = evaluate(ensemble, test_loader, criterion)\nprint('Accuracy of the ensemble on the validation set: %d %%' % (100 * val_acc))","metadata":{"execution":{"iopub.status.busy":"2023-04-25T20:02:29.013546Z","iopub.execute_input":"2023-04-25T20:02:29.013930Z","iopub.status.idle":"2023-04-25T20:02:40.122652Z","shell.execute_reply.started":"2023-04-25T20:02:29.013896Z","shell.execute_reply":"2023-04-25T20:02:40.121539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Evaluate the model on the test set\ny_test_preds = []\ny_test_trues = []\npredlist = []\n\nensemble.eval()\n\nwith torch.no_grad():\n    for data in test_loader:\n        images, labels = data\n        images, labels = images.to(device), labels.to(device)\n        outputs = ensemble(images)\n        predicted = torch.round(outputs)\n        predlist += predicted.cpu().detach().numpy().tolist()\n        outputs = torch.sigmoid(outputs)\n        y_test_preds += outputs.cpu().detach().numpy().tolist()\n        y_test_trues += labels.cpu().detach().numpy().tolist()\n\n       \n\n# Calculate AUC ROC score\nauc_roc_score = roc_auc_score(y_test_trues, y_test_preds)\n\n# Plot ROC curve\nfpr, tpr, _ = roc_curve(y_test_trues, y_test_preds)\n\nplt.plot(fpr, tpr, label=f'ROC curve (AUC =%.2f)' % auc_roc_score)\nplt.plot([0, 1], [0, 1], 'k--')\nplt.xlabel('False Positive Rate')\nplt.ylabel('True Positive Rate')\nplt.title('Receiver Operating Characteristic')\nplt.legend(loc=\"lower right\")\nplt.show()\n\n# Calculate confusion matrix\nconfusion_mat = confusion_matrix(y_test_trues, predlist)\n\n# Plot confusion matrix\nlabels = ['Negative', 'Positive']\nplt.figure(figsize=(5,5))\nsns.heatmap(confusion_mat, xticklabels=labels, yticklabels=labels, annot=True, fmt='d', cmap='Blues')\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Label')\nplt.ylabel('True Label')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-25T20:00:44.105279Z","iopub.execute_input":"2023-04-25T20:00:44.106619Z","iopub.status.idle":"2023-04-25T20:00:55.787225Z","shell.execute_reply.started":"2023-04-25T20:00:44.106565Z","shell.execute_reply":"2023-04-25T20:00:55.786124Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Custom Binary Classification CNN Model","metadata":{}},{"cell_type":"code","source":"class BinaryCNN(nn.Module):\n    def __init__(self):\n        super(BinaryCNN, self).__init__()\n        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)\n        self.bn1 = nn.BatchNorm2d(32)\n        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)\n        self.bn2 = nn.BatchNorm2d(64)\n        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)\n        self.bn3 = nn.BatchNorm2d(128)\n        self.conv4 = nn.Conv2d(128, 256, kernel_size=3, padding=1)\n        self.bn4 = nn.BatchNorm2d(256)\n        self.fc1 = nn.Linear(256 * 6 * 6, 512)\n        self.bn5 = nn.BatchNorm1d(512)\n        self.dropout = nn.Dropout(p=0.5)\n        self.fc2 = nn.Linear(512, 1)\n        self.sigmoid = nn.Sigmoid()\n        \n    def forward(self, x):\n        x = self.pool(nn.functional.relu(self.bn1(self.conv1(x))))\n        x = self.pool(nn.functional.relu(self.bn2(self.conv2(x))))\n        x = self.pool(nn.functional.relu(self.bn3(self.conv3(x))))\n        x = self.pool(nn.functional.relu(self.bn4(self.conv4(x))))\n        x = x.view(-1, 256 * 6 * 6)\n        x = nn.functional.relu(self.bn5(self.fc1(x)))\n        x = self.dropout(x)\n        x = self.fc2(x)\n        x = self.sigmoid(x)\n        return x","metadata":{"_kg_hide-input":false,"execution":{"iopub.status.busy":"2023-04-25T20:03:52.807768Z","iopub.execute_input":"2023-04-25T20:03:52.808822Z","iopub.status.idle":"2023-04-25T20:03:52.821175Z","shell.execute_reply.started":"2023-04-25T20:03:52.808781Z","shell.execute_reply":"2023-04-25T20:03:52.820257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set the hyperparameters\nbatch_size = 32\n\ntrain_transforms = transforms.Compose([\n    transforms.RandomResizedCrop(size=256),\n    transforms.RandomRotation(degrees=15),\n    transforms.RandomHorizontalFlip(),\n    transforms.CenterCrop(size=96),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                         std=[0.229, 0.224, 0.225])\n])\n\ntest_transforms = transforms.Compose([\n    transforms.Resize(size=256),\n    transforms.CenterCrop(size=96),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406],\n                         std=[0.229, 0.224, 0.225])\n])\n\n\n# Create the datasets and data loaders\ndataset_train = CustomDataset(train_df, transform=train_transforms)\ndataset_valid = CustomDataset(test_df, transform=test_transforms)\nloader_train = DataLoader(dataset_train, batch_size=batch_size, shuffle=True)\nloader_valid = DataLoader(dataset_valid, batch_size=batch_size)","metadata":{"execution":{"iopub.status.busy":"2023-04-25T20:03:55.686751Z","iopub.execute_input":"2023-04-25T20:03:55.687485Z","iopub.status.idle":"2023-04-25T20:03:55.696071Z","shell.execute_reply.started":"2023-04-25T20:03:55.687446Z","shell.execute_reply":"2023-04-25T20:03:55.694711Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learning_rate = 0.005\n\n# Initialize the model, criterion, and optimizer\nmodel = BinaryCNN()\ncriterion = nn.BCELoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\nscheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=3)","metadata":{"execution":{"iopub.status.busy":"2023-04-25T20:03:57.780271Z","iopub.execute_input":"2023-04-25T20:03:57.781036Z","iopub.status.idle":"2023-04-25T20:03:57.833746Z","shell.execute_reply.started":"2023-04-25T20:03:57.780997Z","shell.execute_reply":"2023-04-25T20:03:57.832733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train the model\naccs = []\nlosses = []\ny_preds = []\ny_trues = []\ncount = 0\nnum_epochs = 25\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel.to(device)\n\nfor epoch in range(num_epochs):\n    running_loss = 0.0\n    total = 0\n    correct = 0\n    for i, data in enumerate(loader_train, 0):\n        inputs, labels = data\n        inputs, labels = inputs.to(device), labels.to(device)\n        optimizer.zero_grad()\n        \n        outputs = model(inputs)\n        loss = criterion(outputs.squeeze(), labels.float())\n        loss.backward()\n        optimizer.step()\n\n        running_loss += loss.item()\n        if i % 100 == 99:\n            print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100))\n            running_loss = 0.0\n                \n        # calculate accuracy\n        total += labels.size(0)\n        predicted = torch.round(outputs)\n        correct += (predicted == labels.unsqueeze(1)).sum().item()\n        acc = correct / total\n\n        # append accuracy and loss to the lists\n        accs.append(acc)\n        losses.append(loss.item())\n\n        # append predictions and labels to the lists\n        y_preds += predicted.cpu().detach().numpy().tolist()\n        y_trues += labels.cpu().detach().numpy().tolist()\n        \n    print('Epoch [{}/{}], Loss: {:.4f}, Accuracy: {:.2f}%'\n              .format(epoch+1, num_epochs, loss.item(), acc*100))\n    \n    # calculate validation accuracy and loss\n    val_acc, val_loss = evaluate(model, loader_valid, criterion)\n    print('Accuracy of the network on the validation set: %d %%' % (100 * val_acc))\n    \n    # adjust learning rate based on validation loss\n    scheduler.step(val_loss)","metadata":{"execution":{"iopub.status.busy":"2023-04-25T20:03:59.561792Z","iopub.execute_input":"2023-04-25T20:03:59.562542Z","iopub.status.idle":"2023-04-25T20:08:07.634187Z","shell.execute_reply.started":"2023-04-25T20:03:59.562505Z","shell.execute_reply":"2023-04-25T20:08:07.632948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Evaluate the model on the test set\ny_test_preds = []\ny_test_trues = []\npredlist = []\n\nmodel.eval()\n\nwith torch.no_grad():\n    for data in loader_valid:\n        images, labels = data\n        images, labels = images.to(device), labels.to(device)\n        outputs = model(images)\n        predicted = torch.round(outputs)\n        predlist += predicted.cpu().detach().numpy().tolist()\n        outputs = torch.sigmoid(outputs)\n        y_test_preds += outputs.cpu().detach().numpy().tolist()\n        y_test_trues += labels.cpu().detach().numpy().tolist()\n\n# Calculate AUC ROC score\nauc_roc_score = roc_auc_score(y_test_trues, y_test_preds)\n\n# Plot ROC curve\nfpr, tpr, _ = roc_curve(y_test_trues, y_test_preds)\n\nplt.plot(fpr, tpr, label='ROC curve (area = %0.2f)' % auc_roc_score)\nplt.plot([0, 1], [0, 1], 'k--')\nplt.xlim([0.0, 1.0])\nplt.ylim([0.0, 1.05])\nplt.xlabel('False Positive Rate')\nplt.ylabel('True Positive Rate')\nplt.title('Receiver Operating Characteristic')\nplt.legend(loc=\"lower right\")\nplt.show()\n\n# Calculate confusion matrix\nconfusion_mat = confusion_matrix(y_test_trues, predlist)\n\n# Plot confusion matrix\nlabels = ['Negative', 'Positive']\nplt.figure(figsize=(5,5))\nsns.heatmap(confusion_mat, xticklabels=labels, yticklabels=labels, annot=True, fmt='d', cmap='Blues')\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted Label')\nplt.ylabel('True Label')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-25T20:08:10.458267Z","iopub.execute_input":"2023-04-25T20:08:10.458653Z","iopub.status.idle":"2023-04-25T20:08:13.575509Z","shell.execute_reply.started":"2023-04-25T20:08:10.458622Z","shell.execute_reply":"2023-04-25T20:08:13.574312Z"},"trusted":true},"execution_count":null,"outputs":[]}]}