{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":14774,"databundleVersionId":875431,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":2298006,"sourceType":"datasetVersion","datasetId":1381848},{"sourceId":320161,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":270061,"modelId":291046}],"dockerImageVersionId":30919,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nfrom torch.utils.data import DataLoader, Dataset\nfrom PIL import Image\nimport os\n\n# Paths\ndata_dir = \"/kaggle/input/aptos2019-blindness-detection\"\ntrain_csv = os.path.join(data_dir, \"train.csv\")\ntest_csv = os.path.join(data_dir, \"test.csv\")\ntrain_img_dir = os.path.join(data_dir, \"train_images\")\ntest_img_dir = os.path.join(data_dir, \"test_images\")\n\n# Load dataset\ntrain_df = pd.read_csv(train_csv)\ntest_df = pd.read_csv(test_csv)\n\n# Dataset class\nclass RetinopathyDataset(Dataset):\n    def __init__(self, df, img_dir, transform=None):\n        self.df = df\n        self.img_dir = img_dir\n        self.transform = transform\n    \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        img_name = self.df.iloc[idx, 0] + \".png\"\n        img_path = os.path.join(self.img_dir, img_name)\n        image = Image.open(img_path).convert(\"RGB\")\n        \n        if self.transform:\n            image = self.transform(image)\n        \n        label = self.df.iloc[idx, 1] if \"diagnosis\" in self.df.columns else -1\n        return image, label\n\n# Data transformations\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Datasets & Dataloaders\ntrain_dataset = RetinopathyDataset(train_df, train_img_dir, transform)\ntest_dataset = RetinopathyDataset(test_df, test_img_dir, transform)\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\ntest_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)\n\n# CNN + FNN Hybrid Model\nclass HybridModel(nn.Module):\n    def __init__(self, num_classes=5):\n        super(HybridModel, self).__init__()\n        self.cnn = models.densenet121(pretrained=True)\n        self.cnn.classifier = nn.Identity()  # Remove original classifier\n        \n        self.fc = nn.Sequential(\n            nn.Linear(1024, 512),\n            nn.ReLU(),\n            nn.BatchNorm1d(512),\n            nn.Dropout(0.5),\n            nn.Linear(512, 128),\n            nn.ReLU(),\n            nn.BatchNorm1d(128),\n            nn.Dropout(0.5),\n            nn.Linear(128, num_classes)\n        )\n    \n    def forward(self, x):\n        x = self.cnn(x)\n        x = self.fc(x)\n        return x\n\n# Model, Loss & Optimizer\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = HybridModel().to(device)\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=1e-4)\n\n# Training Loop\ndef train_model(model, train_loader, criterion, optimizer, epochs=10):\n    model.train()\n    for epoch in range(epochs):\n        total_loss = 0\n        for images, labels in train_loader:\n            images, labels = images.to(device), labels.to(device)\n            optimizer.zero_grad()\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            optimizer.step()\n            total_loss += loss.item()\n        print(f\"Epoch {epoch+1}/{epochs}, Loss: {total_loss/len(train_loader):.4f}\")\n\ntrain_model(model, train_loader, criterion, optimizer, epochs=10)\n\n# Save Model\ntorch.save(model.state_dict(), \"cnn_fnn_hybrid.pth\")\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-04-02T03:28:53.544874Z","iopub.execute_input":"2025-04-02T03:28:53.545198Z","iopub.status.idle":"2025-04-02T04:42:00.166454Z","shell.execute_reply.started":"2025-04-02T03:28:53.545174Z","shell.execute_reply":"2025-04-02T04:42:00.165687Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nfrom torch.utils.data import DataLoader, Dataset\nfrom PIL import Image\nimport pandas as pd\nimport os\nfrom sklearn.metrics import accuracy_score, classification_report, confusion_matrix\n\n# Load Model\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = HybridModel().to(device)\nmodel.load_state_dict(torch.load(\"cnn_fnn_hybrid.pth\", map_location=device, weights_only=True))\nmodel.eval()\n\n# Dataset Class\nclass RetinopathyDataset(Dataset):\n    def __init__(self, df, img_dir, transform=None):\n        self.df = df\n        self.img_dir = img_dir\n        self.transform = transform\n    \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        img_name = self.df.iloc[idx, 0] + \".png\"\n        img_path = os.path.join(self.img_dir, img_name)\n        image = Image.open(img_path).convert(\"RGB\")\n\n        if self.transform:\n            image = self.transform(image)\n\n        # No labels in test set\n        return image\n\n# Transform\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Load Test Data\ntest_df = pd.read_csv(test_csv)\ntest_dataset = RetinopathyDataset(test_df, test_img_dir, transform)\ntest_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)\n\n# Prediction\npredictions = []\nmodel.eval()\nwith torch.no_grad():\n    for images in test_loader:\n        images = images.to(device)\n        outputs = model(images)\n        probs = torch.softmax(outputs, dim=1)\n        preds = torch.argmax(probs, dim=1)\n        predictions.extend(preds.cpu().numpy())\n\n# Print Results\nprint(\"Predictions:\", predictions)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-02T04:45:38.303745Z","iopub.execute_input":"2025-04-02T04:45:38.304085Z","iopub.status.idle":"2025-04-02T04:46:51.841317Z","shell.execute_reply.started":"2025-04-02T04:45:38.304059Z","shell.execute_reply":"2025-04-02T04:46:51.840627Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nfrom PIL import Image\n\n# Define the model\nclass HybridModel(nn.Module):\n    def __init__(self, num_classes=5):\n        super(HybridModel, self).__init__()\n        self.cnn = models.densenet121(pretrained=True)\n        self.cnn.classifier = nn.Identity()  # Remove original classifier\n        \n        self.fc = nn.Sequential(\n            nn.Linear(1024, 512),\n            nn.ReLU(),\n            nn.BatchNorm1d(512),\n            nn.Dropout(0.5),\n            nn.Linear(512, 128),\n            nn.ReLU(),\n            nn.BatchNorm1d(128),\n            nn.Dropout(0.5),\n            nn.Linear(128, num_classes)\n        )\n    \n    def forward(self, x):\n        x = self.cnn(x)\n        x = self.fc(x)\n        return x\n\n# Load the trained model\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = HybridModel().to(device)\nmodel.load_state_dict(torch.load(\"cnn_fnn_hybrid.pth\", map_location=device))\nmodel.eval()\n\n# Image transformation (same as used during training)\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Get user input for image path\nimage_path = input(\"Enter the path of the image: \").strip()\n\n# Load and preprocess image\ntry:\n    image = Image.open(image_path).convert(\"RGB\")\n    image = transform(image).unsqueeze(0).to(device)  # Add batch dimension\nexcept Exception as e:\n    print(f\"Error loading image: {e}\")\n    exit()\n\n# Predict\nwith torch.no_grad():\n    output = model(image)\n    predicted_class = torch.argmax(output, dim=1).item()\n\n# Severity Mapping\nseverity_mapping = {\n    0: \"No Diabetic Retinopathy\",\n    1: \"Mild\",\n    2: \"Moderate\",\n    3: \"Severe\",\n    4: \"Proliferate DR\"\n}\n\n# Output result\nprint(f\"Predicted severity: {severity_mapping.get(predicted_class, 'Unknown')}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-02T05:08:35.311337Z","iopub.execute_input":"2025-04-02T05:08:35.311632Z","iopub.status.idle":"2025-04-02T05:08:46.008095Z","shell.execute_reply.started":"2025-04-02T05:08:35.311608Z","shell.execute_reply":"2025-04-02T05:08:46.007244Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nfrom torch.utils.data import DataLoader, Dataset\nimport pandas as pd\nimport os\nfrom PIL import Image\nfrom sklearn.metrics import accuracy_score, f1_score, confusion_matrix\n\n# Paths\ndata_dir = \"/kaggle/input/aptos2019-blindness-detection\"\ntrain_csv = os.path.join(data_dir, \"train.csv\")\ntrain_img_dir = os.path.join(data_dir, \"train_images\")\n\n# Load dataset\ntrain_df = pd.read_csv(train_csv)\n\n# Dataset class\nclass RetinopathyDataset(Dataset):\n    def __init__(self, df, img_dir, transform=None):\n        self.df = df\n        self.img_dir = img_dir\n        self.transform = transform\n    \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        img_name = self.df.iloc[idx, 0] + \".png\"\n        img_path = os.path.join(self.img_dir, img_name)\n        image = Image.open(img_path).convert(\"RGB\")\n        \n        if self.transform:\n            image = self.transform(image)\n        \n        label = self.df.iloc[idx, 1]\n        return image, label\n\n# Image transformation\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Load dataset and dataloader\ndataset = RetinopathyDataset(train_df, train_img_dir, transform)\ndataloader = DataLoader(dataset, batch_size=32, shuffle=False)\n\n# Define the model\nclass HybridModel(nn.Module):\n    def __init__(self, num_classes=5):\n        super(HybridModel, self).__init__()\n        self.cnn = models.densenet121(pretrained=True)\n        self.cnn.classifier = nn.Identity()  # Remove original classifier\n        \n        self.fc = nn.Sequential(\n            nn.Linear(1024, 512),\n            nn.ReLU(),\n            nn.BatchNorm1d(512),\n            nn.Dropout(0.5),\n            nn.Linear(512, 128),\n            nn.ReLU(),\n            nn.BatchNorm1d(128),\n            nn.Dropout(0.5),\n            nn.Linear(128, num_classes)\n        )\n    \n    def forward(self, x):\n        x = self.cnn(x)\n        x = self.fc(x)\n        return x\n\n# Load trained model\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = HybridModel().to(device)\nmodel.load_state_dict(torch.load(\"cnn_fnn_hybrid.pth\", map_location=device))\nmodel.eval()\n\n# Evaluation\nall_preds = []\nall_labels = []\n\nwith torch.no_grad():\n    for images, labels in dataloader:\n        images, labels = images.to(device), labels.to(device)\n        outputs = model(images)\n        preds = torch.argmax(outputs, dim=1)\n        \n        all_preds.extend(preds.cpu().numpy())\n        all_labels.extend(labels.cpu().numpy())\n\n# Compute metrics\naccuracy = accuracy_score(all_labels, all_preds)\nf1 = f1_score(all_labels, all_preds, average=\"weighted\")\nconf_matrix = confusion_matrix(all_labels, all_preds)\n\nprint(f\"Accuracy: {accuracy:.4f}\")\nprint(f\"F1 Score: {f1:.4f}\")\nprint(\"Confusion Matrix:\")\nprint(conf_matrix)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-02T05:01:18.151006Z","iopub.execute_input":"2025-04-02T05:01:18.151316Z","iopub.status.idle":"2025-04-02T05:08:26.847221Z","shell.execute_reply.started":"2025-04-02T05:01:18.151294Z","shell.execute_reply":"2025-04-02T05:08:26.846448Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\nimport numpy as np\n\n# Plot Confusion Matrix\nplt.figure(figsize=(8, 6))\nsns.heatmap(conf_matrix, annot=True, fmt=\"d\", cmap=\"Blues\", xticklabels=[0, 1, 2, 3, 4], yticklabels=[0, 1, 2, 3, 4])\nplt.xlabel(\"Predicted Label\")\nplt.ylabel(\"True Label\")\nplt.title(\"Confusion Matrix\")\nplt.show()\n\n# Bar Plot of Class-wise Accuracy\nclass_accuracy = conf_matrix.diagonal() / conf_matrix.sum(axis=1)\nplt.figure(figsize=(8, 5))\nplt.bar(range(5), class_accuracy, color=\"skyblue\")\nplt.xlabel(\"Class\")\nplt.ylabel(\"Accuracy\")\nplt.title(\"Class-wise Accuracy\")\nplt.xticks(range(5), [\"No DR\", \"Mild\", \"Moderate\", \"Severe\", \"Proliferate_DR\"])\nplt.ylim(0, 1)\nplt.show()\n\n# Accuracy & F1 Score\nplt.figure(figsize=(6, 4))\nmetrics = [\"Accuracy\", \"F1 Score\"]\nvalues = [accuracy, f1]\nplt.bar(metrics, values, color=[\"blue\", \"orange\"])\nplt.ylim(0, 1)\nplt.title(\"Model Performance Metrics\")\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-02T05:11:48.248812Z","iopub.execute_input":"2025-04-02T05:11:48.249221Z","iopub.status.idle":"2025-04-02T05:11:49.106201Z","shell.execute_reply.started":"2025-04-02T05:11:48.249176Z","shell.execute_reply":"2025-04-02T05:11:49.105452Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nfrom PIL import Image\n\nclass HybridModel(nn.Module):\n    def __init__(self, num_classes=5):\n        super(HybridModel, self).__init__()\n        self.cnn = models.densenet121(pretrained=True)\n        self.cnn.classifier = nn.Identity()\n        self.fc = nn.Sequential(\n            nn.Linear(1024, 512),\n            nn.ReLU(),\n            nn.BatchNorm1d(512),\n            nn.Dropout(0.5),\n            nn.Linear(512, 128),\n            nn.ReLU(),\n            nn.BatchNorm1d(128),\n            nn.Dropout(0.5),\n            nn.Linear(128, num_classes)\n        )\n\n    def forward(self, x):\n        x = self.cnn(x)\n        x = self.fc(x)\n        return x\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = HybridModel().to(device)\nmodel.load_state_dict(torch.load(\"/kaggle/input/training-model/pytorch/default/1/cnn_fnn_hybrid.pth\", map_location=device))\nmodel.eval()\n\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\nimage_path = input(\"Enter the path of the image: \").strip()\n\ntry:\n    image = Image.open(image_path).convert(\"RGB\")\n    image = transform(image).unsqueeze(0).to(device)\nexcept Exception as e:\n    print(f\"Error loading image: {e}\")\n    exit()\n\nwith torch.no_grad():\n    output = model(image)\n    predicted_class = torch.argmax(output, dim=1).item()\n\nseverity_mapping = {\n    0: \"No Diabetic Retinopathy\",\n    1: \"Mild\",\n    2: \"Moderate\",\n    3: \"Severe\",\n    4: \"Proliferate DR\"\n}\n\nprint(f\"Predicted severity: {severity_mapping.get(predicted_class, 'Unknown')}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-04T05:00:28.801816Z","iopub.execute_input":"2025-04-04T05:00:28.802125Z","iopub.status.idle":"2025-04-04T05:00:34.62131Z","shell.execute_reply.started":"2025-04-04T05:00:28.802102Z","shell.execute_reply":"2025-04-04T05:00:34.620577Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport matplotlib.colors as mcolors\n\n# Define the hybrid model\nclass HybridModel(nn.Module):\n    def __init__(self, num_classes=5):\n        super(HybridModel, self).__init__()\n        self.cnn = models.densenet121(pretrained=True)\n        self.cnn.classifier = nn.Identity()\n        self.fc = nn.Sequential(\n            nn.Linear(1024, 512),\n            nn.ReLU(),\n            nn.BatchNorm1d(512),\n            nn.Dropout(0.5),\n            nn.Linear(512, 128),\n            nn.ReLU(),\n            nn.BatchNorm1d(128),\n            nn.Dropout(0.5),\n            nn.Linear(128, num_classes)\n        )\n\n    def forward(self, x):\n        x = self.cnn(x)\n        x = self.fc(x)\n        return x\n\n# Set device\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# Load the trained model\nmodel = HybridModel().to(device)\nmodel.load_state_dict(torch.load(\"/kaggle/input/training-model/pytorch/default/1/cnn_fnn_hybrid.pth\", map_location=device))\nmodel.eval()\n\n# Image transformation (same as used during training)\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Get user input for image path\nimage_path = input(\"Enter the path of the image: \").strip()\n\n# Load and preprocess image\ntry:\n    image = Image.open(image_path).convert(\"RGB\")\n    image = transform(image).unsqueeze(0).to(device)\nexcept Exception as e:\n    print(f\"Error loading image: {e}\")\n    exit()\n\n# Predict severity level\nwith torch.no_grad():\n    output = model(image)\n    predicted_class = torch.argmax(output, dim=1).item()\n\n# Severity Mapping\nseverity_mapping = {\n    0: \"No Diabetic Retinopathy\",\n    1: \"Mild\",\n    2: \"Moderate\",\n    3: \"Severe\",\n    4: \"Proliferate DR\"\n}\n\nseverity_colors = {\n    0: \"green\",\n    1: \"yellow\",\n    2: \"orange\",\n    3: \"red\",\n    4: \"darkred\"\n}\n\npredicted_label = severity_mapping.get(predicted_class, \"Unknown\")\npredicted_color = severity_colors.get(predicted_class, \"black\")\n\n# Display the image along with severity bar\nfig, ax = plt.subplots(2, 1, figsize=(6, 8))\n\n# Show original image\nimage_original = Image.open(image_path)\nax[0].imshow(image_original)\nax[0].set_title(f\"Predicted: {predicted_label}\", fontsize=14, color=predicted_color)\nax[0].axis(\"off\")\n\n# Generate severity range bar\nbar_colors = [\"green\", \"yellow\", \"orange\", \"red\", \"darkred\"]\nbar = np.zeros((1, 5, 3))\n\nfor i, c in enumerate(bar_colors):\n    bar[0, i, :] = mcolors.to_rgb(c)\n\nax[1].imshow(bar, aspect=\"auto\")\nax[1].set_xticks(range(5))\nax[1].set_xticklabels([\"No DR\", \"Mild\", \"Moderate\", \"Severe\", \"Proliferate DR\"], fontsize=12)\nax[1].set_yticks([])\nax[1].set_xlabel(\"Diabetic Retinopathy Severity\", fontsize=12)\n\n# Highlight predicted severity\nax[1].axvline(x=predicted_class, color=\"black\", linewidth=2, linestyle=\"--\")\n\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-04T05:54:48.35179Z","iopub.execute_input":"2025-04-04T05:54:48.352221Z","iopub.status.idle":"2025-04-04T05:54:51.85551Z","shell.execute_reply.started":"2025-04-04T05:54:48.352193Z","shell.execute_reply":"2025-04-04T05:54:51.854532Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nfrom PIL import Image\nimport matplotlib.pyplot as plt\n\n# Define the directory\nimage_dir = '/kaggle/input/aptos2019-blindness-detection/train_images'\n\n# Get the list of image filenames\nimage_files = [f for f in os.listdir(image_dir) if f.endswith('.png')][:20]\n\n# Plot 20 resized images with zero space between them\nfig, axes = plt.subplots(5, 4, figsize=(8, 10))  # Adjusted figsize to be more compact\n\nfor ax, file_name in zip(axes.flat, image_files):\n    img_path = os.path.join(image_dir, file_name)\n    img = Image.open(img_path).resize((224, 224))\n    \n    ax.imshow(img)\n    ax.set_title(file_name[:10], fontsize=6)\n    ax.axis('off')\n\nplt.subplots_adjust(wspace=0.4, hspace=0)\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-21T06:04:21.251042Z","iopub.execute_input":"2025-04-21T06:04:21.251377Z","iopub.status.idle":"2025-04-21T06:04:24.533332Z","shell.execute_reply.started":"2025-04-21T06:04:21.251349Z","shell.execute_reply":"2025-04-21T06:04:24.532422Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport json\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nfrom torch.utils.data import DataLoader, Dataset, random_split\nfrom PIL import Image\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\n# Paths\ndata_dir = \"/kaggle/input/aptos2019-blindness-detection\"\ntrain_csv = os.path.join(data_dir, \"train.csv\")\ntrain_img_dir = os.path.join(data_dir, \"train_images\")\n\n# Load Data\ndf = pd.read_csv(train_csv)\n\n# Dataset class\nclass RetinopathyDataset(Dataset):\n    def __init__(self, df, img_dir, transform=None):\n        self.df = df\n        self.img_dir = img_dir\n        self.transform = transform\n    \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        img_name = self.df.iloc[idx, 0] + \".png\"\n        img_path = os.path.join(self.img_dir, img_name)\n        image = Image.open(img_path).convert(\"RGB\")\n        if self.transform:\n            image = self.transform(image)\n        label = self.df.iloc[idx, 1]\n        return image, label\n\n# Transforms\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n])\n\n# Dataset & Split\ndataset = RetinopathyDataset(df, train_img_dir, transform)\ntrain_size = int(0.8 * len(dataset))\nval_size = len(dataset) - train_size\ntrain_dataset, val_dataset = random_split(dataset, [train_size, val_size])\n\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)\n\n# Model\nclass HybridModel(nn.Module):\n    def __init__(self, num_classes=5):\n        super(HybridModel, self).__init__()\n        self.cnn = models.densenet121(pretrained=True)\n        self.cnn.classifier = nn.Identity()\n        self.fc = nn.Sequential(\n            nn.Linear(1024, 512),\n            nn.ReLU(),\n            nn.BatchNorm1d(512),\n            nn.Dropout(0.5),\n            nn.Linear(512, 128),\n            nn.ReLU(),\n            nn.BatchNorm1d(128),\n            nn.Dropout(0.5),\n            nn.Linear(128, num_classes)\n        )\n\n    def forward(self, x):\n        x = self.cnn(x)\n        x = self.fc(x)\n        return x\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = HybridModel().to(device)\n\n# Loss and Optimizer\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=1e-4)\n\n# Training\nnum_epochs = 10\nhistory = {\"loss\": [], \"val_loss\": [], \"accuracy\": [], \"val_accuracy\": []}\n\nfor epoch in range(num_epochs):\n    model.train()\n    train_loss, correct, total = 0.0, 0, 0\n    for images, labels in train_loader:\n        images, labels = images.to(device), labels.to(device)\n        optimizer.zero_grad()\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        train_loss += loss.item()\n        _, preds = torch.max(outputs, 1)\n        correct += (preds == labels).sum().item()\n        total += labels.size(0)\n    train_accuracy = correct / total\n\n    model.eval()\n    val_loss, val_correct, val_total = 0.0, 0, 0\n    with torch.no_grad():\n        for images, labels in val_loader:\n            images, labels = images.to(device), labels.to(device)\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n            val_loss += loss.item()\n            _, preds = torch.max(outputs, 1)\n            val_correct += (preds == labels).sum().item()\n            val_total += labels.size(0)\n    val_accuracy = val_correct / val_total\n\n    history[\"loss\"].append(train_loss / len(train_loader))\n    history[\"val_loss\"].append(val_loss / len(val_loader))\n    history[\"accuracy\"].append(train_accuracy)\n    history[\"val_accuracy\"].append(val_accuracy)\n\n    print(f\"Epoch {epoch+1}/{num_epochs} | \"\n          f\"Train Loss: {history['loss'][-1]:.4f}, \"\n          f\"Val Loss: {history['val_loss'][-1]:.4f}, \"\n          f\"Train Acc: {train_accuracy:.4f}, \"\n          f\"Val Acc: {val_accuracy:.4f}\")\n\n# Save model & history\ntorch.save(model.state_dict(), \"cnn_fnn_hybrid.pth\")\nwith open(\"history.json\", \"w\") as f:\n    json.dump(history, f)\n\n# Plot graphs\nepochs = range(1, num_epochs + 1)\n\nplt.figure(figsize=(10, 5))\nplt.plot(epochs, history[\"loss\"], label=\"Training Loss\", marker='o')\nplt.plot(epochs, history[\"val_loss\"], label=\"Validation Loss\", marker='o')\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Loss\")\nplt.title(\"Training vs Validation Loss\")\nplt.legend()\nplt.grid(True)\nplt.show()\n\nplt.figure(figsize=(10, 5))\nplt.plot(epochs, history[\"accuracy\"], label=\"Training Accuracy\", marker='o')\nplt.plot(epochs, history[\"val_accuracy\"], label=\"Validation Accuracy\", marker='o')\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Accuracy\")\nplt.title(\"Training vs Validation Accuracy\")\nplt.legend()\nplt.grid(True)\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-22T03:06:50.827899Z","iopub.execute_input":"2025-04-22T03:06:50.82825Z","iopub.status.idle":"2025-04-22T04:20:02.227894Z","shell.execute_reply.started":"2025-04-22T03:06:50.82822Z","shell.execute_reply":"2025-04-22T04:20:02.22708Z"}},"outputs":[],"execution_count":null}]}