{"metadata":{"kernelspec":{"display_name":"Python 3","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.14"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":71549,"databundleVersionId":8561470,"sourceType":"competition"},{"sourceId":10120999,"sourceType":"datasetVersion","datasetId":6245116},{"sourceId":10130135,"sourceType":"datasetVersion","datasetId":6251775}],"dockerImageVersionId":30805,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true},"papermill":{"default_parameters":{},"duration":669.129184,"end_time":"2024-12-06T17:00:48.57936","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2024-12-06T16:49:39.450176","version":"2.6.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import seaborn as sns\n\nimport matplotlib.pyplot as plt\nimport os\nimport time\nimport numpy as np\nimport glob\nimport json\nimport collections\n\nimport torch\nimport torch.nn as nn\n\nimport matplotlib.patches as patches\nfrom matplotlib import animation, rc\nimport pandas as pd\n\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut","metadata":{"execution":{"iopub.status.busy":"2024-12-14T22:47:04.779250Z","iopub.execute_input":"2024-12-14T22:47:04.779623Z","iopub.status.idle":"2024-12-14T22:47:04.784882Z","shell.execute_reply.started":"2024-12-14T22:47:04.779591Z","shell.execute_reply":"2024-12-14T22:47:04.783980Z"},"papermill":{"duration":6.0633,"end_time":"2024-12-06T16:49:48.170007","exception":false,"start_time":"2024-12-06T16:49:42.106707","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Preprocessing","metadata":{"papermill":{"duration":0.026635,"end_time":"2024-12-06T16:51:03.686283","exception":false,"start_time":"2024-12-06T16:51:03.659648","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# read data\nPATH = '/kaggle/input/rsna-2024-lumbar-spine-degenerative-classification/'\n\ntrain              = pd.read_csv(PATH + 'train.csv')\ntrain_label_coord  = pd.read_csv(PATH + 'train_label_coordinates.csv')\ntrain_series_desc  = pd.read_csv(PATH + 'train_series_descriptions.csv')\n\n# define our filters\ncondition =  \"Spinal Canal Stenosis\"\ncondition_fmt = \"_\".join(condition.lower().split())\n\nlevel = \"L5/S1\"\nlevel_fmt = level.lower().replace(\"/\", \"_\")\n\ncolumn = f\"{condition_fmt}_{level_fmt}\"\n\n# we keep only one level and one condition on train.csv\ntrain_filt = train.drop(columns=[c for c in train.columns if c not in [\"study_id\", column]])\n\n# merge between train.csv and train_label_coordinates.csv on key \"study_id\"\ntrain_label_coord_filt  = train_label_coord.loc[(train_label_coord[\"level\"] == level) & (train_label_coord[\"condition\"] == condition)]\n\ndf = pd.merge(train_filt, train_label_coord_filt, on=\"study_id\").set_index([\"study_id\", \"series_id\"])[[column, \"instance_number\"]]\ndf[column] = df[column].map({\n    'Normal/Mild': 0,\n    'Moderate': 1,\n    'Severe': 2\n})\n\ndf[\"image_path\"] = (\n    PATH +\n    \"train_images/\" +\n    df.index.get_level_values(\"study_id\").astype(str) + \"/\" +\n    df.index.get_level_values(\"series_id\").astype(str) + \"/\" +\n    df[\"instance_number\"].astype(str) + \".dcm\"\n)\n\nvalues = df[column].value_counts()\nprint(values)\n\ndf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-14T22:47:04.830370Z","iopub.execute_input":"2024-12-14T22:47:04.831047Z","iopub.status.idle":"2024-12-14T22:47:04.929404Z","shell.execute_reply.started":"2024-12-14T22:47:04.831017Z","shell.execute_reply":"2024-12-14T22:47:04.928384Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Dataset","metadata":{}},{"cell_type":"code","source":"# Function to open and display DICOM images\ndef display_dicom_images(image_path, name):\n    plt.figure(figsize=(15, 5))  # Adjust figure size if needed\n    ds = pydicom.dcmread(image_path)\n    plt.imshow(ds.pixel_array, cmap=plt.cm.bone)\n    plt.title(f\"Image {name}\")\n    plt.axis('off')\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-14T22:47:04.931144Z","iopub.execute_input":"2024-12-14T22:47:04.931792Z","iopub.status.idle":"2024-12-14T22:47:04.936200Z","shell.execute_reply.started":"2024-12-14T22:47:04.931752Z","shell.execute_reply":"2024-12-14T22:47:04.935351Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.utils import resample\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom sklearn.model_selection import train_test_split\n\ndef undersample_dataframe(df, label_column, target_counts):\n    \"\"\"\n    Undersample the dataset based on the given target class distribution.\n    \n    Args:\n        df (pd.DataFrame): The input dataframe.\n        label_column (str): The name of the column containing the labels.\n        target_counts (dict): The target number of samples for each class.\n    \n    Returns:\n        pd.DataFrame: The undersampled dataframe.\n    \"\"\"\n    dfs = []\n    for label, group in df.groupby(label_column):\n        if label in target_counts:\n            # Undersample or keep all samples based on target_counts\n            n_samples = target_counts[label]\n            if len(group) > n_samples:\n                group = resample(group, replace=False, n_samples=n_samples, random_state=40)\n        dfs.append(group)\n    \n    return pd.concat(dfs)\n\ndef create_loaders(df, transform, batch_size=8, target_counts=None):\n    \"\"\"\n    Create datasets and data loaders with undersampling applied to the training set.\n    \n    Args:\n        df (pd.DataFrame): The input dataframe.\n        transform (torchvision.transforms.Compose): The transformations to apply to the images.\n        batch_size (int): Batch size for DataLoader.\n        target_counts (dict): Target class distribution for undersampling in training set.\n    \n    Returns:\n        tuple: trainloader, valloader\n    \"\"\"    \n    # Apply undersampling to the training set\n    if target_counts:\n        df = undersample_dataframe(df, label_column='spinal_canal_stenosis_l5_s1', target_counts=target_counts)\n\n     # Splitting the study_ids\n    X = df.sort_values(by=\"study_id\").index.get_level_values(\"study_id\").tolist()\n    y = df.sort_values(by=\"study_id\")['spinal_canal_stenosis_l5_s1'].tolist()\n\n    train_study_ids, val_study_ids, _, _ = train_test_split(X, y, test_size=0.3, stratify=y)\n\n     # Create train and val DataFrames\n    train_df = df.loc[df.index.get_level_values(\"study_id\").isin(train_study_ids)]\n    val_df = df.loc[df.index.get_level_values(\"study_id\").isin(val_study_ids)]\n\n    print(\"Train Distribution:\")\n    print(train_df['spinal_canal_stenosis_l5_s1'].value_counts())\n    print()\n    print(\"Eval Distribution:\")\n    print(val_df['spinal_canal_stenosis_l5_s1'].value_counts())\n    \n    # Create datasets and data loaders\n    train_dataset = CustomDataset(train_df, transform)\n    val_dataset = CustomDataset(val_df, transform)\n\n    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, drop_last=False)\n    val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False, drop_last=False)\n    \n    return train_loader, val_loader\n\n# Define the target class distribution\ntarget_counts = {\n    0: 285,  # Undersample class 0 to 150\n    1: 51,    # Keep all samples of class 1\n    2: 19     # Keep all samples of class 2\n}\n\n# Create loaders with undersampling\ntrain_loader, val_loader = create_loaders(\n    df, \n    transform, \n    batch_size=32, \n    target_counts=target_counts\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-14T22:48:06.333418Z","iopub.execute_input":"2024-12-14T22:48:06.334069Z","iopub.status.idle":"2024-12-14T22:48:07.777836Z","shell.execute_reply.started":"2024-12-14T22:48:06.334004Z","shell.execute_reply":"2024-12-14T22:48:07.776910Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nfrom sklearn.model_selection import train_test_split\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision.transforms as transforms\nimport torch\nimport torch.optim.lr_scheduler as lr_scheduler\nfrom tqdm import tqdm","metadata":{"papermill":{"duration":1.893489,"end_time":"2024-12-06T16:51:21.210613","exception":false,"start_time":"2024-12-06T16:51:19.317124","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2024-12-14T22:47:05.016921Z","iopub.execute_input":"2024-12-14T22:47:05.017149Z","iopub.status.idle":"2024-12-14T22:47:05.021165Z","shell.execute_reply.started":"2024-12-14T22:47:05.017126Z","shell.execute_reply":"2024-12-14T22:47:05.020336Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# class CustomDataset(Dataset):\n#     def __init__(self, dataframe, transform=None):\n#         self.dataframe = dataframe\n#         self.transform = transform\n\n#     def __len__(self):\n#         return len(self.dataframe)\n\n#     def __getitem__(self, index):\n#         print('oooo')\n#         image_path = self.dataframe['image_path'][index]\n#         dicom_file = pydicom.dcmread(image_path)  # Load the DICOM file\n#         image = dicom_file.pixel_array  # Extract the pixel array (image data)\n#         label = self.dataframe['spinal_canal_stenosis_l5_s1'][index]\n\n#         # Check for NaN labels\n#         if pd.isnull(label):\n#             raise ValueError(f\"Invalid label at index {index}. Label: {label}\")\n        \n#         if self.transform:\n#             image = self.transform(image)\n\n#         return image, label\n\n\n\n# def create_datasets_and_loaders(df, series_description, transform, batch_size=8):\n#     # Filtra il DataFrame per la descrizione della serie\n#     filtered_df = df[(df['series_description'] == series_description)]\n    \n#     # Divisione del DataFrame in train e validation\n#     train_df, val_df = train_test_split(filtered_df, test_size=0.2, random_state=42)\n#     train_df = train_df.reset_index(drop=True)\n#     val_df = val_df.reset_index(drop=True)\n\n#     # Separazione di X (immagini) e y (etichette) per debugging o analisi\n#     #X_train = train_df['image_path'].tolist()\n#     X_train = [transform(Image.open(path)) for path in train_df['image_path']]\n#     y_train = train_df['spinal_canal_stenosis_l5_s1'].tolist()\n\n#     #X_val = val_df['image_path'].tolistt()\n#     X_val = [transform(Image.open(path)) for path in val_df['image_path']]\n#     y_val = val_df['spinal_canal_stenosis_l5_s1'].tolist()\n\n#     # Creazione dei dataset PyTorch\n#     train_dataset = CustomDataset(train_df, transform)\n#     val_dataset = CustomDataset(val_df, transform)\n\n#     # Creazione dei DataLoader\n#     trainloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, drop_last=True)\n#     valloader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False, drop_last=True)\n    \n#     # Ritorna DataLoader e i dati separati\n#     return trainloader, valloader, len(train_df), len(val_df), X_train, y_train, X_val, y_val\n\n\n\n# # Define the transforms\n# transform = transforms.Compose([\n#     transforms.Resize((224, 224)),  # Ridimensiona l'immagine\n#     transforms.Grayscale(num_output_channels=3),  # Converte a 3 canali in scala di grigi\n#     transforms.ToTensor(),  # Converte l'immagine PIL in un tensore PyTorch\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # Normalizzazione\n# ])\n\n# # dataset for model1\n# trainloader_t1, valloader_t1, len_train_t1, len_val_t1, X_train_t1, y_train_t1, X_val_t1, y_val_t1 = create_datasets_and_loaders(result, 'Sagittal T1', transform)\n# # dataset for model2\n# trainloader_t2, valloader_t2, len_train_t2, len_val_t2, X_train_t2, y_train_t2, X_val_t2, y_val_t2 = create_datasets_and_loaders(result, 'Axial T2', transform)\n# # dataset for model3\n# trainloader_t2stir, valloader_t2stir, len_train_t2stir, len_val_t2stir, X_train_t2stir, y_train_t2stir, X_val_t2stir, y_val_t2stir = create_datasets_and_loaders(result, 'Sagittal T2/STIR', transform)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-14T22:47:05.068775Z","iopub.execute_input":"2024-12-14T22:47:05.069041Z","iopub.status.idle":"2024-12-14T22:47:05.074486Z","shell.execute_reply.started":"2024-12-14T22:47:05.069017Z","shell.execute_reply":"2024-12-14T22:47:05.073528Z"},"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import pandas as pd\n# from PIL import Image\n# from sklearn.model_selection import train_test_split\n# import tensorflow as tf\n# from tensorflow.keras.applications import EfficientNetB0, EfficientNetB1, EfficientNetB2\n# from tensorflow.keras import layers, models\n\n# # Caricamento della tabella\n# data = result\n\n# # Creazione dei dataset per ciascun tipo di immagine\n# datasets = {}\n# for series in data['series_description'].unique():\n#     print(series)\n#     datasets[series] = data[data['series_description'] == series]\n\n# # Mappatura delle etichette\n# label_mapping = {\n#     'Normal/Mild': 0,\n#     'Moderate': 1,\n#     'Severe': 2\n# }\n\n# # Preprocessing delle immagini\n# def preprocess_image(image_path, target_size=(224, 224)):\n#     \"\"\"Carica e preprocessa un'immagine.\"\"\"\n#     img = Image.open(image_path).convert('RGB')\n#     img = img.resize(target_size)  # Ridimensiona l'immagine\n#     img_array = tf.keras.preprocessing.image.img_to_array(img)\n#     img_array = tf.keras.applications.efficientnet.preprocess_input(img_array)  # Normalizza per EfficientNet\n#     return img_array\n\n# # Creazione del dataset preprocessato\n# def create_dataset(data_subset, target_size=(224, 224)):\n#     \"\"\"Crea dataset di immagini e le relative etichette.\"\"\"\n#     images = []\n#     labels = []\n#     for _, row in data_subset.iterrows():\n#         img_path = row['image_path']\n#         label = row['spinal_canal_stenosis_l5_s1']  # Assumendo che ci sia una colonna 'label' con valori categorici\n#         label = label_mapping[label]  # Converte la stringa in intero\n#         images.append(preprocess_image(img_path, target_size))\n#         labels.append(label)\n#     return tf.convert_to_tensor(images), tf.keras.utils.to_categorical(labels, num_classes=3)  # 3 classi: normal, medium, severe\n\n# # Creazione dei dataset per ogni serie_descriptions\n# data_splits = {}\n# for series, subset in datasets.items():\n#     images, labels = create_dataset(subset)\n#     print(\"Primo dataset creato\")\n#     X_train, X_test, y_train, y_test = train_test_split(images, labels, test_size=0.2, random_state=42)\n#     print(\"Primo dataset splittato\")\n#     data_splits[series] = (X_train, X_test, y_train, y_test)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-14T22:47:05.076177Z","iopub.execute_input":"2024-12-14T22:47:05.076453Z","iopub.status.idle":"2024-12-14T22:47:05.086035Z","shell.execute_reply.started":"2024-12-14T22:47:05.076406Z","shell.execute_reply":"2024-12-14T22:47:05.085193Z"},"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# # SABATOOOOOOOOOOOOOOOOOOOOOOOOOO\n# import os\n# import pandas as pd\n# from PIL import Image\n# from sklearn.model_selection import train_test_split\n# import torch\n# from torch.utils.data import Dataset, DataLoader\n# import torch.nn as nn\n# import torchvision.transforms as transforms\n# import torchvision.models as models\n\n# # Caricamento della tabella\n# data = result\n\n# # Mappatura delle etichette\n# label_mapping = {\n#     'Normal/Mild': 0,\n#     'Moderate': 1,\n#     'Severe': 2\n# }\n\n# # Creazione del dataset personalizzato\n# class CustomDataset(Dataset):\n#     def __init__(self, dataframe, transform=None):\n#         self.dataframe = dataframe\n#         self.transform = transform\n\n#     def __len__(self):\n#         return len(self.dataframe)\n\n#     def __getitem__(self, idx):\n#         img_path = self.dataframe.iloc[idx]['image_path']\n#         label_str = self.dataframe.iloc[idx]['spinal_canal_stenosis_l5_s1']\n#         label = label_mapping[label_str]  # Converte la stringa in intero\n\n#         # Caricamento e trasformazione dell'immagine\n#         image = Image.open(img_path).convert('RGB')\n#         if self.transform:\n#             image = self.transform(image)\n\n#         return image, label\n\n# # Trasformazioni per le immagini\n# transform = 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# # Creazione dei dataset per ciascun tipo di immagine\n# data_splits = {}\n# for series in data['series_description'].unique():\n#     subset = data[data['series_description'] == series]\n#     train_df, test_df = train_test_split(subset, test_size=0.2, random_state=42)\n\n#     train_dataset = CustomDataset(train_df, transform=transform)\n#     test_dataset = CustomDataset(test_df, transform=transform)\n\n#     train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=4)\n#     test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False, num_workers=4)\n\n#     data_splits[series] = (train_loader, test_loader)\n\n# print(data_splits)\n# print('dataset!')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-14T22:47:05.096515Z","iopub.execute_input":"2024-12-14T22:47:05.096763Z","iopub.status.idle":"2024-12-14T22:47:05.101528Z","shell.execute_reply.started":"2024-12-14T22:47:05.096740Z","shell.execute_reply":"2024-12-14T22:47:05.100682Z"},"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_model(model, train_loader, test_loader, device, lr=0.01, l2=0.3, epochs=5):\n    model.to(device)\n    criterion = nn.CrossEntropyLoss()\n    optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=l2)\n\n    # Per tracciare i dati\n    history = {\n        \"train_loss\": [],\n        \"test_loss\": [],\n        \"train_accuracy\": [],\n        \"test_accuracy\": [],\n        \"test_auc_roc\": []\n    }\n\n    for epoch in range(epochs):\n        # Training\n        model.train()\n\n        train_total_loss = 0\n                \n        train_n_correct = 0\n        train_n_total = 0\n        for images, labels in train_loader:\n            images, labels = images.to(device), labels.to(device)\n\n            optimizer.zero_grad()\n            outputs = model(images)\n            \n            loss = criterion(outputs, labels)\n            loss.backward()\n            \n            optimizer.step()\n\n            train_total_loss += loss.item()\n            _, pred = torch.max(outputs, dim=1)\n            \n            train_n_total += labels.size(0)\n            train_n_correct += (pred == labels).sum().item()\n\n        train_loss = train_total_loss / train_n_total\n        train_acc = 100 * (train_n_correct / train_n_total)\n\n        # Validation\n        model.eval()\n        \n        test_total_loss = 0\n        \n        test_n_correct = 0\n        test_n_total = 0\n        \n        test_labels = []\n        test_probs = []\n        test_preds = []\n\n        with torch.no_grad():\n            for images, labels in test_loader:\n                images, labels = images.to(device), labels.to(device)\n                outputs = model(images)\n                \n                loss = criterion(outputs, labels)\n                test_total_loss += loss.item()\n\n                # Per calcolare l'accuracy\n                _, pred = torch.max(outputs, 1)\n                \n                test_n_total += labels.size(0)\n                test_n_correct += (pred == labels).sum().item()\n\n                p = torch.softmax(outputs, dim=1)\n                \n                test_probs += p.cpu().tolist()\n                test_labels += labels.cpu().tolist()\n                test_preds += pred.cpu().tolist()\n\n        test_loss = test_total_loss / test_n_total\n        test_acc = 100 * (test_n_correct / test_n_total)\n\n        # Calcola AUC-ROC in modalità multi-classe usando \"ovr\" (One-vs-Rest)\n        test_auc_roc = 100 * roc_auc_score(test_labels, test_probs, multi_class='ovr', average='macro')\n\n        # Salva i valori nelle liste\n        history[\"train_loss\"].append(train_loss)\n        history[\"test_loss\"].append(test_loss)\n        history[\"train_accuracy\"].append(train_acc)\n        history[\"test_accuracy\"].append(test_acc)\n        history[\"test_auc_roc\"].append(test_auc_roc)\n\n        # Stampa i progressi\n        print(f\"Epoch [{epoch + 1}/{epochs}]\")\n        print(f\"  Train Loss: {train_loss:.4f}, Train Accuracy: {train_acc:.2f}%\")\n        print(f\"  Test Loss: {test_loss:.4f}, Test Accuracy: {test_acc:.2f}%, Test ROC-AUC: {test_auc_roc:.2f}%\")\n\n    # Ritorna la cronologia per i grafici\n    return history","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-14T22:55:56.681313Z","iopub.execute_input":"2024-12-14T22:55:56.681690Z","iopub.status.idle":"2024-12-14T22:55:56.693739Z","shell.execute_reply.started":"2024-12-14T22:55:56.681658Z","shell.execute_reply":"2024-12-14T22:55:56.692779Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torchvision.models import efficientnet_b0, EfficientNet_B0_Weights\nfrom torchvision.models import resnet18, ResNet18_Weights\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(\"Device:\", device)\n\nmodel = efficientnet_b0(weights=EfficientNet_B0_Weights.DEFAULT)\nmodel.classifier = nn.Sequential(\n        nn.Linear(model.classifier[1].in_features, 3)\n    )\n\nhistory = train_model(model=model, train_loader=train_loader, test_loader=val_loader, device=device, lr=0.005, epochs=3)","metadata":{"execution":{"iopub.status.busy":"2024-12-14T22:57:14.889452Z","iopub.execute_input":"2024-12-14T22:57:14.889774Z","iopub.status.idle":"2024-12-14T22:58:53.809811Z","shell.execute_reply.started":"2024-12-14T22:57:14.889747Z","shell.execute_reply":"2024-12-14T22:58:53.808808Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"def plot_training_history(history, title=\"Ensemble Model Training History\"):\n    epochs = range(1, len(history[\"train_accuracy\"]) + 1)\n\n    # Accuracy\n    plt.figure(figsize=(12, 4))\n    plt.subplot(1, 3, 1)\n    plt.plot(epochs, history[\"train_accuracy\"], label=\"Train Accuracy\")\n    plt.plot(epochs, history[\"test_accuracy\"], label=\"Validation Accuracy\")\n    plt.xlabel(\"Epochs\")\n    plt.ylabel(\"Accuracy\")\n    plt.title(\"Accuracy\")\n    plt.legend()\n\n    # Loss (combined plot for train and test loss)\n    plt.subplot(1, 3, 2)\n    plt.plot(epochs, history[\"train_loss\"], label=\"Train Loss\", color=\"blue\")\n    plt.plot(epochs, history[\"test_loss\"], label=\"Test Loss\", color=\"red\")\n    plt.xlabel(\"Epochs\")\n    plt.ylabel(\"Loss\")\n    plt.title(\"Loss\")\n    plt.legend()\n\n    # AUC-ROC\n    plt.subplot(1, 3, 3)\n    plt.plot(epochs, history[\"test_auc_roc\"], label=\"Validation AUC-ROC\")\n    plt.xlabel(\"Epochs\")\n    plt.ylabel(\"AUC-ROC\")\n    plt.title(\"AUC-ROC\")\n    plt.legend()\n\n    plt.tight_layout()\n    plt.suptitle(title, y=1.02, fontsize=16)\n    plt.show()\n\n\nplot_training_history(history, title=\"Training History\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-14T22:56:22.495322Z","iopub.execute_input":"2024-12-14T22:56:22.496011Z","iopub.status.idle":"2024-12-14T22:56:23.193228Z","shell.execute_reply.started":"2024-12-14T22:56:22.495979Z","shell.execute_reply":"2024-12-14T22:56:23.192399Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# saving the models !!!!\nimport os\nimport re\nimport torch\n\n# Crea la directory principale\nsave_dir = '/kaggle/working/models/'\nos.makedirs(save_dir, exist_ok=True)\n\n# Salva ogni modello\nfor series, model in models.items():\n    # Rimuove caratteri non validi dai nomi della serie\n    safe_series = re.sub(r'[^a-zA-Z0-9_\\-]', '_', series)\n    save_path = os.path.join(save_dir, f'model_{safe_series}.pth')\n    \n    # Salva il modello\n    torch.save(model.state_dict(), save_path)\n    print(f\"Modello salvato in: {save_path}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-14T22:47:09.406436Z","iopub.status.idle":"2024-12-14T22:47:09.406799Z","shell.execute_reply.started":"2024-12-14T22:47:09.406649Z","shell.execute_reply":"2024-12-14T22:47:09.406666Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# ENSAMBLE PART ! :D","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport torch\nimport matplotlib.pyplot as plt\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.metrics import accuracy_score, roc_auc_score, roc_curve, log_loss\nfrom sklearn.model_selection import train_test_split\n\ndef extract_representations(models, data_splits, device):\n\n    models = {name: model.to(device) for name, model in models.items()}\n    \n    for name, model in models.items():\n        model.eval()  # Imposta i modelli in modalità di valutazione\n        print(f\"Modello {name}.\")\n\n    features = []\n    labels = []\n\n    with torch.no_grad():\n        for series_name, (train_loader, _) in data_splits.items():\n            print(f\"Elaborazione del dataset: {series_name}\")\n            total_batches = len(train_loader)\n            batch_count = 0\n\n            # Itera sui DataLoader per ciascun tipo di immagine\n            for images, batch_labels in train_loader:\n                batch_count += 1\n\n                images = images.to(device)\n                batch_labels = batch_labels.to(device)\n\n                # Estrai le rappresentazioni dai modelli\n                batch_features = []\n                for model_name, model in models.items():\n                    if model_name == series_name:  # Se il modello corrisponde al tipo di immagine\n                        outputs = model(images)  # Passa le immagini nel modello\n                        batch_features.append(outputs.cpu().numpy())  # Salva le rappresentazioni del batch\n\n                # Concatena le rappresentazioni\n                if batch_features:\n                    combined_features = np.hstack(batch_features)\n                    features.append(combined_features)\n                    labels.extend(batch_labels.cpu().numpy())\n\n    return np.vstack(features), np.array(labels)\n\nfrom sklearn.metrics import roc_auc_score\n\ndef evaluate_ensemble_model(features, labels, test_size=0.2):\n\n    # Suddividi il dataset in training e validation set\n    X_train, X_val, y_train, y_val = train_test_split(features, labels, test_size=test_size, random_state=42)\n\n    clf = LogisticRegression(max_iter=1000, random_state=42)\n\n    # Addestramento del modello\n    clf.fit(X_train, y_train)\n    \n    print(\"Addestramento completato.\")\n    \n    # Predizioni sui dati di training e di validazione\n    train_predictions = clf.predict(X_train)\n    val_predictions = clf.predict(X_val)\n    \n    # Calcolo delle metriche\n    train_accuracy = accuracy_score(y_train, train_predictions)\n    val_accuracy = accuracy_score(y_val, val_predictions)\n    \n    # Calcolo AUC-ROC\n    val_auc_roc = roc_auc_score(y_val, clf.predict_proba(X_val), multi_class='ovr')  # Usa la probabilità di tutte le classi\n\n    # Calcolo della Log Loss\n    train_loss = log_loss(y_train, clf.predict_proba(X_train))\n    val_loss = log_loss(y_val, clf.predict_proba(X_val))\n    \n    # Aggiungi ai dati di storia\n    history = {\n        \"train_accuracy\": [train_accuracy],\n        \"test_accuracy\": [val_accuracy],\n        \"train_loss\": [train_loss],\n        \"test_loss\": [val_loss],\n        \"test_auc_roc\": [val_auc_roc]\n    }\n    \n    print(f\"Training Accuracy: {train_accuracy:.4f}\")\n    print(f\"Validation Accuracy: {val_accuracy:.4f}\")\n    print(f\"Validation AUC-ROC: {val_auc_roc:.4f}\")\n    \n    return clf, history\n\ndef plot_training_history(history, title=\"Ensemble Model Training History\"):\n    epochs = range(1, len(history[\"train_accuracy\"]) + 1)\n\n    # Accuracy\n    plt.figure(figsize=(12, 4))\n    plt.subplot(1, 3, 1)\n    plt.plot(epochs, history[\"train_accuracy\"], label=\"Train Accuracy\")\n    plt.plot(epochs, history[\"test_accuracy\"], label=\"Validation Accuracy\")\n    plt.xlabel(\"Epochs\")\n    plt.ylabel(\"Accuracy\")\n    plt.title(\"Accuracy\")\n    plt.legend()\n\n    # Loss (combined plot for train and test loss)\n    plt.subplot(1, 3, 2)\n    plt.plot(epochs, history[\"train_loss\"], label=\"Train Loss\", color=\"blue\")\n    plt.plot(epochs, history[\"test_loss\"], label=\"Test Loss\", color=\"red\")\n    plt.xlabel(\"Epochs\")\n    plt.ylabel(\"Loss\")\n    plt.title(\"Loss\")\n    plt.legend()\n\n    # AUC-ROC\n    plt.subplot(1, 3, 3)\n    plt.plot(epochs, history[\"test_auc_roc\"], label=\"Validation AUC-ROC\")\n    plt.xlabel(\"Epochs\")\n    plt.ylabel(\"AUC-ROC\")\n    plt.title(\"AUC-ROC\")\n    plt.legend()\n\n    plt.tight_layout()\n    plt.suptitle(title, y=1.02, fontsize=16)\n    plt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-14T22:47:09.407934Z","iopub.status.idle":"2024-12-14T22:47:09.408230Z","shell.execute_reply.started":"2024-12-14T22:47:09.408089Z","shell.execute_reply":"2024-12-14T22:47:09.408104Z"},"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Esegui l'estrazione delle caratteristiche\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(device)\ntrain_features, train_labels = extract_representations(models, data_splits, device)\n\n# Addestramento del modello ensemble\nclf, history = evaluate_ensemble_model(train_features, train_labels)\n\n# Grafici per il modello ensemble\nplot_training_history(history, title=\"Ensemble Model Training History\")","metadata":{"execution":{"iopub.status.busy":"2024-12-14T22:47:09.409602Z","iopub.status.idle":"2024-12-14T22:47:09.409901Z","shell.execute_reply.started":"2024-12-14T22:47:09.409759Z","shell.execute_reply":"2024-12-14T22:47:09.409775Z"},"papermill":{"duration":0.067271,"end_time":"2024-12-06T16:51:21.309851","exception":false,"start_time":"2024-12-06T16:51:21.24258","status":"completed"},"tags":[],"trusted":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null}]}