diff --git "a/src/main.ipynb" "b/src/main.ipynb" new file mode 100644--- /dev/null +++ "b/src/main.ipynb" @@ -0,0 +1,2650 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "43a754fe", + "metadata": {}, + "outputs": [], + "source": [ + "# Basic libraries\n", + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "import plotly.express as px\n", + "\n", + "# Deep learning & graph\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.optim as optim\n", + "import torch.nn.functional as F\n", + "\n", + "# RDKit\n", + "from rdkit import Chem\n", + "from rdkit.Chem import AllChem\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "1f1844fd", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[13:03:26] WARNING: not removing hydrogen atom without neighbors\n" + ] + } + ], + "source": [ + "# Load Tox21 data\n", + "df = pd.read_csv(\"tox21.csv\") # Ensure this file is uploaded in your Colab environment\n", + "df = df[['smiles', 'SR-HSE']].dropna()\n", + "\n", + "# Updated Morgan Fingerprint Generator\n", + "from rdkit.Chem.rdFingerprintGenerator import GetMorganGenerator\n", + "\n", + "generator = GetMorganGenerator(radius=2, fpSize=1024)\n", + "\n", + "def mol_to_fp(smiles):\n", + " mol = Chem.MolFromSmiles(smiles)\n", + " if mol:\n", + " return np.array(generator.GetFingerprint(mol))\n", + " return None\n", + "\n", + "# Convert SMILES to fingerprints\n", + "fps, labels = [], []\n", + "for _, row in df.iterrows():\n", + " fp = mol_to_fp(row['smiles'])\n", + " if fp is not None:\n", + " fps.append(fp)\n", + " labels.append(row['SR-HSE'])\n", + "\n", + "X, y = np.array(fps), np.array(labels)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "bbd5aeb9", + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.model_selection import train_test_split\n", + "from sklearn.utils.class_weight import compute_class_weight\n", + "\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, stratify=y, random_state=42)\n", + "\n", + "classes = np.unique(y_train)\n", + "weights = compute_class_weight(class_weight=\"balanced\", classes=classes, y=y_train)\n", + "pos_weight = torch.tensor(weights[1] / weights[0])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "d0d532aa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1: Loss = 1.3065\n", + "Epoch 2: Loss = 1.2969\n", + "Epoch 3: Loss = 1.2842\n", + "Epoch 4: Loss = 1.2674\n", + "Epoch 5: Loss = 1.2448\n", + "Epoch 6: Loss = 1.2137\n", + "Epoch 7: Loss = 1.1772\n", + "Epoch 8: Loss = 1.1343\n", + "Epoch 9: Loss = 1.0832\n", + "Epoch 10: Loss = 1.0278\n", + "Epoch 11: Loss = 0.9664\n", + "Epoch 12: Loss = 0.9063\n", + "Epoch 13: Loss = 0.8500\n", + "Epoch 14: Loss = 0.7909\n", + "Epoch 15: Loss = 0.7270\n", + "Epoch 16: Loss = 0.6784\n", + "Epoch 17: Loss = 0.6211\n", + "Epoch 18: Loss = 0.5691\n", + "Epoch 19: Loss = 0.5257\n", + "Epoch 20: Loss = 0.4756\n", + "Epoch 21: Loss = 0.4371\n", + "Epoch 22: Loss = 0.3983\n", + "Epoch 23: Loss = 0.3618\n", + "Epoch 24: Loss = 0.3357\n", + "Epoch 25: Loss = 0.3059\n", + "Epoch 26: Loss = 0.2791\n", + "Epoch 27: Loss = 0.2531\n", + "Epoch 28: Loss = 0.2352\n", + "Epoch 29: Loss = 0.2114\n", + "Epoch 30: Loss = 0.1910\n" + ] + } + ], + "source": [ + "class ToxicityNet(nn.Module):\n", + " def __init__(self):\n", + " super(ToxicityNet, self).__init__()\n", + " self.model = nn.Sequential(\n", + " nn.Linear(1024, 512),\n", + " nn.ReLU(),\n", + " nn.Dropout(0.3),\n", + " nn.Linear(512, 128),\n", + " nn.ReLU(),\n", + " nn.Linear(128, 1)\n", + " )\n", + "\n", + " def forward(self, x):\n", + " return self.model(x)\n", + "\n", + "# Prepare tensors\n", + "X_train_tensor = torch.tensor(X_train).float()\n", + "y_train_tensor = torch.tensor(y_train).float().unsqueeze(1)\n", + "X_test_tensor = torch.tensor(X_test).float()\n", + "y_test_tensor = torch.tensor(y_test).float().unsqueeze(1)\n", + "\n", + "# Training loop\n", + "model = ToxicityNet()\n", + "criterion = nn.BCEWithLogitsLoss(pos_weight=pos_weight)\n", + "optimizer = optim.Adam(model.parameters(), lr=0.001)\n", + "\n", + "for epoch in range(30):\n", + " model.train()\n", + " optimizer.zero_grad()\n", + " output = model(X_train_tensor)\n", + " loss = criterion(output, y_train_tensor)\n", + " loss.backward()\n", + " optimizer.step()\n", + " print(f\"Epoch {epoch+1}: Loss = {loss.item():.4f}\")\n", + "\n", + "torch.save(model.state_dict(), \"tox_model.pt\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "ed7b8671", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accuracy: 0.9011, ROC-AUC: 0.6676\n" + ] + }, + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "bingroup": "x", + "hovertemplate": "color=0.0
Predicted Probability=%{x}
count=%{y}", + "legendgroup": "0.0", + "marker": { + "color": "#636efa", + "opacity": 0.5, + "pattern": { + "shape": "" + } + }, + "name": "0.0", + "orientation": "v", + "showlegend": true, + "type": "histogram", + "x": { + "bdata": "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", + "dtype": "f4" + }, + "xaxis": "x", + "yaxis": "y" + }, + { + "bingroup": "x", + "hovertemplate": "color=1.0
Predicted Probability=%{x}
count=%{y}", + "legendgroup": "1.0", + "marker": { + "color": "#EF553B", + "opacity": 0.5, + "pattern": { + "shape": "" + } + }, + "name": "1.0", + "orientation": "v", + "showlegend": true, + "type": "histogram", + "x": { + "bdata": "IM53PWrDTT9yOkg6fQQdP0tw6zgVRTo+Y2iRPhFt6jeFpqY7V9F/PxqxKTmqfbo4qAhGPw4ymjQeJmQ/lhEHPmUb1Du3vYk+H3NrO9bjPz2h5w8+f8M2P7Yw+ziU+GM9YHmxPiEHeT8axQU/LRvEPqvZUj39VMY72vZ4P0kFVjw5ge89D+w8P6E7dT/tnIU6ihf0O7Z8sD72g24/y3X8O4A4pzqjdaQ5RFAlPVr4fz/eJQY/6fKxPQnl3j7KdL468aN9PzA2hzvFk403mshbO+LHOT0X7n8/Dxt9Px0pVD9KFaw295JZPSANlTbAHYQ+OKSUPMBGdT+8IDM/B9QCOZ5bED2YelI/cs52P49X7j0IrLg449KKPZtFrj6L6H04VgJ8P8xwKj8=", + "dtype": "f4" + }, + "xaxis": "x", + "yaxis": "y" + } + ], + "layout": { + "barmode": "overlay", + "legend": { + "title": { + "text": "color" + }, + "tracegroupgap": 0 + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "Prediction Probability Distribution" + }, + "xaxis": { + "anchor": "y", + "domain": [ + 0, + 1 + ], + "title": { + "text": "Predicted Probability" + } + }, + "yaxis": { + "anchor": "x", + "domain": [ + 0, + 1 + ], + "title": { + "text": "count" + } + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from sklearn.metrics import accuracy_score, roc_auc_score\n", + "\n", + "model.eval()\n", + "logits = model(X_test_tensor)\n", + "probs = torch.sigmoid(logits).detach().numpy()\n", + "preds_binary = (probs > 0.5).astype(int)\n", + "\n", + "acc = accuracy_score(y_test, preds_binary)\n", + "roc = roc_auc_score(y_test, probs)\n", + "print(f\"Accuracy: {acc:.4f}, ROC-AUC: {roc:.4f}\")\n", + "\n", + "df_viz = pd.DataFrame({\"Predicted Probability\": probs.flatten(), \"Actual Label\": y_test.flatten()})\n", + "fig = px.histogram(df_viz, x=\"Predicted Probability\", color=df_viz[\"Actual Label\"].astype(str),\n", + " barmode=\"overlay\", title=\"Prediction Probability Distribution\")\n", + "fig.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "cbf9e13f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Fold 1\n", + "Accuracy: 0.9134, ROC-AUC: 0.6759\n", + "\n", + "Fold 2\n", + "Accuracy: 0.9219, ROC-AUC: 0.7198\n", + "\n", + "Fold 3\n", + "Accuracy: 0.9180, ROC-AUC: 0.6641\n", + "\n", + "Fold 4\n", + "Accuracy: 0.9165, ROC-AUC: 0.7039\n", + "\n", + "Fold 5\n", + "Accuracy: 0.9180, ROC-AUC: 0.6340\n", + "\n", + "Avg Accuracy: 0.9176, Avg ROC-AUC: 0.6795\n" + ] + } + ], + "source": [ + "from sklearn.model_selection import StratifiedKFold\n", + "\n", + "skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)\n", + "accuracies, rocs = [], []\n", + "\n", + "for fold, (train_idx, val_idx) in enumerate(skf.split(X, y)):\n", + " print(f\"\\nFold {fold+1}\")\n", + " model = ToxicityNet()\n", + " optimizer = optim.Adam(model.parameters(), lr=0.001)\n", + " criterion = nn.BCEWithLogitsLoss(pos_weight=pos_weight)\n", + "\n", + " X_train_tensor = torch.tensor(X[train_idx]).float()\n", + " y_train_tensor = torch.tensor(y[train_idx]).float().unsqueeze(1)\n", + " X_val_tensor = torch.tensor(X[val_idx]).float()\n", + " y_val_tensor = torch.tensor(y[val_idx]).float().unsqueeze(1)\n", + "\n", + " for epoch in range(30):\n", + " model.train()\n", + " optimizer.zero_grad()\n", + " out = model(X_train_tensor)\n", + " loss = criterion(out, y_train_tensor)\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + " model.eval()\n", + " preds = model(X_val_tensor).detach().numpy()\n", + " preds_binary = (preds > 0.5).astype(int)\n", + "\n", + " acc = accuracy_score(y[val_idx], preds_binary)\n", + " roc = roc_auc_score(y[val_idx], preds)\n", + " accuracies.append(acc)\n", + " rocs.append(roc)\n", + " print(f\"Accuracy: {acc:.4f}, ROC-AUC: {roc:.4f}\")\n", + "\n", + "print(f\"\\nAvg Accuracy: {np.mean(accuracies):.4f}, Avg ROC-AUC: {np.mean(rocs):.4f}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "0070e8bb", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[13:03:45] WARNING: not removing hydrogen atom without neighbors\n" + ] + } + ], + "source": [ + "import torch\n", + "from rdkit import Chem\n", + "from torch_geometric.data import Data, DataLoader\n", + "from torch_geometric.nn import GCNConv, global_mean_pool\n", + "\n", + "def atom_to_features_gcn(atom):\n", + " return [\n", + " atom.GetAtomicNum(),\n", + " atom.GetDegree(),\n", + " atom.GetFormalCharge(),\n", + " atom.GetNumExplicitHs(),\n", + " atom.GetNumImplicitHs(),\n", + " atom.GetIsAromatic(),\n", + " atom.GetMass(),\n", + " int(atom.IsInRing()),\n", + " int(atom.GetChiralTag()),\n", + " int(atom.GetHybridization())\n", + " ]\n", + "\n", + "\n", + "def smiles_to_graph(smiles, label):\n", + " mol = Chem.MolFromSmiles(smiles)\n", + " if mol is None:\n", + " return None\n", + " atoms = [atom_to_features_gcn(atom) for atom in mol.GetAtoms()]\n", + " edges = []\n", + " for bond in mol.GetBonds():\n", + " i, j = bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()\n", + " edges += [[i, j], [j, i]]\n", + " return Data(\n", + " x=torch.tensor(atoms, dtype=torch.float),\n", + " edge_index=torch.tensor(edges, dtype=torch.long).t().contiguous(),\n", + " y=torch.tensor([label], dtype=torch.float)\n", + " )\n", + "\n", + "graph_list = [smiles_to_graph(row['smiles'], row['SR-HSE']) for _, row in df.iterrows()]\n", + "graph_list = [g for g in graph_list if g is not None]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "423aee98", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1: Loss = 12.3552\n", + "Epoch 2: Loss = 11.6987\n", + "Epoch 3: Loss = 11.5087\n", + "Epoch 4: Loss = 11.3516\n", + "Epoch 5: Loss = 11.0372\n", + "Epoch 6: Loss = 10.8276\n", + "Epoch 7: Loss = 10.6924\n", + "Epoch 8: Loss = 10.5455\n", + "Epoch 9: Loss = 10.4237\n", + "Epoch 10: Loss = 10.1036\n", + "Epoch 11: Loss = 9.8674\n", + "Epoch 12: Loss = 9.6282\n", + "Epoch 13: Loss = 9.5379\n", + "Epoch 14: Loss = 9.3837\n", + "Epoch 15: Loss = 9.1642\n", + "Epoch 16: Loss = 9.0637\n", + "Epoch 17: Loss = 8.9081\n", + "Epoch 18: Loss = 8.8186\n", + "Epoch 19: Loss = 8.7428\n", + "Epoch 20: Loss = 8.5393\n", + "Epoch 21: Loss = 8.4428\n", + "Epoch 22: Loss = 8.3589\n", + "Epoch 23: Loss = 8.1729\n", + "Epoch 24: Loss = 8.3536\n", + "Epoch 25: Loss = 8.0637\n", + "Epoch 26: Loss = 7.8841\n", + "Epoch 27: Loss = 7.6743\n", + "Epoch 28: Loss = 7.5485\n", + "Epoch 29: Loss = 7.4686\n", + "Epoch 30: Loss = 7.4676\n", + "Epoch 31: Loss = 7.4335\n", + "Epoch 32: Loss = 7.3320\n", + "Epoch 33: Loss = 7.1483\n", + "Epoch 34: Loss = 6.8631\n", + "Epoch 35: Loss = 6.9407\n", + "Epoch 36: Loss = 6.8493\n", + "Epoch 37: Loss = 6.8033\n", + "Epoch 38: Loss = 6.7108\n", + "Epoch 39: Loss = 6.5782\n", + "Epoch 40: Loss = 6.7144\n" + ] + } + ], + "source": [ + "from random import choices\n", + "from sklearn.model_selection import train_test_split\n", + "from torch_geometric.loader import DataLoader\n", + "\n", + "# 1. Split into train/test\n", + "train_graphs, test_graphs = train_test_split(\n", + " graph_list, test_size=0.2, stratify=[g.y.item() for g in graph_list], random_state=42\n", + ")\n", + "\n", + "# 2. Balance the training set\n", + "toxic = [g for g in train_graphs if g.y.item() == 1]\n", + "non_toxic = [g for g in train_graphs if g.y.item() == 0]\n", + "toxic_upsampled = choices(toxic, k=len(non_toxic)) # upsample to match\n", + "train_graphs_balanced = non_toxic + toxic_upsampled\n", + "\n", + "# 3. Loaders\n", + "train_loader = DataLoader(train_graphs_balanced, batch_size=32, shuffle=True)\n", + "test_loader = DataLoader(test_graphs, batch_size=32)\n", + "\n", + "# 4. Focal Loss\n", + "class FocalLoss(nn.Module):\n", + " def __init__(self, alpha=0.25, gamma=2.0):\n", + " super().__init__()\n", + " self.alpha = alpha\n", + " self.gamma = gamma\n", + "\n", + " def forward(self, inputs, targets):\n", + " BCE = F.binary_cross_entropy_with_logits(inputs, targets, reduction='none')\n", + " pt = torch.exp(-BCE)\n", + " loss = self.alpha * (1 - pt) ** self.gamma * BCE\n", + " return loss.mean()\n", + "\n", + "# 5. Rich GCN Model\n", + "class RichGCNModel(nn.Module):\n", + " def __init__(self):\n", + " super().__init__()\n", + " self.conv1 = GCNConv(10, 64)\n", + " self.bn1 = nn.BatchNorm1d(64)\n", + " self.conv2 = GCNConv(64, 128)\n", + " self.bn2 = nn.BatchNorm1d(128)\n", + " self.dropout = nn.Dropout(0.2)\n", + " self.fc1 = nn.Linear(128, 64)\n", + " self.fc2 = nn.Linear(64, 1)\n", + "\n", + " def forward(self, data):\n", + " x, edge_index, batch = data.x, data.edge_index, data.batch\n", + " x = F.relu(self.bn1(self.conv1(x, edge_index)))\n", + " x = F.relu(self.bn2(self.conv2(x, edge_index)))\n", + " x = global_mean_pool(x, batch)\n", + " x = self.dropout(x)\n", + " x = F.relu(self.fc1(x))\n", + " return self.fc2(x)\n", + "\n", + "# 6. Training\n", + "gnn = RichGCNModel()\n", + "optimizer = optim.Adam(gnn.parameters(), lr=0.001)\n", + "loss_fn = FocalLoss(alpha=0.25, gamma=2.0)\n", + "\n", + "for epoch in range(40):\n", + " gnn.train()\n", + " total_loss = 0\n", + " for batch in train_loader:\n", + " optimizer.zero_grad()\n", + " out = gnn(batch)\n", + " loss = loss_fn(out, batch.y.unsqueeze(1))\n", + " loss.backward()\n", + " optimizer.step()\n", + " total_loss += loss.item()\n", + " print(f\"Epoch {epoch+1}: Loss = {total_loss:.4f}\")\n", + "\n", + "# 7. Save model\n", + "torch.save(gnn.state_dict(), \"gcn_model.pt\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "50d2e4e8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Best threshold (F1): 0.498\n", + "\n", + "===== GCN Final Evaluation =====\n", + "Accuracy: 0.9243\n", + "ROC-AUC: 0.7838\n", + " precision recall f1-score support\n", + "\n", + " Non-toxic 0.96 0.96 0.96 1220\n", + " Toxic 0.33 0.32 0.33 74\n", + "\n", + " accuracy 0.92 1294\n", + " macro avg 0.65 0.64 0.64 1294\n", + "weighted avg 0.92 0.92 0.92 1294\n", + "\n", + "GCN Model - Accuracy: 0.9243, ROC-AUC: 0.7838\n" + ] + }, + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "bingroup": "x", + "hovertemplate": "color=0.0
Predicted Probability=%{x}
count=%{y}", + "legendgroup": "0.0", + "marker": { + "color": "#636efa", + "opacity": 0.5, + "pattern": { + "shape": "" + } + }, + "name": "0.0", + "orientation": "v", + "showlegend": true, + "type": "histogram", + "x": { + "bdata": "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", + "dtype": "f4" + }, + "xaxis": "x", + "yaxis": "y" + }, + { + "bingroup": "x", + "hovertemplate": "color=1.0
Predicted Probability=%{x}
count=%{y}", + "legendgroup": "1.0", + "marker": { + "color": "#EF553B", + "opacity": 0.5, + "pattern": { + "shape": "" + } + }, + "name": "1.0", + "orientation": "v", + "showlegend": true, + "type": "histogram", + "x": { + "bdata": "IfXuPmeM8j74eHo+FrmWPm1DTz6n7gU/MZDrPaQypj4ftpY++14YP/sM1z3Zxps+IfUTP91rZz5aUQk/REUAPzKaST5uDBg/5c+aPZzEQTzjH7I+EpOOPkHTQT5LK8o+EzwgP+zhMT/MYRU/gcW7PiyJ3j713gs+2E1WP4Id3j6MUSU/doT/PtMdIT8mSLo+7sbfPlxqGz+jTgA/ZubMPQD68z5Mlrs+vHMWPi6mIj/j2iE+lgXdPm750j4065Q+c0/lPgkEFj7Dwbo+eswZPtdcxT400Rc/GQ4DP9R9ST+q+k4+dBJCPnzAZz6anB0+qdrAPmi3hD4UEps+RCatPg8hlT4RTyg/iAz/Pie1Jz/sfuY9hScnP9UDIz54gks98HwxP1tACT8=", + "dtype": "f4" + }, + "xaxis": "x", + "yaxis": "y" + } + ], + "layout": { + "barmode": "overlay", + "legend": { + "title": { + "text": "color" + }, + "tracegroupgap": 0 + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermap": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermap" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "GCN Model - Prediction Probability Distribution" + }, + "xaxis": { + "anchor": "y", + "domain": [ + 0, + 1 + ], + "title": { + "text": "Predicted Probability" + } + }, + "yaxis": { + "anchor": "x", + "domain": [ + 0, + 1 + ], + "title": { + "text": "count" + } + } + } + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import plotly.express as px\n", + "import torch\n", + "from sklearn.metrics import accuracy_score, roc_auc_score\n", + "\n", + "# Evaluate the GCN model\n", + "from sklearn.metrics import precision_recall_curve, classification_report\n", + "\n", + "gnn.eval()\n", + "all_preds, all_labels = [], []\n", + "\n", + "with torch.no_grad():\n", + " for batch in test_loader:\n", + " out = gnn(batch)\n", + " probs = torch.sigmoid(out)\n", + " all_preds.extend(probs.cpu().numpy())\n", + " all_labels.extend(batch.y.cpu().numpy())\n", + "\n", + "all_preds = np.array(all_preds).flatten()\n", + "all_labels = np.array(all_labels).flatten()\n", + "\n", + "precision, recall, thresholds = precision_recall_curve(all_labels, all_preds)\n", + "f1_scores = 2 * (precision * recall) / (precision + recall + 1e-8)\n", + "best_threshold = thresholds[np.argmax(f1_scores)]\n", + "\n", + "# 🔽 Save threshold for use in Streamlit/Dash\n", + "np.save(\"gcn_best_threshold.npy\", best_threshold)\n", + "print(f\"Best threshold (F1): {best_threshold:.3f}\")\n", + "\n", + "preds_binary = (all_preds > best_threshold).astype(int)\n", + "\n", + "print(\"\\n===== GCN Final Evaluation =====\")\n", + "print(f\"Accuracy: {accuracy_score(all_labels, preds_binary):.4f}\")\n", + "print(f\"ROC-AUC: {roc_auc_score(all_labels, all_preds):.4f}\")\n", + "print(classification_report(all_labels, preds_binary, target_names=[\"Non-toxic\", \"Toxic\"]))\n", + "\n", + "\n", + "#all_preds = np.array(all_preds)\n", + "#all_labels = np.array(all_labels)\n", + "#preds_binary = (all_preds > 0.5).astype(int)\n", + "\n", + "gnn_acc = accuracy_score(all_labels, preds_binary)\n", + "gnn_roc = roc_auc_score(all_labels, all_preds)\n", + "print(f\"GCN Model - Accuracy: {gnn_acc:.4f}, ROC-AUC: {gnn_roc:.4f}\")\n", + "\n", + "# Visualization\n", + "df_gnn_viz = pd.DataFrame({\n", + " \"Predicted Probability\": all_preds.flatten(),\n", + " \"Actual Label\": all_labels.flatten()\n", + "})\n", + "fig_gnn = px.histogram(df_gnn_viz, x=\"Predicted Probability\", \n", + " color=df_gnn_viz[\"Actual Label\"].astype(str),\n", + " barmode=\"overlay\", \n", + " title=\"GCN Model - Prediction Probability Distribution\")\n", + "fig_gnn.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "d15e4039", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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CwAAANsimAUAAIBtEcwCAADAtghmE8C0adMkd+7cEhgYKOXKlZOtW7dGe/2lS5fKU089Za5ftGhRWb16tcfGivjP4axZs6Ry5cryyCOPmFPNmjUfOufwvt9Dp0WLFplugC+++KLbx4iEncMrV65I9+7dJWvWrGaHdf78+fl7aqP5mzJlihQoUEBSpEhhOkv17t1b7ty547HxIryNGzdKgwYNTMct/Zu4YsUKeZgNGzZIyZIlze/fk08+KXPnzhVLaDUDxN2iRYscyZIlc8yePduxb98+xyuvvOJInz694/z585Fe/9dff3UkTpzYMWHCBMeff/7pGDx4sCNp0qSOPXv2eHzsiNsctmzZ0jFt2jTHzp07Hfv373e0a9fOkS5dOsfff//t8bEjbnPodPz4cUf27NkdlStXdjRs2NBj40X85/Du3buO0qVLO+rWrev45ZdfzFxu2LDBsWvXLo+PHbGfvwULFjiSJ09uvurcfffdd46sWbM6evfu7fGx4z+rV692DBo0yLF8+XKtcuX48ssvHdE5duyYI2XKlI4+ffqYeOb999838c2aNWscnkYwG09ly5Z1dO/e3XU+NDTUkS1bNsfbb78d6fWbNWvmqFevXrjLypUr5+jSpYvbx4qEmcOI7t2750iTJo3j008/deMokdBzqPNWsWJFx8cff+xo27YtwazN5nDGjBmOJ554whEcHOzBUSKh5k+vW7169XCXaVBUqVIlt48VDxeTYLZ///6OwoULh7ssKCjIUadOHYenkWYQD8HBwbJ9+3ZzmNkpUaJE5vzmzZsjvY1eHvb6qk6dOlFeH943hxHdunVLQkJC5NFHH3XjSJHQczhy5EjJlCmTdOzY0UMjRULO4cqVK6VChQomzSBz5sxSpEgRGTt2rISGhnpw5Ijr/FWsWNHcxpmKcOzYMZMiUrduXY+NG/HjTfFMEo8/og+5dOmS+cOpf0jD0vMHDhyI9Dbnzp2L9Pp6OewxhxENGDDA5BhF/KWG987hL7/8Ip988ons2rXLQ6NEQs+hBj8//PCDtGrVygRBR44ckW7dupkPltqlCN49fy1btjS3e+aZZ/QIsdy7d09effVVGThwoIdGjfiKKp65du2a3L592+RCewors0A8jBs3zmwg+vLLL82mB3i/69evy8svv2w28mXIkMHq4SCO7t+/b1bWP/roIylVqpQE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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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YltzlfSe0xZk+rnS6z311FNur6Ofi+eff9689vpe0v9f9OzZ03zmtE0gYEV++h9vB2oAAACgIqiZBQAAgGURZgEAAGBZhFkAAABYFmEWAAAAlkWYBQAAgGURZgEAAGBZNW7RBF19Ze/evabpNsv5AQAA+B7tHKuLADVs2LDUBVtqXJjVIFuRdewBAADgWbt27XJZ/dKdGhdmdUbW/uLo0oZVTZdM1OUShw0bZtach/UwhtbHGFofY2htjJ/15Xh4DFNTU83koz23laTGhVl7aYEGWU+F2fDwcPNYfICtiTG0PsbQ+hhDa2P8rC/HS2NYlpJQdgADAACAZRFmAQAAYFmEWQAAAFhWjauZBQAAFW+XlJubK3l5eeWutwwMDJTMzMxy3xa+IacKxlBrbwMCAk74fgizAACgVNnZ2bJv3z7JyMioUAiuX7++6SREj3drslXBGOr9aNutyMjIE7ofwiwAACh1waFt27aZWTRtYh8cHFyuQKO3P3LkiAktpTXAh2/Kr+Qx1HCcnJwsu3fvljZt2pzQDC1hFgAAlDorq2FG+35qe6by0tvqfYSGhhJmLSq/Csawbt26sn37dlPCcCJhlncUAAAoE4IoKlNllSvwrgQAAIBlEWYBAABgWYRZAAAAWBZhFgAAVFvXXHONqc3Ug3ZhaN26tTzxxBOmX66aN2+e43I96E5JI0aMkFWrVpXp/nVvfL3fzp07F7lMd27S+1y+fHmRy04//XS58847Xc5btmyZXHLJJRIfH292tNK9/G+44QbZuHFjuZ7zzp075eyzzzY769WrV0/uuecex/N1p/Br4Hz4559/HNebM2eO9OvXT6KioszrdNFFF5nn6M6CBQtMX9ru3btLVSPMAgCAau3MM880PXI3bdokd911lzz22GPy4osvulxnw4YN5jozZsyQrKwsEwZ17/3SfPDBB3LppZdKamqqLFq0qMLbOHXqVDnllFPMY3/66aeybt06+eSTTyQmJkYeeeSRMt9PXl6eY9sXLlwoH374odnGRx99tNjbaEDV5+58uP7666VFixbSq1cvcx1tzXbllVfKoEGDTDjX1yklJUUuvPDCIvd36NAhGT16tJxxxhniCbTmAgAA1VpISIhp+K9uueUW+f777+Wnn36SBx54wHEdncGMjY0119MZ0/POO0/Wr18vXbt2LbFX6pQpU+TNN980zf/fe+896dOnT7m3TxeiGDt2rJkR1m2z0zCp96fhsKxmzpwpa9euldmzZ5sZXp0ZffLJJ+W+++4zIV5nkQvT8+yvj9JWWT/++KPcfvvtjo4DS5YsMUFZ70tnXNXdd98t559/vrm+ruZld/PNN8uoUaNMu60ffvhBqnWY/eOPP8w3I32B9FuADuDIkSNLvI1OhU+YMEHWrFlj+t09/PDD5icEAADgWee+MV+S07LKcE2b5Nts4m+C0Ym3Y6obFSI/335qhW8fFhYm+/fvd3vZ4cOH5YsvvjDH3QU/Z3PnzjVBdMiQIdKoUSMzw/nqq69KREREubbHPst57733ur1cQ7Zd8+bNTe7RYOrOX3/9JV26dDFB1m748OEmxGt26tGjR6nbo0FfXx8N2HY9e/Y0rdk0vF977bVmAYWPP/7YPHfnIKuXb9261cwqP/XUU+IJXg2z6enp0q1bN/OiuJumLkynuHXqXBO/TsFr7YZOgzdo0MAMFAAA8BwNsgmpmWIVOpOq2UHDo846OtOZVXs2UToz2759+xLvT2diL7/8cjMDqTWzLVu2lK+//rrck2xa/qBKezzVqlUriYuLK/byhIQElyCr7Kf1srLQ56W5yv6a2GeJv/vuO5PZNBjrLG3fvn1l2rRpLs/j/vvvlz///NMxe1vtw+xZZ51lDmU1efJk82K+/PLL5nSHDh1k/vz55luQr4bZ+75bLVt3+MuvqSvE39/9t9G28VFy82mtJDSo4qtfAADgaTpDWjaVPzNb3npUXYZVfw7Xlaz0J/DCM5sawHSHqb///lueeeYZkznsOnXqJDt27DDHBwwYIL/++qv56V/DneYQu6uuusoEwfKGWQ3ZZaVhvCrt3r3bhP2vvvrK5XwNwnfccYephdXXLy0tzdThXnzxxTJr1izH6/r4449L27ZtxZMsVTOrU+c6ne1MQ2zhvQGdaSG1Huy0QFvpG1oPVW32uiRJzfQXOZBY7HWmrUqQxjEhcn73hlW+PSg/+/vEE+8XVA3G0PoYQ+/S110DlwYWPdj9eFu/Mt1eb6vhR/eCr6xVn5y3o7TH1s4BWteqZQMNGzZ0zBo6P59mzZqZn/O1g0BiYqJcdtllprTRHobt7z0tUdDb6C/EmZmZLjWy9tdIa2010GmAVgcPHiyyvRqGo6OjzfnaYUFpravOdp6I+Ph4Wbx4scvjaSmnvS64tNft/ffflzp16sg555zjct1JkyaZ7X3uueccY/jRRx+Z103zmc4q//vvv6Yjw7hx4xyvr74m+npPnz5dBg8e7PJY9svdLWdbns+6pcJscVPnGlCPHj1q3mCFPfvss+ZbgrsC6YqsL11euTk6OKV/cH//Z4UE7S3augO+Q795wtoYQ+tjDL1Dw4juIKR1kmXZw784Gmg9TUOR7gCmQU5pjasz+2ndNvtyvTrDqvnhs88+M6GuVq1aLrfR3PHOO++Y0HbFFVe4XKY7Remsrs786uumwVC7CjjXqurtN2/ebH7G1+PaxUCvp4+ptabu6ni1q0FZdO3a1cwsb9myxbTPUj///LP5ImF/vOJosNQwq0Fec5UenLdBXx/nMXR+7eztuJzpLLXOeGs3BQ29hR9b30v6GLoPVeHWYYXHqdqE2YrQPRV1hzE7fSF1x7Fhw4aZbxhVrWufI2aQBgwcIIGBxwuk1Z+bUuShH9ea4+3atZcRA1tU+fagYv8j1H9Ahw4d6lLkDutgDK2PMfQunYHctWuXmWnU/qflVRUzs2Wl7xcNlcX9m2+f2NJts19H/2p/1xdeeMGE1cLbrK2pVqxYYcJu4TpXbV+lOz7pbfVxNYO88sor0rRpUxNadccqvVyDpl5XJ+L08TQca4i8+uqrTT2vztbqTmFag6t9Yz///HNz//oZ0J3lb7vtNrfPZ+TIkdKxY0dz+fPPP28mAjXc6ml7uNWZWy2F0M+U7rjmXMKg5RRaE1v49dKuBTq7/dprr5nXRMfzoYceMiH11FNPNc9Dn58zLVfQ17fw+c7vK73dwIEDi7yvSgrdlg6z+q1Qp/6d6Wl9wd3Nyir9NqYHd29uT/wPsXGdSIkNEWlSJ6rI48UlFhSZK51e53/Qvs1T7xlUHcbQ+hhD79CdfTTQ6cycffayPOw/V9vvw5Pszf+Le1z7+YWfmwZK3Sfn22+/NX1kneke+xoY9VCYLiTwn//8x/ysrjuRaUssDcravUlnS2vXri39+/c3nRCcux5ccMEFZgZXZ2d1Ztg++aY/zT/99NOObdP70EBc0vOZOnWqCaT6OPoYY8aMMS217LfREKl9dXVcne9Hn5d2ZHD3vLRnrAZuLTd46aWXTEjVkgh9nsV1b7B/CShpW/U67j7X5fmcWyrMFt5rTum3ihOtLwEAANWT/sRdEq2ndbcDlgbJ4uo233jjjRIn3jQkOk9WaTAu3D3BHV2gQMNzSYpbccuZzpYWzktlec4601wSDerarqusX0i01KK4FmLVZgUwrb3RqXr7Mm/aekuP63S6vURA95qz05Zc2rtM+7BpcbVOd+veduPHj/facwAAAID3eDXM6l5vWhBtL4rWuhI9bl9yTfe+swdbpW25fvnlFzMbq/1ptUXXu+++67NtuQAAAFC1vFpmUNw0d0k/DehttO0DAAAA4NWZWQAAAOBEEGYBAEClr1QFeOr9RJgFAAAlsrdJKk8je6A09gU4Cq/+VV6Was0FAAA8T8OGLvWalJRkTmuP0fIsfqB9ZjW4aH9TT/eZReWo7DHU+0tOTjbvJfvywhVFmAUAAKXS/qnKHmjL+3Oyfdl5T68AhspRFWOooVhXRjvR+yPMAgCAUmngaNCggdSrV6/YxQSKo9fXpd112VJWcLOmnCoYw+Dg4EqZ5SXMAgCAcpUclLfGUa+fm5sroaGhhFmLCvDhMaRwBQAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWV4Ps5MmTZLmzZtLaGio9OnTRxYvXlzi9V977TVp166dhIWFSZMmTWT8+PGSmZnpse0FAACA7/BqmP3yyy9lwoQJMnHiRFm6dKl069ZNhg8fLklJSW6v/9lnn8n9999vrr9u3Tp57733zH08+OCDHt92AAAA1PAw+8orr8gNN9wgY8eOlY4dO8rkyZMlPDxc3n//fbfXX7hwofTv319GjRplZnOHDRsmV1xxRamzuQAAAKieAr31wNnZ2bJkyRJ54IEHHOf5+/vLkCFD5K+//nJ7m379+sknn3xiwmvv3r1l69atMm3aNLn66quLfZysrCxzsEtNTTV/c3JyzKGq2R/D3WPl5eYdP56X55HtQeWOIayBMbQ+xtDaGD/ry/HwGJbncbwWZlNSUkyAi4+PdzlfT69fv97tbXRGVm936qmnis1mk9zcXLn55ptLLDN49tln5fHHHy9y/syZM80ssKfMmjWryHkrD/iJSIA5vmHDepl2ZJ3HtgeVM4awFsbQ+hhDa2P8rG+Wh8YwIyPD98NsRcybN0+eeeYZefPNN83OYps3b5Y77rhDnnzySXnkkUfc3kZnfrUu13lmVncc0xKF6Ohoj3yz0IEfOnSoBAUFuVwWtDZJ3tuw3Bxv1669jBjYosq3B5U7hrAGxtD6GENrY/ysL8fDY2j/Jd2nw2xcXJwEBARIYmKiy/l6un79+m5vo4FVSwquv/56c7pLly6Snp4uN954ozz00EOmTKGwkJAQcyhMB8KTHyh3jxcQGHD8eEAAH3Af5+n3DCofY2h9jKG1MX7WF+ShMSzPY3htB7Dg4GDp2bOnzJkzx3Fefn6+Od23b99ip5wLB1YNgUrLDgAAAFCzeLXMQH/+HzNmjPTq1cvs0KU9ZHWmVbsbqNGjR0ujRo1M3as699xzTQeEHj16OMoMdLZWz7eHWgAAANQcXg2zl112mSQnJ8ujjz4qCQkJ0r17d5k+fbpjp7CdO3e6zMQ+/PDD4ufnZ/7u2bNH6tata4Ls008/7cVnAQAAAG/x+g5g48aNM4fidvhyFhgYaBZM0AMAAADg9eVsAQAAgIoizAIAAMCyCLMAAACwLMIsAAAALIswCwAAAMsizAIAAMCyCLMAAACwLMIsAAAALIswCwAAAMsizAIAAMCyCLMAAACwLMIsAAAALIswCwAAAMsizAIAAMCyCLMAAACwLMIsAAAALIswCwAAAMsizAIAAMCyCLMAAACwLMIsAAAALIswCwAAAMsizAIAAMCyCLMAAACwLMIsAAAALIswCwAAAMsizAIAAMCyCLMAAACwLMIsAAAALIswCwAAAMsizAIAAMCyCLMAAACwLMIsAAAALIswCwAAAMsizAIAAMCyCLMAAACwLMIsAAAALIswCwAAAMsizAIAAMCyCLMAAACwLMIsAAAALIswCwAAAMsizAIAAMCyCLMAAACwLMIsAAAALIswCwAAAMsizAIAAMCyCLMAAACwLMIsAAAALIswCwAAAMsizAIAAMCyCLM+7mB6tuTn27y9GQAAAD6JMOvDvlmyW056apZc9d4ib28KAACATyLM+rDvl+0Wm01k4Zb9ZoYWAAAArgizPiwxNctxPF9TLQAAAFwQZn1YYmqmtzcBAADApxFmfVRGdq6kZeZ6ezMAAAB8GmHWAiUGAAAAcI8w66MoMQAAACgdYdZHEWYBAABKR5j1UYRZAACA0hFmfRQ1swAAAKUjzPooZmYBAABKR5j1UYRZAACA0hFmfRRlBgAAAKUjzPogm83GzCwAAEAZEGZ9UOrRXMnKzff2ZgAAAPg8wqwPSmBWFgAAoEwIsz6IEgMAAICyIcz6IMIsAABA2RBmfVBSGp0MAAAAyoIw64MSDjMzCwAAUBaEWR9EmQEAAEDZEGZ9UCJlBgAAAGVCmPVBiZQZAAAAlAlh1sfk5dsk+QgzswAAAGVBmPUx+9OzTKAFAABA6QizPiYplVlZAACAsiLM+hjacgEAAFgozE6aNEmaN28uoaGh0qdPH1m8eHGJ1z906JDcdttt0qBBAwkJCZG2bdvKtGnTpLpITCPMAgAAlFWgeNGXX34pEyZMkMmTJ5sg+9prr8nw4cNlw4YNUq9evSLXz87OlqFDh5rLvvnmG2nUqJHs2LFDYmNjpbpIdCozCPT3k1zqZwEAAHwzzL7yyityww03yNixY81pDbW//PKLvP/++3L//fcXub6ef+DAAVm4cKEEBQWZ83RWtzpJclowoV5UiOyl7AAAAMD3wqzOsi5ZskQeeOABx3n+/v4yZMgQ+euvv9ze5qeffpK+ffuaMoMff/xR6tatK6NGjZL77rtPAgIC3N4mKyvLHOxSU1PN35ycHHOoavbHcPdYebl5x4/n5Znr7Dt01HFeXacwm5ObKzk5Xq8KqZFKGkNYA2NofYyhtTF+1pfj4TEsz+N4LcympKSYABcfH+9yvp5ev36929ts3bpVfvvtN7nyyitNnezmzZvl1ltvNU944sSJbm/z7LPPyuOPP17k/JkzZ0p4eLh4yqxZs4qct/KAn4gUhPANG9bLtCPrZPMePe0nAX42yTly0FHWPGf2bIksmIyGl7gbQ1gLY2h9jKG1MX7WN8tDY5iRkWGNMoPyys/PN/Wyb7/9tpmJ7dmzp+zZs0defPHFYsOszvxqXa7zzGyTJk1k2LBhEh0dXeXbrEFbB15rfe2lEXZBa5PkvQ3LzfF27drLiIEt5PGVc/VWEh8dJvXjo2TtoWRz+RlDhkidiOAq316UbwxhDYyh9TGG1sb4WV+Oh8fQ/ku6T4fZuLg4E0gTExNdztfT9evXd3sb7WCgL6BzSUGHDh0kISHBlC0EBxcNe9rxQA+F6f148gPl7vECAo8/D31ONr8AOZBeMK0eHxMq/v5+x28fGMj/ALzM0+8ZVD7G0PoYQ2tj/KwvyENjWJ7H8FoRpgZPnVmdM2eOy8yrnta6WHf69+9vSgv0enYbN240IdddkLWaJKe2XPWjQ726LQAAAFbg1T2K9Of/d955Rz788ENZt26d3HLLLZKenu7objB69GiXHcT0cu1mcMcdd5gQq50PnnnmGbNDWHVryxVPmAUAAKiaMgPdceuDDz4ws6hJSUkuM6VKd9Iqi8suu0ySk5Pl0UcfNaUC3bt3l+nTpzt2Ctu5c6fpcGCnta4zZsyQ8ePHS9euXU2fWQ222s2g2rXlig6R3QfLXvwMAABQE1UozGqA1DB79tlnS+fOncXP73htZ3mNGzfOHNyZN29ekfO0BOHvv/+W6ijBKczGRzEzCwAAUCVh9osvvpCvvvpKRowYUZGbowxlBvVjCLMAAABVUjOrO1u1bt26IjdFGcsM4qOLdmAAAABAJYTZu+66S/773/+KzWaryM1RjESnbgb12AEMAACgasoM5s+fL3PnzpVff/1VOnXqVKQX2HfffVeRu63xEo4tXRsWFCBRIZZazwIAAMArKpSYYmNj5YILLqj8ranhko7VzGq97InsVAcAAFBTVCjMTpkypfK3pIbLyM6VtKxcc7xeFPWyAAAAZXFCv2Vrj9gNGzaY4+3atZO6deueyN3VaPZZWcWCCQAAAFW4A5iu0nXttdeaZWQHDhxoDg0bNpTrrrtOMjJo9H+iPWZpywUAAFCFYVaXof3999/l559/lkOHDpnDjz/+aM7TTgcov0Tn1b8oMwAAAKi6MoNvv/1WvvnmGzn99NMd5+kCCmFhYXLppZfKW2+9VZG7rdGS0igzAAAA8MjMrJYSxMfHFzm/Xr16lBlU0IH0bMdxwiwAAEAVhtm+ffvKxIkTJTPz+E/jR48elccff9xchhNTnzALAABQdWUGuvrX8OHDpXHjxtKtWzdz3ooVKyQ0NFRmzJhRkbuEk3osZQsAAFB1YbZz586yadMm+fTTT2X9+vXmvCuuuEKuvPJKUzeLiosJC5LQoABvbwYAAED17jMbHh4uN9xwQ+VuDSSeWVkAAIDKD7M//fSTnHXWWRIUFGSOl+S8884r+xbABTt/AQAAVEGYHTlypCQkJJiOBXq8OH5+fpKXl1eOTYAzwiwAAEAVhNn8/Hy3x1G5KDMAAACo4tZc7ugqYDhxtOUCAACo4jD7/PPPy5dffuk4fckll0jt2rWlUaNGpkUXKq4eYRYAAKBqw+zkyZOlSZMm5visWbNk9uzZMn36dLOD2D333FORu8Qx1MwCAABUcWsu3RHMHmanTp0ql156qQwbNkyaN28uffr0qchd4hhqZgEAAKp4ZrZWrVqya9cuc1xnZIcMGWKO22w2OhmcAD8/kbqRhFkAAIAqnZm98MILZdSoUdKmTRvZv3+/KS9Qy5Ytk9atW1fkLiEicZEhEhhQafvkAQAAVHsVCrOvvvqqKSnQ2dkXXnhBIiMjzfn79u2TW2+9tbK3scagxAAAAMADYVZXAbv77ruLnD9+/PiK3B2OiY9i5y8AAIDyYDlbHxIfQ5gFAAAoD5az9SHMzAIAAJQPy9n6EGpmAQAAyodd530IZQYAAAAeCLP/+c9/5PXXXy9y/v/93//JnXfeWZG7BGUGAAAAngmz3377rfTv37/I+f369ZNvvvmmIncJygwAAAA8E2Z1oYSYmJgi50dHR0tKSkpF7rLGCwrwk1rhwd7eDAAAgOofZnWVL13GtrBff/1VWrZsWRnbVePUiwoVf38/b28GAABA9V80YcKECTJu3DhJTk6WwYMHm/PmzJkjL7/8srz22muVvY01AiUGAAAAHgqz1157rWRlZcnTTz8tTz75pDlPl7d96623ZPTo0RW5yxovPpqdvwAAADwSZtUtt9xiDjo7GxYWJpGRkRW9KxBmAQAAPNtnNjc3V2bPni3fffed2Gw2c97evXvlyJEjFb3LGicq5Ph3iaa1w726LQAAADVmZnbHjh1y5plnys6dO025wdChQyUqKkqef/55c3ry5MmVv6XVUO8WteXSXo3l8NEcuahnY29vDgAAQM0Is3fccYf06tVLVqxYIXXq1HGcf8EFF8gNN9xQmdtXrQUG+MsLF3fz9mYAAADUrDD7559/ysKFCyU42LUvqu4EtmfPnsraNgAAAKDya2bz8/MlLy+vyPm7d+825QYAAACAz4bZYcOGufST9fPzMzt+TZw4UUaMGFGZ2wcAAABUbpnBSy+9ZHYA69ixo2RmZsqoUaNk06ZNEhcXJ59//nlF7hIAAADwTJht0qSJ2fnryy+/NH91Vva6666TK6+80vScBQAAAHwyzObk5Ej79u1l6tSpJrzqAQAAALBEzWxQUJApLQAAAAAsuQPYbbfdZhZI0FXAAAAAAEvVzP7zzz8yZ84cmTlzpnTp0kUiIiJcLtclbgEUyM7Nlx+W75HIkEAZ0aWBtzcHAIBqpUJhNjY2Vi666KLK3xqgmknLzJFbPlkq8zenmNNTbz9VOjeK8fZmAQBQM8OsLpbw4osvysaNGyU7O1sGDx4sjz32GB0MADcSDmfKNVMWy/qENMd5O/ZnEGYBAPBWzezTTz8tDz74oERGRkqjRo3k9ddfN/WzAFxtTEyTC99c4BJkAQCAl8PsRx99JG+++abMmDFDfvjhB/n555/l008/NTO2AAr8tWW/XPTWQtl7mK4fAAD4VJjduXOny3K1Q4YMMUvZ7t27tyq2DbCcn1bslTHvL5a0zIJOH10axchNp7X09mYBAFBtlSvMaiuu0NDQIn1ndSEFoCaz2Wzyv9+3yH8+XybZeQW/VAxqV1e+uPEUqRsZ4u3NAwCg2gos7z/Y11xzjYSEHP/HWRdQuPnmm13ac9GaCzVJfr5Nnpi6Vj5YuN1x3hW9m8iT53eWwIAKtXIGAABVEWbHjBlT5LyrrrqqPHcBWNL+TJGnpq2XU9vUk6Ed4x3n5+Tly73frJTvl+1xnHfX0LYybnBrU4IDAAB8KMxOmTKl6rYE8FFbk9PltdUBkpqzU776d48seWSIhAcHSmZOnoz7bKnMXpdkrhfg7yfPXdhFLunVxNubDABAjVGhRROAmmJz0hG56v1/JDWnYJb1aE6eHMnMlbx8m1z/4b+yaNsBc35wgL/836geMqxTfS9vMQAANQthFighyF7xzt+SfCTb5fwDGdly70crZeXuw+Z0RHCAvDO6l/RrHeelLQUAoOYizALFBNnL3/5bUo5kFbns2in/OHrIxoYHyQdje0v3JrFe2EoAAMCu1kAhm5PSXIJsxwZR0jra5rjcHmTrRYXIVzf1JcgCAOBFhFnAyaZEDbKLHEG2c6No+fCaXhIeeDzMqqa1w+XbW/pJ2/goL20pAABQlBkATkFWa2RTjtXIapD95Lo+EhHkJwFOXbbaxUfJx9f1lnrRrguIAAAAzyPMAiKyJfmIS5DVZWg1yMaEF6xw16euTbZmBMpJTWvJq5d1l9jwYG9vMgAAIMwCIrsPZshV7y5yG2TtOtSyyeIrBklICCEWAABfQs0sarSktEwTZPcd26mrY4PoIkHWzt+fFb0AAPA1hFnUWIcysuXqdxfL9v0Z5nTLuhHy0XW93QZZAADgmwizqJGOZOXKmCn/yIbENHO6UWyYmZGNiwzx9qYBAIByIMyixsnMyZMbPvxXVuw6ZE5rgP3k+j7SMDbM25sGAADKiTALS/lx+R554ue1blfmKoucvHy57dOl8tfW/eZ0TFiQfHJ9b2kRF1HJWwoAADyBbgawjOmr98kdXyw3xwP8RR46u2O5bp+Xb5MJX62QOeuTzOmI4AD58Nre0r5+dJVsLwAAqHrMzMISdh3IkHu+Wek4vf9YG62ystls8siPq+XnFXvN6eBAf3l3zMksRQsAgMURZuHztDTg9s+XSVpmboXvY9LczfLZop3meKC/n7x15UnSt1WdStxKAADgDYRZ+LyXZmyQ5cd21iot9GpgnbehoIzA7pslu+WlmRuP398l3eSMDvFVsq0AAMCzqJmFT5u7IUn+98fWMpUR3PP1CvlheUEZwR/3DJKmdcLlz03Jcv+3x8sT7j+rvYzs0ahKtxkAAHgOM7PwuEVb98tfWwq6CZQk4XCm3PXVCsfp0X2bFXvdt//Y6giyas+ho7Jm72G55ZOlkptvc9z+poEtT3j7AQCA7yDMwqOmrdonl739t1zxzt+yeNuBYq+Xm5cv//limRxIL9jRa0iHeLmmX/NiZ2+fm77e5TwNs2On/GMWR1DDOsbLxHM7iZ8fS9ICAFCd+ESYnTRpkjRv3lxCQ0OlT58+snjx4jLd7osvvjDhZOTIkVW+jThxaZk58thPaxynNycdKfa6r/+22RF2G8aEykuXdHUbRLckH5H/fL5MbAWTrw6P/rhaktIKetGe1DRWXr+ihwT4E2QBAKhuvB5mv/zyS5kwYYJMnDhRli5dKt26dZPhw4dLUpLrTjyFbd++Xe6++24ZMGCAx7YVJ+a12ZscAbMkCzenyBu/bTLHNYBqEI0NDy5yvcNHc8xKXvYuB0EBx8NqRnae+auLIWgLrtCggEp8JgAAwFd4Pcy+8sorcsMNN8jYsWOlY8eOMnnyZAkPD5f333+/2Nvk5eXJlVdeKY8//ri0bEkNpBWs25cqHyzcXur1dGWvO75c7phpvWtYW+nVvHaR6+XZbGZGdmtKujndvn6UjOrd1OU6cZHB8uHY3lI7omgQBgAA1YNXuxlkZ2fLkiVL5IEHHnCc5+/vL0OGDJG//vqr2Ns98cQTUq9ePbnuuuvkzz//LPExsrKyzMEuNTXV/M3JyTGHqmZ/jIo8Vv6xHZfM7XNzJSfH6989KkSfx8PfrzIrcBX+UuL8umhHgru+Wi7Jx2ZvT21dR67r29Rxndzc49f9dXWCZOfmm+O1woPkzVHd5Mt/9jguDwvyl/9d2UMaRAed8DifyBjan+fx47keed+hcscQ3scYWhvjZ32eHsPyPI5Xw2xKSor5hz4+3rXnp55ev951hx67+fPny3vvvSfLlxcsa1qaZ5991szgFjZz5kwzA+wps2bNKvdtkpI0vBYE2DmzZ0tkkFjSoiQ/WbKz6M/8q1evkmnJx9tmLUz0k9+3FlwvKsgmw2MSZfr0Xx2XJx09/pa1B1l/scmVzTNl1V/zJGe/lhkEmPOubpUju1cukN3H794rY6jW7S3YLrV02TKx7SxU4AuPqegYwncwhtbG+FnfLA+NYUZGRvXsM5uWliZXX321vPPOOxIXF1em2+isr9bkOs/MNmnSRIYNGybR0dHiiW8WOvBDhw6VoKDypdEfDywTOZhsjp8xZIjUseDP5YcycuSx/87XV8KcPqdLfZm6KsEc79y5i4w4ubE5vutghjz4fzobXzCL+crlJ8npbeu63Nf2/eny9PIFLuc9ck4HuapPQXnBWTabDN15SOpFhUjT2uE+MYYqYcF2+WFHwaINJ/XoIWd1rl9p2wbPjCG8jzG0NsbP+nI8PIb2X9J9PsxqIA0ICJDExESX8/V0/fpF/8HfsmWL2fHr3HPPdZyXn18wQxcYGCgbNmyQVq1audwmJCTEHArTgfDkB6oij+fvtPd9UGCgJf8H8Opv6+VgxrEg27WBDGxb1xFmdez1OWn5wf3frZX0YzttXX5yExnaqWGR+woMdH3+V/RuKtf0b+nS5aBv63pV9lwq+p7R53n8uDXHsbrw9OcelY8xtDbGz/qCPDSG5XkMrxZhBgcHS8+ePWXOnDku4VRP9+3bt8j127dvL6tWrTIlBvbDeeedJ4MGDTLHdcYVvkOXoP188U5zPCI4QB4+u6Pb670/f5ss3l7QhqtxrTB5+Bz319MduQKPBfzezWvL4+fRNxYAgJrO62UGWgIwZswY6dWrl/Tu3Vtee+01SU9PN90N1OjRo6VRo0am9lX70Hbu3Nnl9rGxseZv4fPhXTrb+vAPqxxdCcYPbSv1Y0KLXG9jYpq8OHODOa659KVLuklkiPu3ZUxYkLx3zcmyes9hubpvMwkOtOYOcQAAoBqF2csuu0ySk5Pl0UcflYSEBOnevbtMnz7dsVPYzp07TYcDWMtni3bI6j2pjrZZ7lbvys3PlwlfLXfszHVd/xZySss6Jd7vaW3rmgMAAIBPhFk1btw4c3Bn3rx5Jd72gw8+qKKtQkVpa60XZhTMtqonR3aWwAB/t+UF2/cX7K3Yul6k3D28nUe3EwAAWB9Tnqh0z/66zrEq1yU9G8vJbhY9UPYgq6t8vXJpN1bpAgAA5UaYRaVaseuQfLd0j6PG9f6z2pd6m3GDWkvXxgW1zwAAAOVBmEWl0RW8np62znF6wtC2UieyaFs0Z10axci4wa09sHUAAKA6Isyi0sxelySLtxW02GoRFyGjji1mUBztRqDlBUFu6mkBAADKghSBSpGTl29qZe3uO7O925DaKDbMcfyeYe2kTXyUx7YRAABUPz7RzQDWKydYteewNIwNk7hjZQRf/LNLtianm+O9mtWS4Z0KWqsV1q9VHXn9ih7mPs7rVnSVLwAAgPIgzKLc3l+wXZ6culbiIoNlwf2DTZ/Y12ZtdFz+0Nkdil2ZS88nxAIAgMpCmK3G0rMK2mNFFLOiVkWkZebI63M2meMpR7Jl5/4M+XH5Xtmfnm3OO7trA+nRtFalPR4AAEBJqJmtptbsPSw9npglA1+YKweOBc3K8PHfO+Tw0RzH6X2HM+Xd+VvN8aAAP7lveOmtuAAAACoLYbaa+nTRTsnOyzczpv9uL+gwcKIysnPl3T+3uZz3yqyNkplTsBzt6L7NpWmd8Ep5LAAAgLIgzFZT8zelOI7n2yrnPj9btLPILO/yXYfM3+jQQLmdfrEAAMDDCLPVkNax7jxQsFRsZcnMyZO3/ygoJ3Dn9sFtJDY8uFIfEwAAoDSE2Wpo/ubjs7KV5at/d0lSWpbbyxrXCpPR/ZpV+mMCAACUhjBbDc3fnFyp96ettybP2+I43alhtMvl9wxvJyGBAZX6mAAAAGVBmK1m8vJtsmDz/kq9z++W7pa9hzPN8cHt67mE2W6NY+TcrvSNBQAA3kGYrYYtuZxbZ52o3Lx8edNpVnbc4NZS59iqX+rBER3E39/9AgkAAABVjUUTqpk/nboYVIafVux17Ex2aus4OalpLWlWO9yUHnRuFC19Wtap1McDAAAoD8JsNW7JVRklC/83d7PjtL31ls7MPnJOx0p7HFQ/K3cfko/+2iENY8Nk/JA2xS5vDADAiSLMViNHs/NkyY6DlXZ/01btk63J6eZ47xa1mYVFqXbsT5cXZmyQX1buc5w3rGO8dG4U49XtAgBUX4TZamTRtv1m1S+lE2G2E1gsIV9nZX87Piv7n8FtKmMTUU2lHMmSN+ZsMivP5RZapeNQRuXVcAMAUBhhthpZ4NRftkujGFm5+3CF72vWukTZkJhmjndvEiv9WzMri6LSswqWOH77jy2Snp3n7c0BANRAhNlquPOXzsr2bVWnwmHWZrPJG79tcpz+zxmtqXmEi5y8fPnin13y39mbzKysXXhwgFw/oKWkZebIlAXbvbqNAICagTBbTSSnZcn6hDTHrGytE1haVvvUrt6Tao5rT9lB7epV2nbC2vSLzvTVCfLijA2yNaWgnloF+PvJFb2byH/OaCP1okLl5ZkbvLqdAICagzBbDUsMtIXWiXh/wTbH8VtPZ1bWFwJkZk6+hAV7d5W1RVv3y7O/rpfluw65nD+iS325e1g7aVk30mvbBgCouQiz1bC/rIbZlXsqVmKwNfmI/LY+yRxvFBsmwzvFV9o2oijt1/vKrI3yw7I9MrZ/c7nptFYul/+xMVke+G6VHMrIlilje5uuEp62MTFNnv91vcw59r6w02154Kz20qNpLY9vEwAAdoTZajJzZ5+ZDQ3yl57Na1U4zH648Hid4+i+zSQwgEXiqsr2lHS5/fNlsurYWP3vj62OMJuRnSvP/bre9Gq1m7EmoUJhNjMnT0KDyj+rm3A405QLfLt0tzg3KGgbHyn3n9XelJ8waw8A8DbCbDWwJfmIJKRmmuO9W9SRkMCK/Ryty+B+vWS3OR4WFCCXn9y0UrcTx32/bLc8/P1qlw4AWTkFx5ftPCgTvloh25xqUu2LWBQ2ffU+efuPraaP6xPnd3a5bPWew/LIj6tlxa5D8ug5HeWa/i3KHH71Pt+at0WOHtsm1SAmVMYPbSsXndTY1MgCAOALCLPVrMRgwAnUy3797y7JOBauLurZSGLCgypl++DaymrCV8vlu6V7ilymWfWVmRtk0rwtboOrs6S0TJn44xr5dXWCOb105yG5tn8LaR4XIUeycuWVmRvlg4XbHDOq3y/bU2qY1Rn+qSv3mRnhPYeOOs6PDg2UWwe1lmv6Na/QDC8AAFWJMFvNlrA9tU3FwmxuXr5LK6Vr+pVtFg/l8/CPq02drJ3Ocv6z/YDsPJBhZkFfd1qooluTWLmmXzMZ/+UKl8D5zZLd8tQv68xMurP07Fz5ddU+efzntY6Zeru8UlbQ0OVnn/h5rfzrtIKczr5efUozueOMNlIrouLdMQAAqEqE2WrQ7/PvrfvN8bjIYGkXH1Wh+5m9LtExG3d6u7rSuh57plcFe5CNDAmUp0Z2lpE9GsmwV393uU6gv59pcXXr6a1k9d6CFmlq3+GjMvr9xS4z8c7u/WalrHG6vtZPaxeEkiSlZprlZ7Uu1jnvDmxbVx45u4O0qeD7CQAATyHMWpy2SbLXXfZvHSf+Zaxl1Kb22k+2X+s6Eh0aJO87zcqOLWNtJSqmW+MYef2KHtKsToQ5HRZ8/GOoXyJevbS7dGkcU+R2M9Ykupwe2b2hZOXmO0oNnIOsfiF58vzOMvjleZKTZ3NbF/ve/G0yae5mR2mJalk3Qh45u6O5PTt3AQCsgDBbzVpyldWdXyw3rZb6tKgtj5zTURZvO+AIUwMrWKoA97RcwO6mgS3lrmHtJDjweJcInYF9bfYmOa1tXblzSJtS61J1R6ynL+gsg9vHy4Pfr3K5LD46RB47t5Oc2bm+2zCqZQoafp+Ztk52H3Sti71zSFu5um8zCaKDBQDAQgizFjd/U7Lj+IA2dcvcEsreM3TdvlSXWlntdcqMXOU6uXltmX7nANNlokVcwWyss+Gd6puDO1qO4OzKPk1NW6yo0IKd8zo3LJjB1Qn5Mf2ay4ShbR2XFabdDZ6YutbxxcV+uyv7NDNdCmpTFwsAsCDCrIWlZubIit2HHTOq9WNCy3S775YWtN9SWlP584q95nhMWJBc2KNxFW1tzda+fnSFbteqboTcOLClbEpMMz1oT2lZx+VyXUJWA7LO1mong+JsTDwi5/7ffJe6WJ3J11n5dvU9XxerX6h0x7ehHeMl9gSWXgYAgDBrYX9v2e9o4VTWEoP8fJt869QWKjvv+A5CV/Ru6vUlU+FKZ8kfHNGhxMv7tnINuO44d1DQ8PvQiA5yRgfPL3qwISHN1OlOXbnXtA3T9+0n1/cpcr3NSUdMXa/2zwUAoCSEWQubf2zVr/KE2b+37XfpIerchklX/EL1ovWvOXkFO3hFhQSaLglajuBcs+sJq3Yflv+bu6nITmy6fLJzPa/WgP/vjy1m50Q15ZqTZVD7eh7dVgCAtRBmq0F/WW3ldEoZZufUt0uKNutXusNQw9iwSt0+eN/1p7aQTxbtNOOr9bRxkSEe34bHfl5jZlpL6nH8y6p98r/ft8rafcc7Mti7dRBmAQAlIcxaVGJqpmw9ttxp9yaxRXYUKm71qV9X73N7ma4ehepnwrB25uBNzkFWuy3cMKClWSp3f3q2HMzIkUEvz5NdB4r+WgAAQFnQg8eilu08vlJT7xa1y3Qbbcnk3FPUue/pSU2Pt48CTlTh9l6Na4WZRSJ+v2eQXD+gpQQGFNTq6qpnzkG2a+MY01GjJAmHM+XzxTtlrVNfXQBAzcXMrEUt3XnIcbxH01plus03S3a51Mjadx679tQWtONCpRrRpYHpmqE9czW8nt+9oUvALVyzqyuO3XxaS+nbso78sSnFpV2c85K778/fJlNX7pPcfJtEBAfIkkeGltqXFwBQvRFmq8HMbI8yzKruOpAhf28t6C/aMi7C1MfqDmSNYsPkrM4NqnRbUfNoq7h59wwq9vIbB7SUN+dtMb8q3DSwlXRs6L51mX7h+nXVPrNa2b87jr/nla58p6UK+h4GANRchFkLysnLl5XH+ss2rR1epp16vnNqx3VRz8Yyskcj+X7pbjmzcwOP79kOXN23uTmU5s15m00LLwAAikOKsaD1+9Ik61jf0LLMyopob9mChRK0muDCkxqZ2axxg9uYGTTAVzkH2Tb1IuXZC7vIkA50NwAAHMfMrAUtdS4xaFJ6mP1n+0HZeSDD0Y+2QQw/y8J31Yty/aXh9HZ15bpTW5j3rtZ2O/dXBgCAMGvxetmTmpW+89ePy51KDE5iuVr4tvb1o8wM7N5DR+X87o349QAAUCLCrAUt21XQySAk0F/a13e/44yzlCPZ5q/2oh3eqX6Vbx9wInT2VZdWBgCgLKiZtZiUI1myY39ByUCXRjHl2nnr7C4NJCyYNkYAAKD6IMxazHKn/rJlKTFwdnEvSgwAAED1Qpi1mGW7yrfzl12zOuHSq5zhFwAAwNdRM2sxyyqw8pd9xy9W+QKqRlZunszbkCy/b0yWjg2i5apTmnl7kwCgxiDMWoiuhrTi2M5fDWJCpX5MaJlve0GPRlW4ZUDNk59vk8XbD5huIb+s3Cepmbku7cQa1wr36vYBQE1BmLWQjYlpZglPdVI5ZmVPaVlbmtTmH1agMqzblyo/LN8jPy/fK3sPZ7q9zsH0HGlMVQ8AeARh1kJcSwxKrpeNDg1yHL+4Z5Mq3S7AV6Rm5shPy/fKjv3pcu2pLSptgZA9h46aGdgfl+2VDYlpRS4PDw6QqNBASUzNqpTHAwCUHWHWqit/lRJmz+7aQJbsOCix4UGUGKBas9lssnTnIfl88U7zc//RnIJfL5LTsuS1y3uU675y8vJlW0q6NK8TIRnZufLLqn0mwGo5QWEB/n4ysE2cjOzRSIZ2jJfnfl0vH/21o9KeFwCgbAizFlz5KyjATzo1jCnxujFhQfLypd08tGWAd3y2aIfMWpsoGxOPFLks+UhWmcPwmr2p8s2S3fLTir1yID3b8TnLybMVuf5JTWNNgNW+zXUiXZfeBQB4HmHWIg4fzZEtyenmeMeGMRIaxOIHwKS5W1xORwQHOOrKS5OYmik/LNsj3y7d7TYMOwfZVnUjZGT3RmZ53aZ1qD8HAF9CmLWIFbsPVai/LFDd+LtpMac9lC/v3VQGtasrPZ+aXextj2bnybQ1SfLt0j0yf1Oy5BedeHWoFxUi53VraGZhOzWMprUdAPgowqxFLN1R9p2/gOpsWMd4+WXlXlNKc+FJjeXyk5tIm/goc5nWuborI9Ca18+3+MuDS+dJelae2zCs99W/dR35bX2StI2PklNa1jF1sZVlc9IR2ZJ8RE5rW5dfVgCgEhFmLbjyV3nacgHVzbndGsrAtnVNB4GggOIXMdT2WK/O2ijfLdstuw4cPbbg4fEg27hWmAmwF/ZoJM3jIhznj+3folK2U0O0dj6YtipBfl21TzYlFZQy6OO9cln3SnkMAABh1jLW7StoBxQXGWL+EQZqMp2VLc3afanm4CwiJMDsuKUhtnfz2uJfiTOvzt6dv1VW7j5sOiO42y4AQOUhzFpo9S97iQG1e4B7flL0s6F5tV+rOtJCkuSeK86Q6Iiyr5xXUT8u31vljwEAKECYtRjqZYHihQUHyIA2cfLnphRpUy9SLurZ2HQhqBMeINOmTTOXV9ljF6qD1RDdu0VtGdGlgQzvVF9Oe3GuZObkV9njA0BNRZi1GOplgZJNueZkOZiRI3GRwY5fMXJycqr8cS87uYlZ2CQsOFDO7FRfhnWKN2VBAICqRZi1EJ3p6dq45MUSgJouMMBf6kZ5PkS2rBspX9/cz+OPCwA1XfG7AsPntK8fLeHBfP8AAACwI8xaCPWyQPWlCzroAQBQPkzzWQj1skD1smN/usxelyRz1iXK4m0HTO/c727tJ63rFSwCAQAoHWHWQpiZBawv9WiOPPvrOpmzLsmsCuZyWWauzN+UQpgFgHIgzFpEbHiQtHBapQiANe09nCn/+31rsZcfayntsOtAhszdkGQWYRjSoZ6c2blB1W8kAFgIYdYiejRhsQTAykICA1z6zOrHWUuHzuhQT3LzbPLKrI3m/Oy8fDM7qwFWD1uTj68iNm3VPjmjQ7xjGd+s3DxZsv2g/LEpRQ4fzZbbB7eRhrGsEAigZiHMWkQP6mUBS7ttUCv5+O8d0rlhjAmkg9rVlTrH+tD+tOL4imHP/bq+2PvIyM6TDQlpsmTHQfljY7L8tXW/Oc9Ov/A+c0GXKn4mAOBbCLMWQb0sYG03DmxlDuXtLa2zt3sOHZV9hzPNeee8Mb/Y6x/KyBZP0hKINXsPS6eGMdKkdrhHHxsA7AizPqzRsZ8Lo0ICpXsTwixQXXVpFCMhgf6SlZtvVi47rW09Ob1dXRnYpq7EhAfJ1e8tcoRZZ7o4hJYgzVybWOXbaLPZZNeBo/L31v3y97b9smjrAROyVUxYkCx68AwJLbSkLwB4AmHWh90xpK35x6p3izoSFRrk7c0BUEV05865d58uaZm50qZepPjrlKyTQe3qyZ+bUiQ4wF96Na8lA9sWBN0ODaIkITXTbZhNOZIlC7fslwWbUmTJzoPSvE6E/N+oHo7AqfW2y3Yekr+27JdtKekyqk9TOaVlHZfwumN/hgmvi7YdMH/dBWp1+GiOJKVmSdM6zM4C8DzCrA+rHREs4wa38fZmAPCAknbcuvbUFjK8c32JDQuSiJDi/7etM6dPTl0rCzanyPqENJfLtA3Ye/O3meMLt6TIv9sPmplgu/UJqTL5qp7y99YDsmjbfhNeE1Ozin0snUkODvQ3ARwAvIkwCwAWKjsqyao9h82hOC/O2FDsZRsTj8jgl38v9vLQIH/p1ay29GlRW05pVUe6No6Re79ZKT8uP77zGgB4A2EWACwsNLBonaq2/dI63H6t4mTFrkOm60FhDWNCpW+rOPl26W6396urkfVsVsuUHpzSsrZ0aRRrZmIBwNcQZgHAwmpFBMvtg1ubXrNdG8VI/9YaPutIbHiwo7xgzPuLJScv35zft1Ud6deqjjStHW5aeUWFBsoHC7dLRHCA9Gpe21ynjwmvMY5+tgDgy3wizE6aNElefPFFSUhIkG7duskbb7whvXv3dnvdd955Rz766CNZvXq1Od2zZ0955plnir0+AFR3dw1rZw7utK4XKQvuH1zsbSee21FuOb2V1IkIlkDCKwAL8vr/ub788kuZMGGCTJw4UZYuXWrC7PDhwyUpKcnt9efNmydXXHGFzJ07V/766y9p0qSJDBs2TPbs2ePxbQcAq9PZ2fjoUIIsAMvy+v+9XnnlFbnhhhtk7Nix0rFjR5k8ebKEh4fL+++/7/b6n376qdx6663SvXt3ad++vbz77ruSn58vc+bM8fi2AwAAoAaXGWRnZ8uSJUvkgQcecJzn7+8vQ4YMMbOuZZGRkSE5OTlSu3Ztt5dnZWWZg11qaqr5q7fRQ1WzP4YnHgtVgzG0PsawauhEgl1ObtX+P5UxtDbGz/pyPDyG5Xkcr4bZlJQUycvLk/j4eJfz9fT69cWvT+7svvvuk4YNG5oA7M6zzz4rjz/+eJHzZ86caWaAPWXWrFkeeyxUDcbQ+hjDyrV3r7/jBz4tAYsLrfrHZAytjfGzvlkeGkOdrLTUDmAV9dxzz8kXX3xh/icaGur+/6I666s1uc4zs/Y62+joaI98s9CBHzp0qAQFsYqXFTGG1scYVo3ZX6+UJSkJ5vjpp59uOiRUFcbQ2hg/68vx8Bjaf0n3+TAbFxcnAQEBkpjouhSjnq5fv36Jt33ppZdMmJ09e7Z07dq12OuFhISYQ2E6EJ78QHn68VD5GEPrYwwrl5aF2QUFHn9tj2Tlyspdh2TZrkNyMD1bxp7aokyLPpQFY2htjJ/1BXloDMvzGF4Ns8HBwaa1lu68NXLkSHOefWeucePGFXu7F154QZ5++mmZMWOG9OrVy4NbDABw58fle2T3waOyfNch2ZiUJjbb8cv2Hc6USVee5M3NA1CNeb3MQEsAxowZY0Kp9op97bXXJD093XQ3UKNHj5ZGjRqZ2lf1/PPPy6OPPiqfffaZNG/e3PSmVZGRkeYAAPC8l2dtLPaylCPHd8IFgGoXZi+77DJJTk42AVWDqbbcmj59umOnsJ07d7r8lPXWW2+ZLggXX3yxy/1on9rHHnvM49sPADVVREjRf0IC/P2kff0o6do4Rj5fvKvI5QfSs2Xl7kOycvdhWbP3sDSICZP7z2ovoUFFl+UFAEuEWaUlBcWVFejOXc62b9/uoa0CAJTkulNbyN5DRyU0MEBOahYr3ZvUMsvghgUHSFZuniPM7jqQIbd9ulRW7jkkuw4cLXI/urzusE4l7ycBAD4dZgEA1tOqbqR8MLb0pcT3Hs6Uvav2FXt5WmZuJW8ZgJqEMAsAqHRB/v4SGx4khzKONz4PDfKXzg1jpGvjWNmfniU/Lt/r1W0EUD0QZgEAlc7f30/eHd1LZq9LkhZx4SbAtqkXKYEBBftAfPz3Dpcwm59vkx0HMkwd7eo9qeavdke4/OQmctNprbz4TAD4OsIsAKBK9Gpe2xxK89qcjTLxpzWmP21hr8/ZRJgFUCLCLADAq9ztFGaXmZvv0W0BYD2EWQCAx3VsECV+fuJYXKFhTKh0ahRjamo7NYyW56evl01JR7y9mQAsgDALAPC4ns1qyy+3D5CDGdnSoUG01I4Idrn89d82eW3bAFgLYRYA4BUdG0Z7exMAVAPHl9YCAAAALIYwCwCoNvLybbI9JV3mbkgyK495WmZOnqRlHu+tC6DqUWYAALAUXSp3S1K6JKQeFX8/P9mYmCYbEo6Yv5uS0iQzp6ADQkRwgCy4f7DEhrvW4xaWkZ1r7k9vqzudbU46IrXDg+XhczpIVGiQ29scSM+WLclHZEvSEfNXb7MlOV12HcwwO7W9dll3GdmjUZU8fwCuCLMAAJ9ls9lk+uoEWbv3kPyx0V9e37xAtu/PMDOwpUnPzpOtKelyUtOCMJuamWNC5+bEIya46nENr7o4gzvdmsTKqa3jCkKrI7AWhFYNsyXRbSbMAp5BmAUA+CzNrDd/ssSpMi692Otqq6/mdSIkKydP9h7ONOe9/ftWSc/OlU2JRyQhteC8snrw+1Xlur4u12ufFc639xwDUOUIswAAnxMeHOD2/OBAf2ldN1LW7ks1M6entKwt7eKjpG18lLSuFymhQQHy+M9rZMqC7eb609cklPg4USGB0jo+0iy126ZelJnJ/XzxzhJvEx8dIq3qRprH07/24/5+Ir2fmeNyXV2md+/ho7ItJd0cduzPkLbxkXJprybip+kbwAkjzAIAfM6dQ9rKq7M2Sq3wYGlbP0pax4VJwoalcvXIMyUsNKTE2zaKDStyXmx4kLStF+USXDWAajB1DpUH07Nl0bb9snN/hjSrE14QVutFmgCtf1vWjZDoYupok9KOz/wu2XFQhr/6h2zbny7ZblYxa1c/Wro3iS3nqwLAHcIsAMDnnNKyjnx5U1/H6ZycHJm2UyQwoPQmPNf0ay4RIYGSm5cvretFSZv4SKkTEVymmdBaEcHy212nm5rcAJ1qraD96dnmUJyUtKwK3zcAV4RZAEC1ooH3it5NT+g+KhJk4yJCpGntcNl5rCVYUICfNKsTIS3iIqRlXITZ2ey39UkntF0AiiLMAgBQCfz9/eTH2/rLhsQ0aRgTJo1qhbmE4klzNxNmgSpAmAUAoJJomYKWSADwHMIsAAAepqUIs9cmyo4DGWalsh37083xwxk5ctNpLeXGga28vYmAZRBmAQDwsCemri32svfmbyPMAuVQ+m6hAADghIUFue+dW1hOHgsuAOXBzCwAAB5wXveGsmBzihzMyDZdDprUDpdmtcOlaZ2CvxdP/svRCQFA2RFmAQDwgLjIEHnvmpOLvZwFwYCKIcwCAOBD8m02s1PYroMZsufgUdl98KjsOaR/MyQyJFCeGtlF6seEenszAZ9BmAUAwIccysiRAS/MLfbyro13yX/OaOPRbQJ8GTuAAQDgA0ICy/ZPcnp2bpVvC2AlzMwCAOADbjm9lbwxZ7NEhgZK41ph0ii24NC4VrikHMmS+79b5e1NBHwSYRYAAB9wQY/G5uDOoq37K3y/2bn5kpiaKTl5+dIiLkL82NMM1QxhFgAAi8rKzZPEw1my7/BR2Xc40xwSjh1PSM2UvYcyzayu3fghbeWOIdTbonohzAIAYCH/+32r6Ve771Cm7E/PLtdt529OJsyi2mEHMAAALGb1ntRSg6y/n0j96FDp1iTWcZ6NxcVQDTEzCwCAj2tXP0pqhQfJwYwcczrA30/io0JMv9kGMWHSICb0+PFY/RsqdSNDJDDAX/LybdLqwWnefgpAlSHMAgDg42LDg+W3u043CynUiwqVulEhJtBWdT1uypFsSU7LkiOZudKtSYxEhQZV6WMCFUGYBQDAAmpFBJvDiciz2SThcKYJqLpjmP5NPvY3pdDf1EzXfrbdm8TKD7f1P35f+TbZn15wXe2R27pe1AltG1BRhFkAAGqIZTsPySnPzqnQbZfvOiSj319cEIDTsuRAepbkO9XgvnRJN7m4Z2O3rcE0QO86IjJvY7IcPKozvlmSkpZt/url1w9oIb2a1z6Rp4YajDALAEA1psUIwYH+JjSWRXhwgCljiIsMMXW309ckOC77Y2Nysbe7++sVsnrPYTPTm3JshlfLFA4fzTkeOVYtc3tbbS3247hTy/nMgAKEWQAAqjF/fz+5a2hb+XrJbokKDSwIqfawGqWBNdhxWg8RIa7R4Pnp6+WteVscp4MC/EzI1dtoUN2+P8Nx2QcLt1doGwuXNADlQZgFAKCau+m0VuZQEfcMayfndm1YEGKjQiQmLMixitiRrFw5+anZcjQnz+0Mb0FADpY6EcGSfiBBTurQWuJjwgrOjwqRa6f8I2lZBFmcGMIsAAAocWa3Y8Not5dFhgTKT+P6y9KdB03HBXtpQlxUsIQHH48YOTk5Mm3aNBlxRmsJCjreESEggKV1ceIIswAAoMLaxEeZQ2W1AzuUkSMHM7LlYHqOHNK/x07r8QOO8/R0jpkZPrtrA5l4bifHfWhtsP12Af4irepGOmaS7V0Y9PJDR3PMohKFyyqc5eblm1IKPej1D2fo34LH1hnq87s3qvIWaSgdYRYAAHjVjv3p0unR6ZKeXbRcoTRTFmyXeRuSJTc/3wRgDbiFaVsxe8BNzcxxWQntopMaS0iQvyOomuCaURBcSyuB0Mca3be5y3k2m02y8/IlJDCg3M8FFUOYBQAAXhHo72/+aouvigRZu20p6aW2FSvOt0t3V/hxH/1xjfyxMUUOH5utNbO3R3PM7HDv5rXl8xtPYebWAwizAADAK8b0bSb/+2OrWXQhNjxIaoUHm9pbXbrXLBJx7LjzeXq92LBg+WnFXtMOTGle1OvoZbWP3cfsdYkujxUdGnjs9sGycvchl9lZZxo+Y8OCTBlBjHmsgsc3p8OCZEvyEZm6cp/j+oUfx27x9gOyfX+6KXNA1SLMAgAAr7j9jDbmUBG6QMPQjvHmZ/3o0CCzo1rhete9hzIlIiTAhNBALaB18u/2A5KQmmkCsz2oahjWndqca2wL0/KDhVv2y4H07CLdGzT4amlC2rFWY1qfi6pHmAUAAJakAbQ4Gl6b1gkv9vKKrjims7WzJ5xmSht0tldP63bYa2Tv+2alfPnvLnN8+c5Dsu9wpqQeLajVTT2aa8oQDqZnS7/WdUzHB+fLCv7mSPsG0TK2X3OXgK47x+l1NCDXjwl12abs3HxJy8wxIVq35USXPbYawiwAAEA51I4INofS3PvtymIvswfe4jw5da20jIswC0poyC28glvLuhEmvKZl5khmzvHLAv395K2reppZ65rCdc4dAAAAFRZfaNb0RGxNSTfLArtbinhrcrokp2W5BFmVm2+T6auPL0FcEzAzCwAAUEmu6ddcsnLyTNCMDgsypQgFf4MkOixQdh04Kmv3pUq9qJAil2sJwfUf/eu4r6iQgst0GWK9XHcqc75Mz48KLbhcSxIWbyu4XAOwtjvTmVttH3bk2N/07FzTZaGy+gL7CsIsAABAJdHygwdGdKjw7bc9O8KUFuiOaO7aeumObbqDWuHLtqWky6CX5pnjv29MltNeLDheWHCAvyx8YLBZra26IMwCAAD4CA2qpe3Y5k50aEH4La2Dgi7osCnxiAmz2gkiIzvPzNimZ+VJUICfNK5V/E5zvoowCwAAYHF1IkPkifM7ybRV+yQ0MEAiQwPN7K7+1ZIEbSemB3XFO3+byzTEFu63e/NpreT+s9qLlRBmAQAAqoEr+zQzB3fy8sURZpW7ZX/Vr6v3EWYBAADgWy7o0UhmrEmQXQcyJCIk0CwmobOzBccD5fcNyaYEId/N0mhap6stwHx1DQjCLAAAQDXXtE64TLtjQLGX93pqlqQcyTbdFoa88rsczc6TDK2lzc5ztAaLCQqQzqekS5v6seJLCLMAAAA1XJDTjmWbk464vc7hHD+ZsSbJ58IsiyYAAADUcGP7N5eQQH/x8xOJCA4w3Q6a1QmXDg2iiyzK4GuYmQUAAKjhbhzYSq7t38K099L2YM5+W58o135wfDEHX0OYBQAAgBTXw7Zfqzj54+6BMve33+TcU5qKr6HMAAAAAMUKDQqQBjGhEhsiZulcX0OYBQAAgGURZgEAAGBZhFkAAABYFmEWAAAAlkWYBQAAgGURZgEAAGBZhFkAAABYFmEWAAAAlkWYBQAAgGURZgEAAGBZhFkAAABYFmEWAAAAlkWYBQAAgGURZgEAAGBZhFkAAABYFmEWAAAAlkWYBQAAgGUFSg1js9nM39TUVI88Xk5OjmRkZJjHCwoK8shjonIxhtbHGFofY2htjJ/15Xh4DO05zZ7bSlLjwmxaWpr526RJE29vCgAAAErJbTExMSVdRfxsZYm81Uh+fr7s3btXoqKixM/PzyPfLDQ479q1S6Kjo6v88VD5GEPrYwytjzG0NsbP+lI9PIYaTzXINmzYUPz9S66KrXEzs/qCNG7c2OOPqwPPB9jaGEPrYwytjzG0NsbP+qI9OIalzcjasQMYAAAALIswCwAAAMsizFaxkJAQmThxovkLa2IMrY8xtD7G0NoYP+sL8eExrHE7gAEAAKD6YGYWAAAAlkWYBQAAgGURZgEAAGBZhFkAAABYFmG2EkyaNEmaN28uoaGh0qdPH1m8eHGJ1//666+lffv25vpdunSRadOmeWxbceJj+M4778iAAQOkVq1a5jBkyJBSxxy+9zm0++KLL8xqgCNHjqzybUTljuGhQ4fktttukwYNGpg9rNu2bcv/Ty00fq+99pq0a9dOwsLCzMpS48ePl8zMTI9tL1z98ccfcu6555oVt/T/iT/88IOUZt68eXLSSSeZz1/r1q3lgw8+EK/QbgaouC+++MIWHBxse//9921r1qyx3XDDDbbY2FhbYmKi2+svWLDAFhAQYHvhhRdsa9eutT388MO2oKAg26pVqzy+7ajYGI4aNco2adIk27Jly2zr1q2zXXPNNbaYmBjb7t27Pb7tqNgY2m3bts3WqFEj24ABA2znn3++x7YXJz6GWVlZtl69etlGjBhhmz9/vhnLefPm2ZYvX+7xbUf5x+/TTz+1hYSEmL86djNmzLA1aNDANn78eI9vOwpMmzbN9tBDD9m+++477XJl+/77720l2bp1qy08PNw2YcIEk2feeOMNk2+mT59u8zTC7Anq3bu37bbbbnOczsvLszVs2ND27LPPur3+pZdeajv77LNdzuvTp4/tpptuqvJtReWMYWG5ubm2qKgo24cffliFW4nKHkMdt379+tneffdd25gxYwizFhvDt956y9ayZUtbdna2B7cSlTV+et3Bgwe7nKehqH///lW+rShdWcLsvffea+vUqZPLeZdddplt+PDhNk+jzOAEZGdny5IlS8zPzHb+/v7m9F9//eX2Nnq+8/XV8OHDi70+fG8MC8vIyJCcnBypXbt2FW4pKnsMn3jiCalXr55cd911HtpSVOYY/vTTT9K3b19TZhAfHy+dO3eWZ555RvLy8jy45ajo+PXr18/cxl6KsHXrVlMiMmLECI9tN06ML+WZQI8/YjWSkpJi/sep/yN1pqfXr1/v9jYJCQlur6/nwxpjWNh9991naowKf6jhu2M4f/58ee+992T58uUe2kpU9hhq+Pntt9/kyiuvNCFo8+bNcuutt5ovlrpKEXx7/EaNGmVud+qpp+ovxJKbmys333yzPPjggx7aapyo4vJMamqqHD161NRCewozs8AJeO6558wORN9//73Z6QG+Ly0tTa6++mqzI19cXJy3NwcVlJ+fb2bW3377benZs6dcdtll8tBDD8nkyZO9vWkoA91xSGfS33zzTVm6dKl899138ssvv8iTTz7p7U2DBTEzewL0H8KAgABJTEx0OV9P169f3+1t9PzyXB++N4Z2L730kgmzs2fPlq5du1bxlqKyxnDLli2yfft2s9euczBSgYGBsmHDBmnVqpUHthwn8jnUDgZBQUHmdnYdOnQws0X6s3dwcHCVbzcqPn6PPPKI+VJ5/fXXm9Pa2Sc9PV1uvPFG86VEyxTg2+oXk2eio6M9OiureLecAP2fpc4IzJkzx+UfRT2ttVzu6PnO11ezZs0q9vrwvTFUL7zwgplBmD59uvTq1ctDW4vKGENti7dq1SpTYmA/nHfeeTJo0CBzXFsEwfc/h/379zelBfYvImrjxo0m5BJkfX/8dF+DwoHV/sWkYP8j+Lq+vpRnPL7LWTVsR6LtRT744APTmuLGG2807UgSEhLM5VdffbXt/vvvd2nNFRgYaHvppZdMW6eJEyfSmstiY/jcc8+ZFjTffPONbd++fY5DWlqaF59FzVbeMSyMbgbWG8OdO3eaLiLjxo2zbdiwwTZ16lRbvXr1bE899ZQXn0XNVd7x03/7dPw+//xz0+Jp5syZtlatWpmOP/COtLQ003JSDxoPX3nlFXN8x44d5nIdPx3Hwq257rnnHpNntGUlrbksTHurNW3a1AQcbU/y999/Oy477bTTzD+Uzr766itb27ZtzfW1rcUvv/ziha1GRcewWbNm5oNe+KD/c4Z1PofOCLPWHMOFCxea1oYaorRN19NPP21arsH3xy8nJ8f22GOPmQAbGhpqa9Kkie3WW2+1HTx40Etbj7lz57r9t80+bvpXx7Hwbbp3727GXD+DU6ZM8cq2++l/PD8fDAAAAJw4amYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBAABgWYRZAAAAWBZhFgAAAJZFmAUAAIBlEWYBoAbz8/OTH374wRzfvn27Ob18+XJvbxYAlBlhFgC85JprrjHhUQ9BQUHSokULuffeeyUzM9PbmwYAlhHo7Q0AgJrszDPPlClTpkhOTo4sWbJExowZY8Lt888/7+1NAwBLYGYWALwoJCRE6tevL02aNJGRI0fKkCFDZNasWeay/Px8efbZZ82MbVhYmHTr1k2++eYbl9uvWbNGzjnnHImOjpaoqCgZMGCAbNmyxVz2zz//yNChQyUuLk5iYmLktNNOk6VLl3rleQJAVSHMAoCPWL16tSxcuFCCg4PNaQ2yH330kUyePNmE1vHjx8tVV10lv//+u7l8z549MnDgQBOIf/vtNzOze+2110pubq65PC0tzcz0zp8/X/7++29p06aNjBgxwpwPANUFZQYA4EVTp06VyMhIE0CzsrLE399f/u///s8cf+aZZ2T27NnSt29fc92WLVuaYPq///3PzLJOmjTJzLh+8cUXpuZWtW3b1nHfgwcPdnmst99+W2JjY00Y1tlcAKgOCLMA4EWDBg2St956S9LT0+XVV1+VwMBAueiii8xMbEZGhikTcJadnS09evQwx7XrgJYV2INsYYmJifLwww/LvHnzJCkpSfLy8sx97ty50yPPDQA8gTALAF4UEREhrVu3Nsfff/99Uxf73nvvSefOnc15v/zyizRq1MjlNlpWoLSOtiRaYrB//37573//K82aNTO301leDcQAUF0QZgHAR2iJwYMPPigTJkyQjRs3mvCps6haUuBO165d5cMPPzSdENzNzi5YsEDefPNNUyerdu3aJSkpKVX+PADAk9gBDAB8yCWXXCIBAQGmLvbuu+82O31pYNUOBdqJ4I033jCn1bhx4yQ1NVUuv/xy+ffff2XTpk3y8ccfy4YNG8zlusOXnl63bp0sWrRIrrzyylJncwHAapiZBQAfojWzGlJfeOEF2bZtm9StW9d0Ndi6davZeeukk04ys7eqTp06povBPffcY2ZvNQR3795d+vfvby7XcoUbb7zR3EZbf+kOZRqQAaA68bPZbDZvbwQAAABQEZQZAAAAwLIIswAAALAswiwAAAAsizALAAAAyyLMAgAAwLIIswAAALAswiwAAAAsizALAAAAyyLMAgAAwLIIswAAALAswiwAAADEqv4fbNDXt8cK1rEAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from sklearn.metrics import roc_curve, precision_recall_curve\n", + "\n", + "# ROC Curve\n", + "fpr, tpr, _ = roc_curve(all_labels, all_preds)\n", + "plt.figure(figsize=(8, 6))\n", + "plt.plot(fpr, tpr, label=f'ROC-AUC: {gnn_roc:.3f}', linewidth=2)\n", + "plt.plot([0, 1], [0, 1], 'k--', label='Random')\n", + "plt.xlabel(\"False Positive Rate\")\n", + "plt.ylabel(\"True Positive Rate\")\n", + "plt.title(\"GCN Model - ROC Curve\")\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.show()\n", + "\n", + "# Precision-Recall Curve\n", + "precision, recall, _ = precision_recall_curve(all_labels, all_preds)\n", + "plt.figure(figsize=(8, 6))\n", + "plt.plot(recall, precision, label=f\"PR-AUC: {roc_auc_score(all_labels, all_preds):.3f}\", linewidth=2)\n", + "plt.xlabel(\"Recall\")\n", + "plt.ylabel(\"Precision\")\n", + "plt.title(\"GCN Model - Precision-Recall Curve\")\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "f619a4e5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from dash import Dash, html, dcc, Input, Output\n", + "import dash\n", + "import plotly.express as px\n", + "import numpy as np\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "from rdkit import Chem\n", + "from rdkit.Chem import AllChem, rdMolDescriptors\n", + "from torch_geometric.data import Data\n", + "from torch_geometric.nn import GCNConv, global_mean_pool\n", + "import threading, webbrowser, nest_asyncio\n", + "nest_asyncio.apply()\n", + "\n", + "# ============================\n", + "# Fingerprint-based MLP Model\n", + "# ============================\n", + "class ToxicityNet(nn.Module):\n", + " def __init__(self):\n", + " super().__init__()\n", + " self.model = nn.Sequential(\n", + " nn.Linear(1024, 512),\n", + " nn.ReLU(),\n", + " nn.Dropout(0.3),\n", + " nn.Linear(512, 128),\n", + " nn.ReLU(),\n", + " nn.Linear(128, 1)\n", + " )\n", + " def forward(self, x):\n", + " return self.model(x)\n", + "\n", + "model = ToxicityNet()\n", + "try:\n", + " model.load_state_dict(torch.load(\"tox_model.pt\"))\n", + " model.eval()\n", + " model_loaded = True\n", + "except:\n", + " model_loaded = False\n", + "\n", + "fp_generator = GetMorganGenerator(radius=2, fpSize=1024)\n", + "def predict_toxicity(smiles):\n", + " if not model_loaded:\n", + " return \"Model not loaded\", 0.0\n", + " try:\n", + " mol = Chem.MolFromSmiles(smiles)\n", + " if mol is None:\n", + " return \"Invalid SMILES\", 0.0\n", + " fp = fp_generator.GetFingerprint(mol)\n", + " fp_array = np.array(fp).reshape(1, -1)\n", + " with torch.no_grad():\n", + " logits = model(torch.tensor(fp_array).float())\n", + " prob = torch.sigmoid(logits).item()\n", + " return (\"Toxic\" if prob > 0.5 else \"Non-toxic\"), prob\n", + " except Exception as e:\n", + " return f\"Error: {str(e)}\", 0.0\n", + "\n", + "# ============================\n", + "# GCN Model\n", + "# ============================\n", + "class RichGCNModel(nn.Module):\n", + " def __init__(self):\n", + " super().__init__()\n", + " self.conv1 = GCNConv(10, 64)\n", + " self.bn1 = nn.BatchNorm1d(64)\n", + " self.conv2 = GCNConv(64, 128)\n", + " self.bn2 = nn.BatchNorm1d(128)\n", + " self.dropout = nn.Dropout(0.2)\n", + " self.fc1 = nn.Linear(128, 64)\n", + " self.fc2 = nn.Linear(64, 1)\n", + "\n", + " def forward(self, data):\n", + " x, edge_index, batch = data.x, data.edge_index, data.batch\n", + " x = F.relu(self.bn1(self.conv1(x, edge_index)))\n", + " x = F.relu(self.bn2(self.conv2(x, edge_index)))\n", + " x = global_mean_pool(x, batch)\n", + " x = self.dropout(x)\n", + " x = F.relu(self.fc1(x))\n", + " return self.fc2(x)\n", + "\n", + "\n", + "gcn_model = RichGCNModel()\n", + "try:\n", + " gcn_model.load_state_dict(torch.load(\"gcn_model.pt\"))\n", + " gcn_model.eval()\n", + " gcn_model_loaded = True\n", + "except:\n", + " gcn_model_loaded = False\n", + "\n", + "def atom_to_features_gcn(atom):\n", + " return [\n", + " atom.GetAtomicNum(),\n", + " atom.GetDegree(),\n", + " atom.GetFormalCharge(),\n", + " atom.GetNumExplicitHs(),\n", + " atom.GetNumImplicitHs(),\n", + " atom.GetIsAromatic(),\n", + " atom.GetMass(),\n", + " int(atom.IsInRing()),\n", + " int(atom.GetChiralTag()),\n", + " int(atom.GetHybridization())\n", + " ]\n", + "\n", + "def smiles_to_graph_gcn(smiles):\n", + " mol = Chem.MolFromSmiles(smiles)\n", + " if mol is None:\n", + " return None\n", + " atoms = [atom_to_features_gcn(atom) for atom in mol.GetAtoms()]\n", + " edges = []\n", + " for bond in mol.GetBonds():\n", + " i, j = bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()\n", + " edges += [[i, j], [j, i]]\n", + " if not edges:\n", + " edges = [[0, 0]]\n", + " return Data(\n", + " x=torch.tensor(atoms, dtype=torch.float),\n", + " edge_index=torch.tensor(edges, dtype=torch.long).t().contiguous(),\n", + " batch=torch.zeros(len(atoms), dtype=torch.long)\n", + " )\n", + "\n", + "def predict_toxicity_gcn(smiles):\n", + " if not gcn_model_loaded:\n", + " return \"GCN Model not loaded\", 0.0\n", + " try:\n", + " graph_data = smiles_to_graph_gcn(smiles)\n", + " if graph_data is None:\n", + " return \"Invalid SMILES\", 0.0\n", + " with torch.no_grad():\n", + " logits = gcn_model(graph_data)\n", + " prob = torch.sigmoid(logits).item()\n", + " return (\"Toxic\" if prob > best_threshold else \"Non-toxic\"), prob\n", + " except Exception as e:\n", + " return f\"Error: {str(e)}\", 0.0\n", + "\n", + "# ============================\n", + "# Dash App with Tabs\n", + "# ============================\n", + "app = Dash(__name__, suppress_callback_exceptions=True)\n", + "app.title = \"Drug Toxicity Prediction\"\n", + "\n", + "# Histogram samples\n", + "fig_sample_fp = px.histogram(\n", + " x=np.random.beta(2, 5, 100),\n", + " color=np.random.binomial(1, 0.3, 100).astype(str),\n", + " nbins=20,\n", + " title=\"Sample Prediction Probability Distribution\",\n", + " labels={\"x\": \"Predicted Probability\", \"color\": \"Actual Label\"}\n", + ")\n", + "\n", + "fig_sample_gcn = px.histogram(\n", + " x=np.random.beta(2, 5, 100),\n", + " color=np.random.binomial(1, 0.3, 100).astype(str),\n", + " nbins=20,\n", + " title=\"GCN Model - Sample Prediction Probability Distribution\",\n", + " labels={\"x\": \"Predicted Probability\", \"color\": \"Actual Label\"}\n", + ")\n", + "\n", + "# App layout with Tabs\n", + "app.layout = html.Div([\n", + " html.H1(\"🧪 Drug Toxicity Prediction Dashboard\", style={\"textAlign\": \"center\", \"color\": \"#2c3e50\"}),\n", + " dcc.Tabs(id='tabs', value='tab-fp', children=[\n", + " dcc.Tab(label='Fingerprint Model', value='tab-fp'),\n", + " dcc.Tab(label='GCN Model', value='tab-gcn'),\n", + " ]),\n", + " html.Div(id='tab-content')\n", + "])\n", + "\n", + "# ============================\n", + "# Tab Content Callbacks\n", + "# ============================\n", + "@app.callback(Output('tab-content', 'children'), Input('tabs', 'value'))\n", + "def render_tab(tab):\n", + " if tab == 'tab-fp':\n", + " return html.Div([\n", + " html.Div([dcc.Graph(figure=fig_sample_fp)], style={\"width\": \"48%\", \"display\": \"inline-block\"}),\n", + " html.Div([ html.H3(\"Make a Prediction\"),\n", + " html.Label(\"Enter SMILES string:\"),\n", + " dcc.Input(id='fp-smiles', value='CCO', type='text', debounce=True,\n", + " style={\"width\": \"100%\", \"padding\": \"10px\", \"marginBottom\": \"10px\"}),\n", + " html.Div(id='fp-output', style={\"marginTop\": \"1rem\", \"fontSize\": \"18px\", \"padding\": \"10px\"}),\n", + " html.Div(id='fp-prob', style={\"marginTop\": \"1rem\", \"fontSize\": \"16px\"}),\n", + " html.Hr(),\n", + " html.H4(\"Example SMILES:\"), html.P(\"• CCO\"), html.P(\"• CC(=O)O\"), html.P(\"• c1ccccc1\"),\n", + " ], style={\"width\": \"48%\", \"float\": \"right\", \"padding\": \"20px\"}),\n", + " html.Div(id='fp-info', style={\"marginTop\": \"2rem\", \"padding\": \"20px\"})\n", + " ])\n", + " elif tab == 'tab-gcn':\n", + " return html.Div([\n", + " html.Div([dcc.Graph(figure=fig_sample_gcn)], style={\"width\": \"48%\", \"display\": \"inline-block\"}),\n", + " html.Div([\n", + " html.H3(\"🔬 Graph Neural Network Prediction\"),\n", + " html.P(\"This model uses molecular graph structure and atom features\", style={\"fontSize\": \"14px\"}),\n", + " html.Label(\"Enter SMILES string:\"),\n", + " dcc.Input(id='gcn-smiles', value='CCO', type='text', debounce=True,\n", + " style={\"width\": \"100%\", \"padding\": \"10px\", \"marginBottom\": \"10px\"}),\n", + " html.Div(id='gcn-output', style={\"marginTop\": \"1rem\", \"fontSize\": \"18px\", \"padding\": \"10px\"}),\n", + " html.Div(id='gcn-prob', style={\"marginTop\": \"1rem\", \"fontSize\": \"16px\"}),\n", + " html.Hr(),\n", + " html.H4(\"Test Molecules:\"), html.P(\"• c1ccc(cc1)N\"), html.P(\"• C=CC=O\"),\n", + " ], style={\"width\": \"48%\", \"float\": \"right\", \"padding\": \"20px\"}),\n", + " html.Div(id='gcn-info', style={\"marginTop\": \"2rem\", \"padding\": \"20px\"})\n", + " ])\n", + "\n", + "# ============================\n", + "# Callback for Fingerprint Tab\n", + "# ============================\n", + "@app.callback(\n", + " [Output('fp-output', 'children'), Output('fp-output', 'style'),\n", + " Output('fp-prob', 'children'), Output('fp-info', 'children')],\n", + " Input('fp-smiles', 'value')\n", + ")\n", + "def update_fp_tab(smiles):\n", + " if not smiles:\n", + " return \"Enter SMILES\", {\"color\": \"gray\"}, \"\", \"\"\n", + " result, prob = predict_toxicity(smiles)\n", + " color = \"green\" if \"Non\" in result else \"red\" if \"Toxic\" in result else \"orange\"\n", + " info = html.Div()\n", + " try:\n", + " mol = Chem.MolFromSmiles(smiles)\n", + " if mol:\n", + " info = html.Div([\n", + " html.H4(\"Molecule Info:\"),\n", + " html.P(f\"Formula: {rdMolDescriptors.CalcMolFormula(mol)}\"),\n", + " html.P(f\"Weight: {rdMolDescriptors.CalcExactMolWt(mol):.2f}\"),\n", + " html.P(f\"Atoms: {mol.GetNumAtoms()}\"),\n", + " html.P(f\"Bonds: {mol.GetNumBonds()}\")\n", + " ])\n", + " except: pass\n", + " return result, {\"color\": color, \"fontWeight\": \"bold\"}, f\"Probability: {prob:.3f}\", info\n", + "\n", + "# ============================\n", + "# Callback for GCN Tab\n", + "# ============================\n", + "@app.callback(\n", + " [Output('gcn-output', 'children'), Output('gcn-output', 'style'),\n", + " Output('gcn-prob', 'children'), Output('gcn-info', 'children')],\n", + " Input('gcn-smiles', 'value')\n", + ")\n", + "def update_gcn_tab(smiles):\n", + " if not smiles:\n", + " return \"Enter SMILES\", {\"color\": \"gray\"}, \"\", \"\"\n", + " result, prob = predict_toxicity_gcn(smiles)\n", + " color = \"green\" if \"Non\" in result else \"red\" if \"Toxic\" in result else \"orange\"\n", + " info = html.Div()\n", + " try:\n", + " mol = Chem.MolFromSmiles(smiles)\n", + " graph_data = smiles_to_graph_gcn(smiles)\n", + " if mol and graph_data:\n", + " info = html.Div([\n", + " html.H4(\"Graph Info:\"),\n", + " html.P(f\"Formula: {rdMolDescriptors.CalcMolFormula(mol)}\"),\n", + " html.P(f\"Weight: {rdMolDescriptors.CalcExactMolWt(mol):.2f}\"),\n", + " html.P(f\"Atoms: {mol.GetNumAtoms()}\"),\n", + " html.P(f\"Bonds: {mol.GetNumBonds()}\"),\n", + " html.P(f\"Edges: {graph_data.edge_index.shape[1]}\"),\n", + " html.P(f\"Node Features: 5\")\n", + " ])\n", + " except: pass\n", + " return result, {\"color\": color, \"fontWeight\": \"bold\"}, f\"GCN Probability: {prob:.3f}\", info\n", + "\n", + "# ============================\n", + "# Run App\n", + "# ============================\n", + "def open_browser():\n", + " webbrowser.open_new(\"http://127.0.0.1:8050\")\n", + "threading.Timer(1, open_browser).start()\n", + "\n", + "if __name__ == '__main__':\n", + " app.run(debug=True, port=8050)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dbbddde7", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "drug_env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.18" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}