{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":39272,"databundleVersionId":4629629,"sourceType":"competition"},{"sourceId":4619402,"sourceType":"datasetVersion","datasetId":2688773}],"dockerImageVersionId":30747,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport os\nfrom PIL import Image\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-08-05T11:09:43.720774Z","iopub.execute_input":"2024-08-05T11:09:43.72114Z","iopub.status.idle":"2024-08-05T11:09:43.726641Z","shell.execute_reply.started":"2024-08-05T11:09:43.721111Z","shell.execute_reply":"2024-08-05T11:09:43.725738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the path to the folder containing images\nimage_directory = '/kaggle/input/rsna-breast-cancer-256-pngs'\n\n# List all files in the directory\nall_files = os.listdir(image_directory)\n\n# Filter out only the PNG files\nimage_files = [file for file in all_files if file.endswith('.png')]\n\n# Count the number of images\nnum_images = len(image_files)\n\nprint(f\"Total number of images: {num_images}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:09:47.700494Z","iopub.execute_input":"2024-08-05T11:09:47.701493Z","iopub.status.idle":"2024-08-05T11:09:47.743805Z","shell.execute_reply.started":"2024-08-05T11:09:47.701459Z","shell.execute_reply":"2024-08-05T11:09:47.742862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\n# Path to the CSV file and image directory\ncsv_file = '/kaggle/input/rsna-breast-cancer-detection/train.csv'\nimage_directory = '/kaggle/input/rsna-breast-cancer-256-pngs'\n\n# Read the CSV file into a DataFrame\ndf = pd.read_csv(csv_file)\n\n# List all PNG files in the image directory\nimage_files = [file for file in os.listdir(image_directory) if file.endswith('.png')]\n\n# Extract patient IDs from the filenames (assuming format: patientID_image.png)\nimage_patient_ids = [file.split('_')[0] for file in image_files]\n\n# Check if all patient IDs in the CSV exist in the image directory\ncsv_patient_ids = df['patient_id'].astype(str).tolist()\nmissing_ids = [patient_id for patient_id in csv_patient_ids if patient_id not in image_patient_ids]\n\nif missing_ids:\n    print(f\"Missing patient IDs: {missing_ids}\")\nelse:\n    print(\"All patient IDs in the CSV exist in the image directory.\")\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:09:50.408873Z","iopub.execute_input":"2024-08-05T11:09:50.409285Z","iopub.status.idle":"2024-08-05T11:10:02.991655Z","shell.execute_reply.started":"2024-08-05T11:09:50.409254Z","shell.execute_reply":"2024-08-05T11:10:02.990633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# Get the patient ID from the first row of the CSV\nfirst_patient_id = str(df.iloc[0]['patient_id'])\n\n# Find the corresponding image file\nfirst_image_filename = [file for file in image_files if file.startswith(first_patient_id)][0]\n\n# Open the image file\nimage_path = os.path.join(image_directory, first_image_filename)\nimg = Image.open(image_path)\n\n# Display the image dimensions\nprint(f\"First image for patient ID {first_patient_id}: {first_image_filename}, Dimensions: {img.size}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:02.993576Z","iopub.execute_input":"2024-08-05T11:10:02.993892Z","iopub.status.idle":"2024-08-05T11:10:03.01027Z","shell.execute_reply.started":"2024-08-05T11:10:02.993865Z","shell.execute_reply":"2024-08-05T11:10:03.009239Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Path to the CSV file\ncsv_file = '/kaggle/input/rsna-breast-cancer-detection/train.csv'\n\n# Read the CSV file into a DataFrame\ndf = pd.read_csv(csv_file)\n\n# Display the first few rows of the DataFrame\nprint(df.head())\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:03.011634Z","iopub.execute_input":"2024-08-05T11:10:03.011989Z","iopub.status.idle":"2024-08-05T11:10:03.098975Z","shell.execute_reply.started":"2024-08-05T11:10:03.011962Z","shell.execute_reply":"2024-08-05T11:10:03.098011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Columns to keep for density classification\ncolumns_to_keep = ['patient_id', 'image_id', 'density', 'age', 'laterality', 'view', 'BIRADS', 'difficult_negative_case', 'implant']\n\n# Create a new DataFrame with only the selected columns\ndf_selected = df[columns_to_keep]\n\n# Display the selected columns\ndf_selected.head()\n\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:03.101299Z","iopub.execute_input":"2024-08-05T11:10:03.101606Z","iopub.status.idle":"2024-08-05T11:10:03.120912Z","shell.execute_reply.started":"2024-08-05T11:10:03.101581Z","shell.execute_reply":"2024-08-05T11:10:03.119728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Discard rows where the 'density' column has NaN values\ndf_selected_cleaned = df_selected.dropna(subset=['density'])\n\n# Discard rows where the 'implant' column is set to 1\ndf_selected_cleaned = df_selected_cleaned[df_selected_cleaned['implant'] != 1]\n\n# Display the cleaned DataFrame\nprint(df_selected_cleaned.head())\nprint(f\"Total entries after cleaning: {len(df_selected_cleaned)}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:03.122347Z","iopub.execute_input":"2024-08-05T11:10:03.122714Z","iopub.status.idle":"2024-08-05T11:10:03.145956Z","shell.execute_reply.started":"2024-08-05T11:10:03.122667Z","shell.execute_reply":"2024-08-05T11:10:03.144955Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Function to visualize random images\ndef visualize_random_images(df, image_dir, num_images=5):\n    # Select random samples\n    random_samples = df.sample(num_images)\n    \n    plt.figure(figsize=(15, 10))\n    \n    for i, row in random_samples.iterrows():\n        patient_id = row['patient_id']\n        image_id = row['image_id']\n        image_filename = f\"{patient_id}_{image_id}.png\"\n        image_path = os.path.join(image_dir, image_filename)\n        \n        # Open and display the image\n        img = Image.open(image_path)\n        \n        plt.subplot(1, num_images, random_samples.index.get_loc(i) + 1)\n        plt.imshow(img, cmap='gray')\n        plt.title(f\"ID: {patient_id}_{image_id}\\nDensity: {row['density']}\")\n        plt.axis('off')\n    \n    plt.tight_layout()\n    plt.show()\n\n# Visualize random images\nvisualize_random_images(df_selected_cleaned, image_directory)","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:03.147206Z","iopub.execute_input":"2024-08-05T11:10:03.147499Z","iopub.status.idle":"2024-08-05T11:10:03.810477Z","shell.execute_reply.started":"2024-08-05T11:10:03.147475Z","shell.execute_reply":"2024-08-05T11:10:03.809586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Count the occurrences of each density category\ndensity_counts = df_selected_cleaned['density'].value_counts()\n\n# Display the counts\nprint(\"Number of images in each density category:\")\nprint(density_counts)\n\n# Visualize the results using a bar plot\nimport matplotlib.pyplot as plt\n\nplt.figure(figsize=(8, 5))\ndensity_counts.plot(kind='bar', title='Number of Images in Each Density Category', ylabel='Number of Images', xlabel='Density Category')\nplt.xticks(rotation=0)\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:03.811852Z","iopub.execute_input":"2024-08-05T11:10:03.812219Z","iopub.status.idle":"2024-08-05T11:10:04.093175Z","shell.execute_reply.started":"2024-08-05T11:10:03.812185Z","shell.execute_reply":"2024-08-05T11:10:04.092262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder\n\n# Initialize the LabelEncoder\nlabel_encoder = LabelEncoder()\n\n# Fit the LabelEncoder on the 'density' column and transform the labels to integers\ndf_selected_cleaned['density'] = label_encoder.fit_transform(df_selected_cleaned['density'])\n\n# Verify the encoding\nprint(df_selected_cleaned['density'].head())\n\n# Display the mapping of labels to integers\nlabel_mapping = dict(zip(label_encoder.classes_, label_encoder.transform(label_encoder.classes_)))\nprint(\"Label Mapping:\", label_mapping)\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:04.094366Z","iopub.execute_input":"2024-08-05T11:10:04.094661Z","iopub.status.idle":"2024-08-05T11:10:04.109081Z","shell.execute_reply.started":"2024-08-05T11:10:04.094636Z","shell.execute_reply":"2024-08-05T11:10:04.108004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nfrom sklearn.model_selection import train_test_split\n\n# Assuming you have a DataFrame `df_selected_cleaned` with your data\n\n# Define the stratify column (e.g., 'density')\nstratify_col = df_selected_cleaned['density']\n\n# Split the dataset into training, validation, and test sets using stratified sampling\ntrain_df, test_df = train_test_split(df_selected_cleaned, test_size=0.2, stratify=stratify_col, random_state=42)\ntrain_df, val_df = train_test_split(train_df, test_size=0.25, stratify=train_df['density'], random_state=42)  # 0.25 * 0.8 = 0.2\n\n\"\"\"\n60% for the training set (75% of 80%).\n20% for the validation set (25% of 80%).\n20% for the test set (from the initial split).\n\"\"\"\n# Verify the splits\nprint(f\"Training set size: {len(train_df)}\")\nprint(f\"Validation set size: {len(val_df)}\")\nprint(f\"Test set size: {len(test_df)}\")\n\n# Display class distribution in each split\nprint(\"Class distribution in Training set:\")\nprint(train_df['density'].value_counts())\nprint(\"Class distribution in Validation set:\")\nprint(val_df['density'].value_counts())\nprint(\"Class distribution in Test set:\")\nprint(test_df['density'].value_counts())\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:04.110502Z","iopub.execute_input":"2024-08-05T11:10:04.110903Z","iopub.status.idle":"2024-08-05T11:10:04.152723Z","shell.execute_reply.started":"2024-08-05T11:10:04.110868Z","shell.execute_reply":"2024-08-05T11:10:04.151728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import time\nfrom datetime import timedelta\nfrom tqdm import tqdm\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torchvision import models\nfrom torch.utils.data import Dataset, DataLoader\nimport cv2\nimport numpy as np\nimport os\nfrom albumentations.pytorch import ToTensorV2\nimport albumentations as A","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:25.695111Z","iopub.execute_input":"2024-08-05T11:10:25.695472Z","iopub.status.idle":"2024-08-05T11:10:25.701346Z","shell.execute_reply.started":"2024-08-05T11:10:25.695446Z","shell.execute_reply":"2024-08-05T11:10:25.700237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nfrom PIL import Image\nimport cv2\nimport torch\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision.transforms as transforms\nimport matplotlib.pyplot as plt\n\n'''\n# Define the transformations for training and validation\ntrain_transform = transforms.Compose([\n    transforms.Resize((256, 256)),\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomRotation(15),\n    transforms.ColorJitter(brightness=0.2, contrast=0.2),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n'''\n\n# Define the transformations for training\ntrain_transform = transforms.Compose([\n    transforms.Resize((256, 256)),                # Resize the image to 256x256 (assuming you want this)\n    transforms.RandomRotation(30),                # Random rotation within 30 degrees\n    transforms.RandomAffine(\n        degrees=0,                                # No additional rotation since it's handled separately\n        translate=(0.2, 0.2),                     # Width and height shift within 20%\n        shear=0.2,                                # Shear within 20%\n        scale=(0.8, 1.2)                          # Zoom in and out within 80% to 120%\n    ),\n    transforms.RandomHorizontalFlip(),            # Random horizontal flip\n    transforms.ToTensor(),                        # Convert the image to a PyTorch tensor\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # Normalize\n])\n\n\n\nval_test_transform = transforms.Compose([\n    transforms.Resize((256, 256)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Define the custom dataset\nclass BreastCancerDataset(Dataset):\n    def __init__(self, dataframe, image_dir, transform=None):\n        self.dataframe = dataframe\n        self.image_dir = image_dir\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.dataframe)\n\n    def __getitem__(self, idx):\n        row = self.dataframe.iloc[idx]\n        patient_id = int(row['patient_id'])\n        image_id = int(row['image_id'])\n        img_name = os.path.join(self.image_dir, f\"{patient_id}_{image_id}.png\")\n        image = Image.open(img_name).convert('RGB')\n        \n        label = row['density']\n        \n        if self.transform:\n            image = self.transform(image)\n\n        return image, label\n\n# Create the datasets\nimage_directory = '/kaggle/input/rsna-breast-cancer-256-pngs'\n\ntrain_dataset = BreastCancerDataset(train_df, image_directory, transform=train_transform)\nval_dataset = BreastCancerDataset(val_df, image_directory, transform=val_test_transform)\ntest_dataset = BreastCancerDataset(test_df, image_directory, transform=val_test_transform)\n\n# Create the data loaders\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)\ntest_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:26.122581Z","iopub.execute_input":"2024-08-05T11:10:26.12302Z","iopub.status.idle":"2024-08-05T11:10:26.138538Z","shell.execute_reply.started":"2024-08-05T11:10:26.12299Z","shell.execute_reply":"2024-08-05T11:10:26.137586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torchvision\n\n# Function to visualize a batch of images\ndef imshow(img, title=None):\n    npimg = img.numpy().transpose((1, 2, 0))\n    plt.imshow(npimg)\n    if title is not None:\n        plt.title(title)\n    plt.show()\n\n# Function to visualize a batch of images from a DataLoader\ndef visualize_batch(dataloader, title, num_images=8):\n    # Get a batch of data\n    images, labels = next(iter(dataloader))\n    \n    # Select only the first num_images\n    images = images[:num_images]\n    labels = labels[:num_images]\n    \n    # Make a grid from batch with padding\n    out = torchvision.utils.make_grid(images, nrow=num_images, padding=2)\n    imshow(out, title=title)\n\n# Visualize a batch from the training DataLoader\nprint(\"Training DataLoader\")\nvisualize_batch(train_loader, \"Training Data\")\n\n# Visualize a batch from the validation DataLoader\nprint(\"Validation DataLoader\")\nvisualize_batch(val_loader, \"Validation Data\")\n\n# Visualize a batch from the test DataLoader\nprint(\"Test DataLoader\")\nvisualize_batch(test_loader, \"Test Data\")\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:27.172566Z","iopub.execute_input":"2024-08-05T11:10:27.173255Z","iopub.status.idle":"2024-08-05T11:10:28.328296Z","shell.execute_reply.started":"2024-08-05T11:10:27.173224Z","shell.execute_reply":"2024-08-05T11:10:28.327133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check a batch of data from the train loader\nfor images, labels in train_loader:\n    print(f\"Train Loader - Images shape: {images.shape}\")\n    print(f\"Train Loader - Labels shape: {labels.shape}\")\n    break  # Only need to check one batch\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:28.330575Z","iopub.execute_input":"2024-08-05T11:10:28.331316Z","iopub.status.idle":"2024-08-05T11:10:28.555941Z","shell.execute_reply.started":"2024-08-05T11:10:28.331276Z","shell.execute_reply":"2024-08-05T11:10:28.554974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check a batch of data from the train loader\nfor images, labels in val_loader:\n    print(f\"Train Loader - Images shape: {images.shape}\")\n    print(f\"Train Loader - Labels shape: {labels.shape}\")\n    break  # Only need to check one batch\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:28.557121Z","iopub.execute_input":"2024-08-05T11:10:28.557469Z","iopub.status.idle":"2024-08-05T11:10:28.643178Z","shell.execute_reply.started":"2024-08-05T11:10:28.557443Z","shell.execute_reply":"2024-08-05T11:10:28.642182Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DenseNet121","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torchvision import models\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision.transforms as transforms\nfrom PIL import Image\nimport os\nimport time\nfrom tqdm import tqdm\nfrom datetime import timedelta","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:34.236565Z","iopub.execute_input":"2024-08-05T11:10:34.236971Z","iopub.status.idle":"2024-08-05T11:10:34.242715Z","shell.execute_reply.started":"2024-08-05T11:10:34.236944Z","shell.execute_reply":"2024-08-05T11:10:34.241625Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Initialize the DenseNet-121 model\nclass CustomDenseNet121(nn.Module):\n    def __init__(self, num_classes=4):\n        super(CustomDenseNet121, self).__init__()\n        self.densenet = models.densenet121(pretrained=True)\n        self.densenet.classifier = nn.Linear(self.densenet.classifier.in_features, num_classes)\n        \n    def forward(self, x):\n        x = self.densenet(x)\n        return x\n\nnum_classes = len(train_df['density'].unique())  # Adjust based on your dataset\nmodel = CustomDenseNet121(num_classes=num_classes)\n\n# Wrap the model with DataParallel for multi-GPU training\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = nn.DataParallel(model)\nmodel = model.to(device)\n\n# Define loss function and optimizer\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=0.001)","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:34.244846Z","iopub.execute_input":"2024-08-05T11:10:34.24529Z","iopub.status.idle":"2024-08-05T11:10:34.723997Z","shell.execute_reply.started":"2024-08-05T11:10:34.245254Z","shell.execute_reply":"2024-08-05T11:10:34.72291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Early Stopping\nclass EarlyStopping:\n    def __init__(self, patience=10, min_delta=0):\n        self.patience = patience\n        self.min_delta = min_delta\n        self.counter = 0\n        self.best_loss = None\n        self.early_stop = False\n\n    def check_early_stop(self, val_loss):\n        if self.best_loss is None:\n            self.best_loss = val_loss\n        elif val_loss > self.best_loss - self.min_delta:\n            self.counter += 1\n            if self.counter >= self.patience:\n                self.early_stop = True\n        else:\n            self.best_loss = val_loss\n            self.counter = 0\n\n# Reduce Learning Rate on Plateau\nclass ReduceLROnPlateau:\n    def __init__(self, optimizer, factor=0.1, patience=5, min_lr=1e-6):\n        self.optimizer = optimizer\n        self.factor = factor\n        self.patience = patience\n        self.min_lr = min_lr\n        self.counter = 0\n        self.best_loss = None\n\n    def step(self, val_loss):\n        if self.best_loss is None:\n            self.best_loss = val_loss\n        elif val_loss > self.best_loss:\n            self.counter += 1\n            if self.counter >= self.patience:\n                self._reduce_lr()\n                self.counter = 0\n        else:\n            self.best_loss = val_loss\n            self.counter = 0\n\n    def _reduce_lr(self):\n        for param_group in self.optimizer.param_groups:\n            new_lr = max(param_group['lr'] * self.factor, self.min_lr)\n            param_group['lr'] = new_lr\n            print(f'Reduced learning rate to {new_lr}')\n\n# Model Checkpointing\ndef save_checkpoint(model, epoch, val_loss, best_loss, path=\"model_checkpoint.pth\"):\n    if val_loss < best_loss:\n        print(f'Saving model with val_loss {val_loss:.4f} at epoch {epoch+1}')\n        torch.save(model.state_dict(), path)\n        best_loss = val_loss\n    return best_loss\n\n# Initialize early stopping and learning rate scheduler\nearly_stopping = EarlyStopping(patience=10, min_delta=0.001)\nlr_scheduler = ReduceLROnPlateau(optimizer, factor=0.2, patience=5, min_lr=1e-6)\nbest_loss = float('inf')","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:36.517647Z","iopub.execute_input":"2024-08-05T11:10:36.518067Z","iopub.status.idle":"2024-08-05T11:10:36.534836Z","shell.execute_reply.started":"2024-08-05T11:10:36.518038Z","shell.execute_reply":"2024-08-05T11:10:36.533893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Track history\ntrain_losses = []\nval_losses = []\ntrain_accuracies = []\nval_accuracies = []\n\n# Record the start time\nstart_time = time.time()\n\n# Training loop\nnum_epochs = 50\nfor epoch in range(num_epochs):\n    epoch_start_time = time.time()  # Start time for the epoch\n    \n    model.train()  # Set the model to training mode\n    running_loss = 0.0\n    corrects_train = 0\n    total_train = 0\n    progress_bar = tqdm(train_loader, desc=f'Epoch {epoch+1}/{num_epochs}')\n    for inputs, labels in progress_bar:\n        inputs, labels = inputs.to(device), labels.to(device).long()  # Convert labels to int64\n\n        optimizer.zero_grad()  # Zero the parameter gradients\n        outputs = model(inputs)  # Forward pass\n        loss = criterion(outputs, labels)  # Calculate loss\n        loss.backward()  # Backward pass\n        optimizer.step()  # Optimize the model parameters\n\n        running_loss += loss.item() * inputs.size(0)\n\n        _, preds = torch.max(outputs, 1)\n        corrects_train += torch.sum(preds == labels.data)\n        total_train += labels.size(0)\n        \n        progress_bar.set_postfix(loss=loss.item())\n\n    epoch_loss = running_loss / len(train_loader.dataset)\n    train_acc = corrects_train.double() / total_train\n    train_losses.append(epoch_loss)\n    train_accuracies.append(train_acc.item())\n    print(f'Epoch {epoch+1}/{num_epochs}, Training Loss: {epoch_loss:.4f}, Training Accuracy: {train_acc:.4f}')\n\n    model.eval()  # Set the model to evaluation mode\n    val_loss = 0.0\n    corrects_val = 0\n    with torch.no_grad():\n        for inputs, labels in val_loader:\n            inputs, labels = inputs.to(device), labels.to(device).long()  # Convert labels to int64\n            outputs = model(inputs)\n            loss = criterion(outputs, labels)\n            val_loss += loss.item() * inputs.size(0)\n            _, preds = torch.max(outputs, 1)\n            corrects_val += torch.sum(preds == labels.data)\n\n    val_loss = val_loss / len(val_loader.dataset)\n    val_losses.append(val_loss)\n    val_acc = corrects_val.double() / len(val_loader.dataset)\n    val_accuracies.append(val_acc.item())\n    print(f'Validation Loss: {val_loss:.4f}, Validation Accuracy: {val_acc:.4f}')\n\n    # Check for early stopping\n    early_stopping.check_early_stop(val_loss)\n    if early_stopping.early_stop:\n        print(\"Early stopping\")\n        break\n\n    # Step learning rate scheduler\n    lr_scheduler.step(val_loss)\n\n    # Save model checkpoint\n    best_loss = save_checkpoint(model, epoch, val_loss, best_loss)\n    \n    epoch_end_time = time.time()  # End time for the epoch\n    epoch_duration = epoch_end_time - epoch_start_time\n    print(f'Time taken for epoch {epoch+1}: {epoch_duration:.2f} seconds')\n\n# Calculate total training time\nend_time = time.time()\nelapsed_time = end_time - start_time\nformatted_time = str(timedelta(seconds=int(elapsed_time)))\nprint(f'Training time: {formatted_time}')\n\n# Save the final model\ntorch.save(model.state_dict(), 'densenet121_mammogram_final.pth')\nprint(\"Model saved as densenet121_mammogram_final.pth\")\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:10:39.390987Z","iopub.execute_input":"2024-08-05T11:10:39.391318Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torchvision.models as models\nimport torch.nn as nn\n\n# Define the custom VGG16 model\nclass CustomVGG16(nn.Module):\n    def __init__(self, num_classes=4):\n        super(CustomVGG16, self).__init__()\n        self.vgg = models.vgg16(pretrained=True)\n        self.vgg.classifier[6] = nn.Linear(self.vgg.classifier[6].in_features, num_classes)\n        \n    def forward(self, x):\n        x = self.vgg(x)\n        return x\n\n# Instantiate the model\nnum_classes = 4  # Replace with the actual number of classes in your dataset\nmodel = CustomVGG16(num_classes=num_classes)\n\n# Calculate the number of parameters\ntotal_params = sum(p.numel() for p in model.parameters())\ntrainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)\nnon_trainable_params = total_params - trainable_params\n\nprint(f\"Total parameters: {total_params}\")\nprint(f\"Trainable parameters: {trainable_params}\")\nprint(f\"Non-trainable parameters: {non_trainable_params}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-08-05T11:09:40.29118Z","iopub.status.idle":"2024-08-05T11:09:40.291542Z","shell.execute_reply.started":"2024-08-05T11:09:40.291369Z","shell.execute_reply":"2024-08-05T11:09:40.291384Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}