{ "cells": [ { "cell_type": "code", "execution_count": 14, "id": "f27bc33e-2451-4ef3-80e9-f3081e7db8c5", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import torch\n", "import torch.nn as nn\n", "import torch.optim as optim\n", "from torch.utils.data import DataLoader, Dataset\n", "import torchaudio\n", "import torchvision\n", "import matplotlib.pyplot as plt\n", "from preprocess import get_raw_data, get_batch_generator\n", "from datasets import load_from_disk\n", "import os\n", "import csv\n", "import torch\n", "from tqdm import tqdm" ] }, { "cell_type": "code", "execution_count": 2, "id": "f62a5ab8-0ac3-4543-9496-1c2cfca92e66", "metadata": {}, "outputs": [], "source": [ "dataset = load_from_disk(\"audio\")" ] }, { "cell_type": "code", "execution_count": 3, "id": "314a5450-4881-40c4-995a-b01fcc31e536", "metadata": {}, "outputs": [], "source": [ "SR = 12000\n", "\n", "signals_train, labels_train, sizes_train = get_raw_data(dataset[\"train\"])\n", "signals_test, labels_test, sizes_test = get_raw_data(dataset[\"test\"])\n" ] }, { "cell_type": "code", "execution_count": 4, "id": "6b0e9608-5a49-4183-9273-8f2e72e4f9a3", "metadata": {}, "outputs": [], "source": [ "# **Dataset to load audio file. Implement mixup transform**\n", "class AudioDataset(Dataset):\n", " def __init__(self, X, y, mean, std, n_mels, n_fft, hop_length, mixup=False):\n", " \n", " self.X = X\n", " self.labels = y\n", " self.sample_rate = 12000\n", " self.mel_transform = torchaudio.transforms.MelSpectrogram(\n", " sample_rate=self.sample_rate,\n", " n_fft=n_fft,\n", " hop_length=hop_length,\n", " n_mels=n_mels\n", " )\n", "\n", " self.env_idx = np.where(self.labels == 1)[0]\n", " self.mixup = mixup\n", " self.mean = mean\n", " self.std = std\n", " \n", " def __len__(self):\n", " return len(self.X)\n", " \n", " def __getitem__(self, idx):\n", " waveform = self.X[idx]\n", " if self.mixup:\n", " r = np.random.random()\n", " if r > 0.5:\n", " idx_to_add = np.random.choice(self.env_idx)\n", " to_add = self.X[idx_to_add]\n", " #r *= 2\n", " assert (r <= 1)\n", " waveform = r*waveform + (1-r)*to_add\n", "\n", " waveform = torch.as_tensor(waveform).unsqueeze(0)\n", "\n", " mel_spectrogram = self.mel_transform(waveform)\n", " mel_spectrogram = torch.log10(1+mel_spectrogram)\n", " \n", " # Normaliser le spectrogramme\n", " mel_spectrogram = (mel_spectrogram - self.mean)/self.std\n", " \n", " return mel_spectrogram, self.labels[idx]\n", "\n", "def train_model(\n", " model, \n", " dataloaders, \n", " criterion, \n", " optimizer, \n", " num_epochs, \n", " device, \n", " save_dir=\"checkpoints\", \n", " csv_file=\"validation_accuracy.csv\"\n", "):\n", " # Préparer le dossier de sauvegarde\n", " os.makedirs(save_dir, exist_ok=True)\n", "\n", " # Préparer le fichier CSV\n", " if not os.path.exists(csv_file):\n", " with open(csv_file, mode=\"w\", newline=\"\") as file:\n", " writer = csv.writer(file)\n", " writer.writerow([\"epoch\", \"val_accuracy\"]) # En-têtes du CSV\n", "\n", " model = model.to(device)\n", "\n", " for epoch in range(num_epochs):\n", " print(f\"Epoch {epoch + 1}/{num_epochs}\")\n", " print(\"-\" * 10)\n", "\n", " for phase in ['train', 'val']:\n", " if phase == 'train':\n", " model.train()\n", " else:\n", " model.eval()\n", "\n", " running_loss = 0.0\n", " running_corrects = 0\n", " \n", " for inputs, labels in dataloaders[phase]:\n", " inputs = inputs.to(device, dtype=torch.float)\n", " labels = labels.to(device, dtype=torch.float).view(-1) # Labels en 1D pour BCEWithLogitsLoss\n", "\n", " optimizer.zero_grad()\n", "\n", " with torch.set_grad_enabled(phase == 'train'):\n", " outputs = model(inputs).view(-1) # Sorties en 1D pour BCEWithLogitsLoss\n", " loss = criterion(outputs, labels) # Calcul de la perte\n", " \n", " if phase == 'train':\n", " loss.backward()\n", " optimizer.step()\n", " \n", " running_loss += loss.item() * inputs.size(0)\n", "\n", " # Calcul des prédictions binaires (sigmoid + seuil 0.5)\n", " preds = torch.sigmoid(outputs) > 0.5\n", " running_corrects += torch.sum(preds == labels.bool()) # Comparaison binaire\n", " #print(running_corrects, len(dataloaders[phase].dataset))\n", " \n", " epoch_loss = running_loss / len(dataloaders[phase].dataset)\n", " epoch_acc = running_corrects.double() / len(dataloaders[phase].dataset)\n", " \n", " print(f\"{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}\")\n", "\n", " # Sauvegarde du modèle et de l'accuracy si en phase de validation\n", " if phase == 'val':\n", " # Sauvegarder le modèle\n", " model_save_path = os.path.join(save_dir, f\"model_epoch_{epoch + 1}.pth\")\n", " torch.save(model.state_dict(), model_save_path)\n", " print(f\"Model saved to {model_save_path}\")\n", "\n", " # Écrire l'accuracy dans le fichier CSV\n", " with open(csv_file, mode=\"a\", newline=\"\") as file:\n", " writer = csv.writer(file)\n", " writer.writerow([epoch + 1, epoch_acc.item()]) # Ajouter l'epoch et l'accuracy\n", "\n", " print(\"Training complete.\")\n", " return model\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "d8d813e0-a445-4b65-b9e3-68e8bee28e8d", "metadata": {}, "outputs": [], "source": [ "X_train = signals_train\n", "X_test = signals_test\n", "y_train = labels_train\n", "y_test = labels_test" ] }, { "cell_type": "code", "execution_count": 6, "id": "c17f7b65-03cc-4eda-892e-0cfee758257c", "metadata": {}, "outputs": [], "source": [ "# Paramètres dataset\n", "\n", "SAMPLE_RATE = 12000\n", "N_FFT = 2048 \n", "HOP_LENGTH = 512 \n", "N_MELS = 100 \n", "BATCH_SIZE = 64\n", "MEAN = -24.443264\n", "STD = 8.27237\n", "\n", "\n", "MEAN = 0.17555018\n", "STD = 0.19079028\n", "MEAN=0.18522209\n", "STD=0.20916936\n", "\n", "\n", "\n", "# Créer les datasets et dataloaders\n", "train_dataset = AudioDataset(X_train,\n", " y_train,\n", " mean=MEAN,\n", " std=STD,\n", " n_mels=N_MELS,\n", " n_fft=N_FFT,\n", " hop_length=HOP_LENGTH,\n", " mixup=True)\n", "val_dataset = AudioDataset(X_test,\n", " y_test,\n", " mean=MEAN,\n", " std=STD,\n", " n_mels=N_MELS,\n", " n_fft=N_FFT,\n", " hop_length=HOP_LENGTH,\n", " mixup=False)\n", "\n", "dataloaders = {\n", " \"train\": DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=4),\n", " \"val\": DataLoader(val_dataset, batch_size=BATCH_SIZE, shuffle=False, num_workers=4)\n", "}" ] }, { "cell_type": "code", "execution_count": 21, "id": "11bbd974-9065-487c-a7db-ee6e7c66c5e5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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lfodbDvrIcXP1q1b6emnn6ZHHnnkVDel7RgdHaUPfOAD9OCDD1I+n4//wGlKFEV06aWX0ic+8QkiIrr44ovp6aefpnvuuYduuOGGU9y6E6ftntRWrVpFqVTKeSM1Pj5Ow8PDTT51enDjjTfSD37wA/rJT34inD+Hh4epUqnQ1NSU2P5067OdO3fSoUOH6LWvfS2l02lKp9P08MMP05133knpdJqGhoa0n4hozZo1dN5554m/nXvuubRv3z4iokZfvFK/g203qGWzWbrkkkto+/btjb9FUUTbt2+nzZs3n8KWnTqMMXTjjTfSt7/9bXrooYdo48aNYv0ll1xCmUxG9Nnu3btp3759p1WfvelNb6KnnnqKfvnLXzZ+Lr30Urr++usbv2s/EV155ZVOSNDvfvc7OvPMM4mIaOPGjTQ8PCz6qVQq0WOPPfbK6KdT/aZiOb75zW+aXC5nvvKVr5hdu3aZd7/73aa3t9eMjY2d6qadEt7znveYYrFofvrTn5qDBw82fubn5xvb/OM//qNZv369eeihh8wTTzxhNm/ebDZv3nwKW90e8Lefxmg/GWPM448/btLptPn4xz9u9uzZY772ta+Zjo4O8x//8R+NbT75yU+a3t5e893vftf8+te/Ntdcc43ZuHGjWVhYOIUtXxltOagZY8znPvc5s379epPNZs3ll19uHn300VPdpFMGES37c++99za2WVhYMO9973tNX1+f6ejoMH/1V39lDh48eOoa3SbgoKb9tMT3v/99c8EFF5hcLmc2bdpkvvjFL4r1URSZ2267zQwNDZlcLmfe9KY3md27d5+i1raG+qkpipIo2k5TUxRFORF0UFMUJVHooKYoSqLQQU1RlEShg5qiKIlCBzVFURKFDmqKoiQKHdQURUkUOqgpipIodFBTFCVR6KCmKEqi+P8B7u60tSVq5OsAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.imshow((val_dataset[5][0][0]))" ] }, { "cell_type": "code", "execution_count": 8, "id": "eba16b15-b762-4b65-9386-e64ad666e41e", "metadata": {}, "outputs": [], "source": [ "class ConvLayer(nn.Module):\n", " def __init__(self, in_channels, out_channels):\n", " super(ConvLayer, self).__init__()\n", " self.conv_layers = nn.Sequential(\n", " nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False),\n", " nn.BatchNorm2d(out_channels),\n", " nn.ReLU(),\n", " nn.MaxPool2d(kernel_size=2, stride=2),\n", " )\n", "\n", " def forward(self, x):\n", " x = self.conv_layers(x)\n", " return x\n", "\n", "\n", "class AudioClassifierCNN(nn.Module):\n", " def __init__(self):\n", " super(AudioClassifierCNN, self).__init__()\n", " \n", " self.conv_layers = nn.Sequential(\n", " ConvLayer(1, 16),\n", " ConvLayer(16, 32),\n", " ConvLayer(32, 64),\n", " ConvLayer(64, 128),\n", " ConvLayer(128, 256),\n", " ConvLayer(256, 256)\n", " )\n", "\n", "\n", " self.fc_layers = nn.Sequential(\n", " nn.Flatten(),\n", " nn.Linear(256, 32),\n", " nn.ReLU(),\n", " nn.Dropout(0.4),\n", " nn.Linear(32, 1)\n", " )\n", "\n", " def forward(self, x):\n", " x = self.conv_layers(x)\n", " x = self.fc_layers(x)\n", " return x.squeeze(1)" ] }, { "cell_type": "code", "execution_count": 9, "id": "37214be6-cf2a-472f-8c59-8a57d4efb7a1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor([0.4159], grad_fn=)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model = AudioClassifierCNN()\n", "a, b = train_dataset[3]\n", "model(a.unsqueeze(0))" ] }, { "cell_type": "code", "execution_count": 10, "id": "93a17a9d-203b-4c61-ba2c-63deebe6c42e", "metadata": {}, "outputs": [], "source": [ "# (To find mean and std for normalization)\n", "if 0:\n", " mean = []\n", " std = []\n", " mean_b = []\n", " std_b = []\n", " for a, b in train_dataset:\n", " mean.append(a.mean((-1,-2)))\n", " std.append(a.std((-1,-2)))\n", " print(np.mean(mean, 0))\n", " print(np.mean(std, 0))" ] }, { "cell_type": "code", "execution_count": 11, "id": "9d74c1d8-0f3d-4802-9a15-5c62464a3fcc", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/50\n", "----------\n", "train Loss: 0.2585 Acc: 0.9038\n", "val Loss: 0.2161 Acc: 0.9196\n", "Model saved to checkpoints2/model_epoch_1.pth\n", "Epoch 2/50\n", "----------\n", "train Loss: 0.2139 Acc: 0.9247\n", "val Loss: 0.1747 Acc: 0.9382\n", "Model saved to checkpoints2/model_epoch_2.pth\n", "Epoch 3/50\n", "----------\n", "train Loss: 0.1972 Acc: 0.9321\n", "val Loss: 0.1415 Acc: 0.9491\n", "Model saved to checkpoints2/model_epoch_3.pth\n", "Epoch 4/50\n", "----------\n", "train Loss: 0.1855 Acc: 0.9351\n", "val Loss: 0.1346 Acc: 0.9515\n", "Model saved to checkpoints2/model_epoch_4.pth\n", "Epoch 5/50\n", "----------\n", "train Loss: 0.1786 Acc: 0.9380\n", "val Loss: 0.1483 Acc: 0.9521\n", "Model saved to checkpoints2/model_epoch_5.pth\n", "Epoch 6/50\n", "----------\n" ] }, { "ename": "KeyboardInterrupt", "evalue": "", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[11], line 12\u001b[0m\n\u001b[1;32m 9\u001b[0m optimizer \u001b[38;5;241m=\u001b[39m optim\u001b[38;5;241m.\u001b[39mAdam(model\u001b[38;5;241m.\u001b[39mparameters(), lr\u001b[38;5;241m=\u001b[39mLEARNING_RATE)\n\u001b[1;32m 11\u001b[0m \u001b[38;5;66;03m# Entraîner le modèle\u001b[39;00m\n\u001b[0;32m---> 12\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[43mtrain_model\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdataloaders\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcriterion\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43moptimizer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnum_epochs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m50\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcuda\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msave_dir\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcheckpoints2\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcsv_file\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mvalid2.csv\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n", "Cell \u001b[0;32mIn[4], line 89\u001b[0m, in \u001b[0;36mtrain_model\u001b[0;34m(model, dataloaders, criterion, optimizer, num_epochs, device, save_dir, csv_file)\u001b[0m\n\u001b[1;32m 86\u001b[0m loss \u001b[38;5;241m=\u001b[39m criterion(outputs, labels) \u001b[38;5;66;03m# Calcul de la perte\u001b[39;00m\n\u001b[1;32m 88\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m phase \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtrain\u001b[39m\u001b[38;5;124m'\u001b[39m:\n\u001b[0;32m---> 89\u001b[0m \u001b[43mloss\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbackward\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 90\u001b[0m optimizer\u001b[38;5;241m.\u001b[39mstep()\n\u001b[1;32m 92\u001b[0m running_loss \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m loss\u001b[38;5;241m.\u001b[39mitem() \u001b[38;5;241m*\u001b[39m inputs\u001b[38;5;241m.\u001b[39msize(\u001b[38;5;241m0\u001b[39m)\n", "File \u001b[0;32m~/.local/share/virtualenvs/kangourou-v5SGOwnr/lib/python3.11/site-packages/torch/_tensor.py:626\u001b[0m, in \u001b[0;36mTensor.backward\u001b[0;34m(self, gradient, retain_graph, create_graph, inputs)\u001b[0m\n\u001b[1;32m 616\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m has_torch_function_unary(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 617\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m handle_torch_function(\n\u001b[1;32m 618\u001b[0m Tensor\u001b[38;5;241m.\u001b[39mbackward,\n\u001b[1;32m 619\u001b[0m (\u001b[38;5;28mself\u001b[39m,),\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 624\u001b[0m inputs\u001b[38;5;241m=\u001b[39minputs,\n\u001b[1;32m 625\u001b[0m )\n\u001b[0;32m--> 626\u001b[0m \u001b[43mtorch\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mautograd\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mbackward\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 627\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgradient\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mretain_graph\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcreate_graph\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43minputs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minputs\u001b[49m\n\u001b[1;32m 628\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/.local/share/virtualenvs/kangourou-v5SGOwnr/lib/python3.11/site-packages/torch/autograd/__init__.py:347\u001b[0m, in \u001b[0;36mbackward\u001b[0;34m(tensors, grad_tensors, retain_graph, create_graph, grad_variables, inputs)\u001b[0m\n\u001b[1;32m 342\u001b[0m retain_graph \u001b[38;5;241m=\u001b[39m create_graph\n\u001b[1;32m 344\u001b[0m \u001b[38;5;66;03m# The reason we repeat the same comment below is that\u001b[39;00m\n\u001b[1;32m 345\u001b[0m \u001b[38;5;66;03m# some Python versions print out the first line of a multi-line function\u001b[39;00m\n\u001b[1;32m 346\u001b[0m \u001b[38;5;66;03m# calls in the traceback and some print out the last line\u001b[39;00m\n\u001b[0;32m--> 347\u001b[0m \u001b[43m_engine_run_backward\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 348\u001b[0m \u001b[43m \u001b[49m\u001b[43mtensors\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 349\u001b[0m \u001b[43m \u001b[49m\u001b[43mgrad_tensors_\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 350\u001b[0m \u001b[43m \u001b[49m\u001b[43mretain_graph\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 351\u001b[0m \u001b[43m \u001b[49m\u001b[43mcreate_graph\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 352\u001b[0m \u001b[43m \u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 353\u001b[0m \u001b[43m \u001b[49m\u001b[43mallow_unreachable\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 354\u001b[0m \u001b[43m \u001b[49m\u001b[43maccumulate_grad\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 355\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/.local/share/virtualenvs/kangourou-v5SGOwnr/lib/python3.11/site-packages/torch/autograd/graph.py:823\u001b[0m, in \u001b[0;36m_engine_run_backward\u001b[0;34m(t_outputs, *args, **kwargs)\u001b[0m\n\u001b[1;32m 821\u001b[0m unregister_hooks \u001b[38;5;241m=\u001b[39m _register_logging_hooks_on_whole_graph(t_outputs)\n\u001b[1;32m 822\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 823\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mVariable\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_execution_engine\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun_backward\u001b[49m\u001b[43m(\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# Calls into the C++ engine to run the backward pass\u001b[39;49;00m\n\u001b[1;32m 824\u001b[0m \u001b[43m \u001b[49m\u001b[43mt_outputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\n\u001b[1;32m 825\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# Calls into the C++ engine to run the backward pass\u001b[39;00m\n\u001b[1;32m 826\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 827\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m attach_logging_hooks:\n", "\u001b[0;31mKeyboardInterrupt\u001b[0m: " ] } ], "source": [ "# Paramètre apprentissage\n", "EPOCHS = 20\n", "LEARNING_RATE = 0.001\n", "\n", "# Initialiser le modèle, la loss, et l'optimiseur\n", "num_classes = 2 # Ajustez selon vos besoins\n", "model = AudioClassifierCNN()\n", "criterion = nn.BCEWithLogitsLoss()\n", "optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE)\n", "\n", "# Entraîner le modèle\n", "model = train_model(model, dataloaders, criterion, optimizer, num_epochs=50, device=\"cuda\", save_dir=\"checkpoints2\", csv_file=\"valid2.csv\")\n" ] }, { "cell_type": "code", "execution_count": 12, "id": "7e854804-ae5e-46e1-88fb-53f5acfd9429", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[codecarbon WARNING @ 01:53:44] Multiple instances of codecarbon are allowed to run at the same time.\n", "[codecarbon INFO @ 01:53:44] [setup] RAM Tracking...\n", "[codecarbon INFO @ 01:53:44] [setup] CPU Tracking...\n", "[codecarbon WARNING @ 01:53:44] No CPU tracking mode found. Falling back on CPU constant mode. \n", " Linux OS detected: Please ensure RAPL files exist at \\sys\\class\\powercap\\intel-rapl to measure CPU\n", "\n", "[codecarbon INFO @ 01:53:45] CPU Model on constant consumption mode: AMD Ryzen 9 5900X 12-Core Processor\n", "[codecarbon INFO @ 01:53:45] [setup] GPU Tracking...\n", "[codecarbon INFO @ 01:53:45] Tracking Nvidia GPU via pynvml\n", "[codecarbon INFO @ 01:53:45] >>> Tracker's metadata:\n", "[codecarbon INFO @ 01:53:45] Platform system: Linux-6.1.0-26-amd64-x86_64-with-glibc2.36\n", "[codecarbon INFO @ 01:53:45] Python version: 3.11.2\n", "[codecarbon INFO @ 01:53:45] CodeCarbon version: 2.8.3\n", "[codecarbon INFO @ 01:53:45] Available RAM : 31.259 GB\n", "[codecarbon INFO @ 01:53:45] CPU count: 24\n", "[codecarbon INFO @ 01:53:45] CPU model: AMD Ryzen 9 5900X 12-Core Processor\n", "[codecarbon INFO @ 01:53:45] GPU count: 1\n", "[codecarbon INFO @ 01:53:45] GPU model: 1 x NVIDIA GeForce RTX 3080\n", "[codecarbon INFO @ 01:53:49] Saving emissions data to file /home/kangourou/frugal/emissions.csv\n" ] } ], "source": [ "from codecarbon import EmissionsTracker\n", "tracker = EmissionsTracker(allow_multiple_runs=True)" ] }, { "cell_type": "code", "execution_count": 19, "id": "f23a1000-90e0-4777-825f-38d270128ae7", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[codecarbon WARNING @ 01:55:10] Already started tracking\n", "100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 119/119 [00:00<00:00, 173.09it/s]\n", "[codecarbon INFO @ 01:55:10] Energy consumed for RAM : 0.000160 kWh. RAM Power : 11.722217559814453 W\n", "[codecarbon INFO @ 01:55:10] Energy consumed for all CPUs : 0.000717 kWh. Total CPU Power : 52.5 W\n", "[codecarbon INFO @ 01:55:10] Energy consumed for all GPUs : 0.001315 kWh. Total GPU Power : 238.54231240370862 W\n", "[codecarbon INFO @ 01:55:10] 0.002192 kWh of electricity used since the beginning.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "0.05850168950330892\n" ] } ], "source": [ "mel_transform = torchaudio.transforms.MelSpectrogram(\n", " sample_rate=SAMPLE_RATE,\n", " n_fft=2048,\n", " hop_length=512,\n", " n_mels=100\n", ").cuda()\n", "X_train\n", "model.cuda()\n", "preds = []\n", "\n", "tracker.start()\n", "tracker.start_task(\"inference\")\n", "with torch.inference_mode():\n", " bs=128\n", " for i in tqdm(range(0, X_test.shape[0], bs)):\n", " batch = X_test[i:i+bs]\n", " mel = mel_transform(torch.as_tensor(batch).cuda())\n", " mel = torch.log10(1+mel)\n", " #mel_spectrogram = mel_spectrogram[:,:50]\n", " #mfcc = self.mfcc_transform(waveform).mean(-1).squeeze(0)\n", " \n", "\n", " # Normaliser le spectrogramme\n", " mel = (mel - MEAN)/STD\n", " mel = mel.unsqueeze(1)\n", " #pred = np.argmax(model(mel).cpu().numpy(), -1)\n", " pred = torch.sigmoid(model(mel)).cpu().numpy()\n", " preds.append(pred)\n", "preds = np.concatenate(preds)\n", "\n", "emissions_data = tracker.stop_task()\n", "print(emissions_data.energy_consumed * 1000)" ] }, { "cell_type": "code", "execution_count": 20, "id": "bc710afc-392d-4591-b129-07d3419f8696", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "np.float64(0.9478174603174603)" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "((preds>0.5)==labels_test).sum()/preds.size" ] }, { "cell_type": "code", "execution_count": null, "id": "d6f3d8e7-3315-4f78-b7a4-789d75eb1eac", "metadata": {}, "outputs": [], "source": [ "np.save(\"preds_nn.npy\", preds)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.11.2" } }, "nbformat": 4, "nbformat_minor": 5 }