{"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":"gpu","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"},{"sourceId":7447509,"sourceType":"datasetVersion","datasetId":4334995}],"dockerImageVersionId":30746,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## MODEL","metadata":{}},{"cell_type":"code","source":"import torch.optim as optim\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision.transforms as transforms\nimport torch \nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport os\nfrom torch.utils.data import DataLoader, TensorDataset\n\n# Check if GPU is available\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(f\"Using device: {device}\")\n\n# Define the CNN model with Dropout layers\nclass SimpleCNN(nn.Module):\n    def __init__(self):\n        super(SimpleCNN, self).__init__()\n        self.conv1 = nn.Conv2d(in_channels=4, out_channels=16, kernel_size=3, padding=1)\n        self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, padding=1)\n        self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1)\n        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.dropout = nn.Dropout(0.5)\n        self.fc1 = nn.Linear(64 * 16 * 32, 128)\n        self.fc2 = nn.Linear(128, 6)\n\n    def forward(self, x):\n        x = self.pool(F.relu(self.conv1(x)))\n        x = self.pool(F.relu(self.conv2(x)))\n        x = self.pool(F.relu(self.conv3(x)))\n        x = x.view(x.size(0), -1)\n        x = self.dropout(F.relu(self.fc1(x)))\n        x = self.fc2(x)\n        return x\n\n# Load file with data description\nBASE_PATH = \"/kaggle/input/hms-harmful-brain-activity-classification\"\ndf = pd.read_csv(f'{BASE_PATH}/train.csv')\nSPEC_PATH = \"/kaggle/input/brain-eeg-spectrograms/EEG_Spectrograms\"\nos.chdir(SPEC_PATH)\nspec_list = os.listdir()\n\n# Initialize arrays for storing data\nSpec_array = []\nlabels = []\npatient_ids = []\n\nprint(\"spec_list size = \", len(spec_list))\n\n# Load and preprocess spectrogram files\nfor spec_nme in spec_list[0:100]:\n    spec = np.load(spec_nme)\n    eegid = int(spec_nme.split('.')[0])\n    rec = df.loc[df['eeg_id'] == eegid]\n    lab = np.unique(rec['expert_consensus'].values)\n    pid = np.unique(rec['patient_id'].values)\n    \n    if len(lab) == 1:\n        Spec_array.append(spec)\n        labels.append(lab)\n        patient_ids.append(pid)\n\n# Convert to numpy arrays\nSpec_array = np.array(Spec_array)\nlabels = np.array(labels)\n\n# Map string labels to integers\nlabel_dict = {\n    'Seizure': 1,\n    'LPD': 2,\n    'GPD': 3,\n    'LRDA': 4,\n    'GRDA': 5,\n    'Other': 0\n}\n\nlabels2 = [label_dict[l[0]] for l in labels]\nlabels = torch.tensor(labels2, dtype=torch.long)\n\n# Convert data to PyTorch tensors\nspec_data = torch.Tensor(Spec_array)\nspec_data = spec_data.permute(0, 3, 1, 2)\n\n# Calculate mean and std for normalization\nchann_mean = np.mean(Spec_array, axis=tuple(range(0, 3)))\nchann_std = np.std(Spec_array, axis=tuple(range(0, 3)))\n\n# Define normalization and data augmentation transformations\naugmentation_transforms = transforms.Compose([\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomVerticalFlip(),\n    transforms.RandomRotation(20),\n    transforms.Normalize(mean=chann_mean, std=chann_std)\n])\n\n# Apply the transformation\nspec_data = augmentation_transforms(spec_data)\n\n# Create a dataset and DataLoader\nspec_dataset = TensorDataset(spec_data, labels)\ntrain_size = int(0.8 * len(spec_dataset))\nval_size = len(spec_dataset) - train_size\ntrain_dataset, val_dataset = torch.utils.data.random_split(spec_dataset, [train_size, val_size])\ntrain_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=64, shuffle=False)\n\n# Model, loss, optimizer\nmodel = SimpleCNN().to(device)\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)\n\n# Track metrics\ntrain_loss_list = []\nval_loss_list = []\nepochs = []\n\nnum_epochs = 20  \nearly_stopping_patience = 3  # Stop after 3 epochs with no improvement\nbest_val_loss = float('inf')\npatience_counter = 0\n\nfor epoch in range(num_epochs):\n    model.train()\n    train_loss = 0.0\n    \n    for inputs, labels in train_loader:\n        inputs, labels = inputs.to(device), labels.to(device)\n        optimizer.zero_grad()\n        outputs = model(inputs)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        train_loss += loss.item() * inputs.size(0)\n    \n    train_loss = train_loss / len(train_loader.dataset)\n    train_loss_list.append(train_loss)\n\n    model.eval()\n    val_loss = 0.0\n    \n    with torch.no_grad():\n        for inputs, labels in val_loader:\n            inputs, labels = inputs.to(device), labels.to(device)\n            outputs = model(inputs)\n            loss = criterion(outputs, labels)\n            val_loss += loss.item() * inputs.size(0)\n    \n    val_loss = val_loss / len(val_loader.dataset)\n    val_loss_list.append(val_loss)\n    epochs.append(epoch + 1)\n    \n    print(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {train_loss:.4f}, Validation Loss: {val_loss:.4f}')\n\n    # Early stopping\n    if val_loss < best_val_loss:\n        best_val_loss = val_loss\n        patience_counter = 0\n    else:\n        patience_counter += 1\n        if patience_counter >= early_stopping_patience:\n            print(\"Early stopping triggered\")\n            break\n\n# Plot training and validation loss\nplt.figure(figsize=(12, 6))\nplt.subplot(1, 2, 1)\nplt.plot(epochs, train_loss_list, 'r', label='Training loss')\nplt.plot(epochs, val_loss_list, 'b', label='Validation loss')\nplt.title('Training and Validation loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-07-22T07:22:36.965162Z","iopub.execute_input":"2024-07-22T07:22:36.965481Z","iopub.status.idle":"2024-07-22T07:22:38.609404Z","shell.execute_reply.started":"2024-07-22T07:22:36.965456Z","shell.execute_reply":"2024-07-22T07:22:38.608527Z"},"trusted":true},"execution_count":null,"outputs":[]}]}