{"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 warnings\nwarnings.filterwarnings('ignore')\n\nimport os\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score, balanced_accuracy_score, classification_report, confusion_matrix\nfrom sklearn.model_selection import train_test_split\nimport cv2\nimport pickle\nfrom PIL import Image\nimport torch\nimport torchvision\nimport torchvision.transforms as transforms\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader, TensorDataset\nfrom torch.optim.lr_scheduler import StepLR\nfrom torch.nn import Dropout\n\nnum_classes = 5\n\n# Model structure\n#kept private because ongoing research in progress\n# Define the loss function and optimizer\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(combine_model.parameters(), lr=0.0001)\n\n# Check if GPU is available\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(f\"Using device: {device}\")\ncombine_model.to(device)\n\n# Loading preprocessed data\nwith open(\"/root/breast/UBC/merged_data.pkl\", \"rb\") as f:\n    data1 = pickle.load(f) #Orignal Training images (large images are already processed)\nwith open(\"/root/breast/UBC/train_thumbnails_513_images_noTma.pkl\", \"rb\") as f:\n    data2 = pickle.load(f)  #Given train_thumbnail images set #No tma (538-25 = 513)\n\nimages1 = data1[\"images\"]\nlabels1 = data1[\"labels\"]\nimages2 = data2[\"images\"]\nlabels2 = data2[\"labels\"]\nimages = images1 + images2\nlabels = labels1 + labels2\n\nimage_label_1 = []\nfor i in labels:\n    if i == \"CC\":\n        image_label_1.append(0)\n    elif i == \"EC\":\n        image_label_1.append(1)\n    elif i == \"HGSC\":\n        image_label_1.append(2)\n    elif i == \"LGSC\":\n        image_label_1.append(3)\n    elif i == \"MC\":\n        image_label_1.append(4)\n\nx = np.array(images)\ny = np.array(image_label_1)\n\nbatch_size = 4\nx_train_tmp, x_test, y_train_tmp, y_test = train_test_split(x, y, test_size=0.1, shuffle=True)\nx_train, x_val, y_train, y_val = train_test_split(x_train_tmp, y_train_tmp, test_size=0.1, shuffle=True)\n\nx_train_tensor = torch.tensor(x_train.transpose((0, 3, 1, 2)), dtype=torch.float32).to(device)\ny_train_tensor = torch.tensor(y_train, dtype=torch.long).to(device)\n\nx_test_tensor = torch.tensor(x_test.transpose((0, 3, 1, 2)), dtype=torch.float32).to(device)\ny_test_tensor = torch.tensor(y_test, dtype=torch.long).to(device)\n\nx_val_tensor = torch.tensor(x_val.transpose((0, 3, 1, 2)), dtype=torch.float32).to(device)\ny_val_tensor = torch.tensor(y_val, dtype=torch.long).to(device)\n\n# DataLoader for training and validation and testing\ntrain_dataset = torch.utils.data.TensorDataset(x_train_tensor, y_train_tensor)\ntrain_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)\n\nval_dataset = torch.utils.data.TensorDataset(x_val_tensor, y_val_tensor)\nval_loader = torch.utils.data.DataLoader(dataset=val_dataset, batch_size=batch_size, shuffle=False)\n\ntest_dataset = torch.utils.data.TensorDataset(x_test_tensor, y_test_tensor)\ntest_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(x_train.shape)\nprint(x_val.shape)\nprint(x_test.shape)\nprint(y_train.shape)\nprint(y_val.shape)\nprint(y_test.shape)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_losses = []\ntrain_accuracies = []\nval_losses = []\nval_accuracies = []\n\nnum_epochs = 100\nfor epoch in range(num_epochs):\n    combine_model.train()\n    train_loss = 0.0\n    train_acc = 0.0\n\n    for images, labels in train_loader:\n        optimizer.zero_grad()\n        images = images.to(device)\n        labels = labels.to(device)\n\n        #few steps are hidden related to model structure\n        output = output.max(dim=1)[0]\n        loss = criterion(output, labels)\n        loss.backward()\n        optimizer.step()\n\n        train_loss += loss.item() * images.size(0)\n        _, predictions = torch.max(output, 1)\n        train_acc += torch.sum(predictions == labels.data)\n\n    train_loss = train_loss / len(train_loader.dataset)\n    train_acc = train_acc.double() / len(train_loader.dataset)\n\n    # Validation\n    combine_model.eval()\n    val_loss = 0.0\n    val_acc = 0.0\n\n    with torch.no_grad():\n        for images, labels in val_loader:\n            images = images.to(device)\n            labels = labels.to(device)\n\n            #few steps are hidden related to model structure\n            output = output.max(dim=1)[0]\n            loss = criterion(output, labels)\n\n            val_loss += loss.item() * images.size(0)\n            _, predictions = torch.max(output, 1)\n            val_acc += torch.sum(predictions == labels.data)\n\n        val_loss = val_loss / len(val_loader.dataset)\n        val_acc = val_acc.double() / len(val_loader.dataset)\n\n    # Append loss and accuracy to lists\n    train_losses.append(train_loss)\n    train_accuracies.append(train_acc.item())\n    val_losses.append(val_loss)\n    val_accuracies.append(val_acc.item())\n\n    print(f\"Epoch {epoch+1}/{num_epochs}\")\n    print(f\"Train Loss: {train_loss:.4f} Train Acc: {train_acc:.4f}\")\n    print(f\"Val Loss: {val_loss:.4f} Val Acc: {val_acc:.4f}\")\n\n# Plotting the loss and accuracy\nplt.figure(figsize=(12, 4))\nplt.subplot(1, 2, 1)\nplt.plot(range(1, num_epochs+1), train_losses, label='Train Loss')\nplt.plot(range(1, num_epochs+1), val_losses, label='Validation Loss')\nplt.xlabel('Epoch',fontweight='bold',fontsize=25)\nplt.ylabel('Loss',fontweight='bold',fontsize=25)\nplt.xticks(fontweight='bold',fontsize=25)\nplt.yticks(fontweight='bold',fontsize=25)\n# plt.title('Training and Validation Loss')\nplt.legend()\nplt.savefig(\"/root/breast/UBC/LossPlots.png\",dpi=500)\nplt.savefig(\"/root/breast/UBC/LossPlots.eps\",dpi=500)\nplt.subplot(1, 2, 2)\nplt.plot(range(1, num_epochs+1), train_accuracies, label='Train Accuracy')\nplt.plot(range(1, num_epochs+1), val_accuracies, label='Validation Accuracy')\nplt.xlabel('Epoch',fontweight='bold',fontsize=25)\nplt.ylabel('Accuracy',fontweight='bold',fontsize=25)\nplt.xticks(fontweight='bold',fontsize=25)\nplt.yticks(fontweight='bold',fontsize=25)\n# plt.title('Training and Validation Accuracy')\nplt.legend()\nplt.tight_layout()\nplt.savefig(\"/root/breast/UBC/AccPlots.png\",dpi=500)\nplt.savefig(\"/root/breast/UBC/AccPlots.eps\",dpi=500)\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pickle\nExptype = \"_allModels\"\n# Combine the lists\ncombined_lists = [train_losses, train_accuracies, val_losses, val_accuracies]\n\n# Define the path for saving the pickle file\npickle_path = f\"/root/breast/UBC/List_{Exptype}.pickle\"\n\n# Save the combined lists to pickle\nwith open(pickle_path, \"wb\") as file:\n    pickle.dump(combined_lists, file)\n\nprint(f\"Combined lists saved to: {pickle_path}\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Evaluation on the test set\ncombine_model.eval()\ntest_loss = 0.0\ntest_acc = 0.0\ny_true = []\ny_pred = []\nwith torch.no_grad():\n    for images, labels in test_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n\n        #few steps are hidden related to model structure\n        output = output.max(dim=1)[0]\n        loss = criterion(output, labels)\n        \n        test_loss += loss.item() * images.size(0)\n        _, predictions = torch.max(output, 1)\n        test_acc += torch.sum(predictions == labels.data)\n\n        y_true.extend(labels.cpu().numpy())\n        y_pred.extend(predictions.cpu().numpy())\n\n    test_loss = test_loss / len(test_loader.dataset)\n    test_acc = test_acc.double() / len(test_loader.dataset)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Test Loss: {test_loss:.4f} Test Acc: {test_acc:.4f}\")\n# Calculate additional evaluation metrics\ny_true = np.array(y_true)\ny_pred = np.array(y_pred)\n\naccuracy = accuracy_score(y_true, y_pred)\nprecision = precision_score(y_true, y_pred, average='weighted')\nrecall = recall_score(y_true, y_pred, average='weighted')\nf1 = f1_score(y_true, y_pred, average='weighted')\nbalanced_accuracy = balanced_accuracy_score(y_true, y_pred)\n\nprint(f\"Accuracy: {accuracy:.4f}\")\nprint(f\"Precision: {precision:.4f}\")\nprint(f\"Recall: {recall:.4f}\")\nprint(f\"F1 Score: {f1:.4f}\")\nprint(f\"Balanced Accuracy: {balanced_accuracy:.4f}\")\n\n# Confusion Matrix\ncm = confusion_matrix(y_true, y_pred)\nclass_names = [\"CC\", \"EC\", \"HGSC\", \"LGSC\", \"MC\"]\n\nplt.figure(figsize=(8, 6))\nsns.heatmap(cm, annot=True, fmt=\"d\", cmap=\"gray\", xticklabels=class_names, yticklabels=class_names)\nplt.title(\"Confusion Matrix\")\nplt.xlabel(\"Predicted Labels\")\nplt.ylabel(\"True Labels\")\nplt.show()","metadata":{},"execution_count":null,"outputs":[]}]}