Spaces:
Runtime error
Runtime error
Upload 2 files
Browse files- notebooks/CNN_training.ipynb +582 -0
- notebooks/XGBoost_train.ipynb +365 -0
notebooks/CNN_training.ipynb
ADDED
|
@@ -0,0 +1,582 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "code",
|
| 5 |
+
"execution_count": 14,
|
| 6 |
+
"id": "f27bc33e-2451-4ef3-80e9-f3081e7db8c5",
|
| 7 |
+
"metadata": {},
|
| 8 |
+
"outputs": [],
|
| 9 |
+
"source": [
|
| 10 |
+
"import numpy as np\n",
|
| 11 |
+
"import torch\n",
|
| 12 |
+
"import torch.nn as nn\n",
|
| 13 |
+
"import torch.optim as optim\n",
|
| 14 |
+
"from torch.utils.data import DataLoader, Dataset\n",
|
| 15 |
+
"import torchaudio\n",
|
| 16 |
+
"import torchvision\n",
|
| 17 |
+
"import matplotlib.pyplot as plt\n",
|
| 18 |
+
"from preprocess import get_raw_data, get_batch_generator\n",
|
| 19 |
+
"from datasets import load_from_disk\n",
|
| 20 |
+
"import os\n",
|
| 21 |
+
"import csv\n",
|
| 22 |
+
"import torch\n",
|
| 23 |
+
"from tqdm import tqdm"
|
| 24 |
+
]
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
"cell_type": "code",
|
| 28 |
+
"execution_count": 2,
|
| 29 |
+
"id": "f62a5ab8-0ac3-4543-9496-1c2cfca92e66",
|
| 30 |
+
"metadata": {},
|
| 31 |
+
"outputs": [],
|
| 32 |
+
"source": [
|
| 33 |
+
"dataset = load_from_disk(\"audio\")"
|
| 34 |
+
]
|
| 35 |
+
},
|
| 36 |
+
{
|
| 37 |
+
"cell_type": "code",
|
| 38 |
+
"execution_count": 3,
|
| 39 |
+
"id": "314a5450-4881-40c4-995a-b01fcc31e536",
|
| 40 |
+
"metadata": {},
|
| 41 |
+
"outputs": [],
|
| 42 |
+
"source": [
|
| 43 |
+
"SR = 12000\n",
|
| 44 |
+
"\n",
|
| 45 |
+
"signals_train, labels_train, sizes_train = get_raw_data(dataset[\"train\"])\n",
|
| 46 |
+
"signals_test, labels_test, sizes_test = get_raw_data(dataset[\"test\"])\n"
|
| 47 |
+
]
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
"cell_type": "code",
|
| 51 |
+
"execution_count": 4,
|
| 52 |
+
"id": "6b0e9608-5a49-4183-9273-8f2e72e4f9a3",
|
| 53 |
+
"metadata": {},
|
| 54 |
+
"outputs": [],
|
| 55 |
+
"source": [
|
| 56 |
+
"# **Dataset to load audio file. Implement mixup transform**\n",
|
| 57 |
+
"class AudioDataset(Dataset):\n",
|
| 58 |
+
" def __init__(self, X, y, mean, std, n_mels, n_fft, hop_length, mixup=False):\n",
|
| 59 |
+
" \n",
|
| 60 |
+
" self.X = X\n",
|
| 61 |
+
" self.labels = y\n",
|
| 62 |
+
" self.sample_rate = 12000\n",
|
| 63 |
+
" self.mel_transform = torchaudio.transforms.MelSpectrogram(\n",
|
| 64 |
+
" sample_rate=self.sample_rate,\n",
|
| 65 |
+
" n_fft=n_fft,\n",
|
| 66 |
+
" hop_length=hop_length,\n",
|
| 67 |
+
" n_mels=n_mels\n",
|
| 68 |
+
" )\n",
|
| 69 |
+
"\n",
|
| 70 |
+
" self.env_idx = np.where(self.labels == 1)[0]\n",
|
| 71 |
+
" self.mixup = mixup\n",
|
| 72 |
+
" self.mean = mean\n",
|
| 73 |
+
" self.std = std\n",
|
| 74 |
+
" \n",
|
| 75 |
+
" def __len__(self):\n",
|
| 76 |
+
" return len(self.X)\n",
|
| 77 |
+
" \n",
|
| 78 |
+
" def __getitem__(self, idx):\n",
|
| 79 |
+
" waveform = self.X[idx]\n",
|
| 80 |
+
" if self.mixup:\n",
|
| 81 |
+
" r = np.random.random()\n",
|
| 82 |
+
" if r > 0.5:\n",
|
| 83 |
+
" idx_to_add = np.random.choice(self.env_idx)\n",
|
| 84 |
+
" to_add = self.X[idx_to_add]\n",
|
| 85 |
+
" #r *= 2\n",
|
| 86 |
+
" assert (r <= 1)\n",
|
| 87 |
+
" waveform = r*waveform + (1-r)*to_add\n",
|
| 88 |
+
"\n",
|
| 89 |
+
" waveform = torch.as_tensor(waveform).unsqueeze(0)\n",
|
| 90 |
+
"\n",
|
| 91 |
+
" mel_spectrogram = self.mel_transform(waveform)\n",
|
| 92 |
+
" mel_spectrogram = torch.log10(1+mel_spectrogram)\n",
|
| 93 |
+
" \n",
|
| 94 |
+
" # Normaliser le spectrogramme\n",
|
| 95 |
+
" mel_spectrogram = (mel_spectrogram - self.mean)/self.std\n",
|
| 96 |
+
" \n",
|
| 97 |
+
" return mel_spectrogram, self.labels[idx]\n",
|
| 98 |
+
"\n",
|
| 99 |
+
"def train_model(\n",
|
| 100 |
+
" model, \n",
|
| 101 |
+
" dataloaders, \n",
|
| 102 |
+
" criterion, \n",
|
| 103 |
+
" optimizer, \n",
|
| 104 |
+
" num_epochs, \n",
|
| 105 |
+
" device, \n",
|
| 106 |
+
" save_dir=\"checkpoints\", \n",
|
| 107 |
+
" csv_file=\"validation_accuracy.csv\"\n",
|
| 108 |
+
"):\n",
|
| 109 |
+
" # Préparer le dossier de sauvegarde\n",
|
| 110 |
+
" os.makedirs(save_dir, exist_ok=True)\n",
|
| 111 |
+
"\n",
|
| 112 |
+
" # Préparer le fichier CSV\n",
|
| 113 |
+
" if not os.path.exists(csv_file):\n",
|
| 114 |
+
" with open(csv_file, mode=\"w\", newline=\"\") as file:\n",
|
| 115 |
+
" writer = csv.writer(file)\n",
|
| 116 |
+
" writer.writerow([\"epoch\", \"val_accuracy\"]) # En-têtes du CSV\n",
|
| 117 |
+
"\n",
|
| 118 |
+
" model = model.to(device)\n",
|
| 119 |
+
"\n",
|
| 120 |
+
" for epoch in range(num_epochs):\n",
|
| 121 |
+
" print(f\"Epoch {epoch + 1}/{num_epochs}\")\n",
|
| 122 |
+
" print(\"-\" * 10)\n",
|
| 123 |
+
"\n",
|
| 124 |
+
" for phase in ['train', 'val']:\n",
|
| 125 |
+
" if phase == 'train':\n",
|
| 126 |
+
" model.train()\n",
|
| 127 |
+
" else:\n",
|
| 128 |
+
" model.eval()\n",
|
| 129 |
+
"\n",
|
| 130 |
+
" running_loss = 0.0\n",
|
| 131 |
+
" running_corrects = 0\n",
|
| 132 |
+
" \n",
|
| 133 |
+
" for inputs, labels in dataloaders[phase]:\n",
|
| 134 |
+
" inputs = inputs.to(device, dtype=torch.float)\n",
|
| 135 |
+
" labels = labels.to(device, dtype=torch.float).view(-1) # Labels en 1D pour BCEWithLogitsLoss\n",
|
| 136 |
+
"\n",
|
| 137 |
+
" optimizer.zero_grad()\n",
|
| 138 |
+
"\n",
|
| 139 |
+
" with torch.set_grad_enabled(phase == 'train'):\n",
|
| 140 |
+
" outputs = model(inputs).view(-1) # Sorties en 1D pour BCEWithLogitsLoss\n",
|
| 141 |
+
" loss = criterion(outputs, labels) # Calcul de la perte\n",
|
| 142 |
+
" \n",
|
| 143 |
+
" if phase == 'train':\n",
|
| 144 |
+
" loss.backward()\n",
|
| 145 |
+
" optimizer.step()\n",
|
| 146 |
+
" \n",
|
| 147 |
+
" running_loss += loss.item() * inputs.size(0)\n",
|
| 148 |
+
"\n",
|
| 149 |
+
" # Calcul des prédictions binaires (sigmoid + seuil 0.5)\n",
|
| 150 |
+
" preds = torch.sigmoid(outputs) > 0.5\n",
|
| 151 |
+
" running_corrects += torch.sum(preds == labels.bool()) # Comparaison binaire\n",
|
| 152 |
+
" #print(running_corrects, len(dataloaders[phase].dataset))\n",
|
| 153 |
+
" \n",
|
| 154 |
+
" epoch_loss = running_loss / len(dataloaders[phase].dataset)\n",
|
| 155 |
+
" epoch_acc = running_corrects.double() / len(dataloaders[phase].dataset)\n",
|
| 156 |
+
" \n",
|
| 157 |
+
" print(f\"{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}\")\n",
|
| 158 |
+
"\n",
|
| 159 |
+
" # Sauvegarde du modèle et de l'accuracy si en phase de validation\n",
|
| 160 |
+
" if phase == 'val':\n",
|
| 161 |
+
" # Sauvegarder le modèle\n",
|
| 162 |
+
" model_save_path = os.path.join(save_dir, f\"model_epoch_{epoch + 1}.pth\")\n",
|
| 163 |
+
" torch.save(model.state_dict(), model_save_path)\n",
|
| 164 |
+
" print(f\"Model saved to {model_save_path}\")\n",
|
| 165 |
+
"\n",
|
| 166 |
+
" # Écrire l'accuracy dans le fichier CSV\n",
|
| 167 |
+
" with open(csv_file, mode=\"a\", newline=\"\") as file:\n",
|
| 168 |
+
" writer = csv.writer(file)\n",
|
| 169 |
+
" writer.writerow([epoch + 1, epoch_acc.item()]) # Ajouter l'epoch et l'accuracy\n",
|
| 170 |
+
"\n",
|
| 171 |
+
" print(\"Training complete.\")\n",
|
| 172 |
+
" return model\n"
|
| 173 |
+
]
|
| 174 |
+
},
|
| 175 |
+
{
|
| 176 |
+
"cell_type": "code",
|
| 177 |
+
"execution_count": 5,
|
| 178 |
+
"id": "d8d813e0-a445-4b65-b9e3-68e8bee28e8d",
|
| 179 |
+
"metadata": {},
|
| 180 |
+
"outputs": [],
|
| 181 |
+
"source": [
|
| 182 |
+
"X_train = signals_train\n",
|
| 183 |
+
"X_test = signals_test\n",
|
| 184 |
+
"y_train = labels_train\n",
|
| 185 |
+
"y_test = labels_test"
|
| 186 |
+
]
|
| 187 |
+
},
|
| 188 |
+
{
|
| 189 |
+
"cell_type": "code",
|
| 190 |
+
"execution_count": 6,
|
| 191 |
+
"id": "c17f7b65-03cc-4eda-892e-0cfee758257c",
|
| 192 |
+
"metadata": {},
|
| 193 |
+
"outputs": [],
|
| 194 |
+
"source": [
|
| 195 |
+
"# Paramètres dataset\n",
|
| 196 |
+
"\n",
|
| 197 |
+
"SAMPLE_RATE = 12000\n",
|
| 198 |
+
"N_FFT = 2048 \n",
|
| 199 |
+
"HOP_LENGTH = 512 \n",
|
| 200 |
+
"N_MELS = 100 \n",
|
| 201 |
+
"BATCH_SIZE = 64\n",
|
| 202 |
+
"MEAN = -24.443264\n",
|
| 203 |
+
"STD = 8.27237\n",
|
| 204 |
+
"\n",
|
| 205 |
+
"\n",
|
| 206 |
+
"MEAN = 0.17555018\n",
|
| 207 |
+
"STD = 0.19079028\n",
|
| 208 |
+
"MEAN=0.18522209\n",
|
| 209 |
+
"STD=0.20916936\n",
|
| 210 |
+
"\n",
|
| 211 |
+
"\n",
|
| 212 |
+
"\n",
|
| 213 |
+
"# Créer les datasets et dataloaders\n",
|
| 214 |
+
"train_dataset = AudioDataset(X_train,\n",
|
| 215 |
+
" y_train,\n",
|
| 216 |
+
" mean=MEAN,\n",
|
| 217 |
+
" std=STD,\n",
|
| 218 |
+
" n_mels=N_MELS,\n",
|
| 219 |
+
" n_fft=N_FFT,\n",
|
| 220 |
+
" hop_length=HOP_LENGTH,\n",
|
| 221 |
+
" mixup=True)\n",
|
| 222 |
+
"val_dataset = AudioDataset(X_test,\n",
|
| 223 |
+
" y_test,\n",
|
| 224 |
+
" mean=MEAN,\n",
|
| 225 |
+
" std=STD,\n",
|
| 226 |
+
" n_mels=N_MELS,\n",
|
| 227 |
+
" n_fft=N_FFT,\n",
|
| 228 |
+
" hop_length=HOP_LENGTH,\n",
|
| 229 |
+
" mixup=False)\n",
|
| 230 |
+
"\n",
|
| 231 |
+
"dataloaders = {\n",
|
| 232 |
+
" \"train\": DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=4),\n",
|
| 233 |
+
" \"val\": DataLoader(val_dataset, batch_size=BATCH_SIZE, shuffle=False, num_workers=4)\n",
|
| 234 |
+
"}"
|
| 235 |
+
]
|
| 236 |
+
},
|
| 237 |
+
{
|
| 238 |
+
"cell_type": "code",
|
| 239 |
+
"execution_count": 7,
|
| 240 |
+
"id": "11bbd974-9065-487c-a7db-ee6e7c66c5e5",
|
| 241 |
+
"metadata": {},
|
| 242 |
+
"outputs": [
|
| 243 |
+
{
|
| 244 |
+
"data": {
|
| 245 |
+
"text/plain": [
|
| 246 |
+
"<matplotlib.image.AxesImage at 0x7fd388f59e90>"
|
| 247 |
+
]
|
| 248 |
+
},
|
| 249 |
+
"execution_count": 7,
|
| 250 |
+
"metadata": {},
|
| 251 |
+
"output_type": "execute_result"
|
| 252 |
+
},
|
| 253 |
+
{
|
| 254 |
+
"data": {
|
| 255 |
+
"image/png": "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hZ7QTsAXBYSQUsFBjRBSKpp2UGtra5MPf/jD0tbWdqqb0tSwn+YG+2lulKGfmu5FASGELISmfVIjhJD5wEGNEFIqOKgRQkoFBzVCSKngoEYIKRVNO6jdfvvtctZZZ0l7e7tceuml8vDDD5/qJp0ytm3bJhdffLF0dXXJihUr5KqrrpJdu3aZbY4fPy6bNm2Svr4+Wbx4sVxzzTUyNDR0ilrcHHz84x+XJElky5Yt9b+xn2Z49tln5e1vf7v09fVJR0eHXHDBBfLII4/U1zvn5Oabb5aVK1dKR0eHbNy4UZ588slT2OK505SD2te//nW58cYb5cMf/rA8+uij8qpXvUquuOIKOXDgwKlu2inh/vvvl02bNsmDDz4o9913n0xNTcmb3/xmGR8fr29zww03yHe+8x2555575P7775d9+/bJ1VdffQpbfWr52c9+Jp/97Gflla98pfk7+0nk8OHDctlll0lLS4t8//vfl8cff1z+9V//VZYsWVLf5pZbbpHbbrtN7rzzTnnooYeks7NTrrjiCjl+/PgpbPkccU3IJZdc4jZt2lRfrtVqbtWqVW7btm2nsFXNw4EDB5yIuPvvv98559zw8LBraWlx99xzT32b3/zmN05E3I4dO05VM08ZY2Nj7pxzznH33Xef+5M/+RP3vve9zznHfjrBBz7wAff617++4fosy9zAwID7l3/5l/rfhoeHXVtbm/vqV7/6h2jigmi6J7XJyUnZuXOnbNy4sf63NE1l48aNsmPHjlPYsuZhZGRERESWLl0qIiI7d+6Uqakp02fr1q2TNWvWnJZ9tmnTJnnLW95i+kOE/XSCb3/727J+/Xp561vfKitWrJALL7xQPv/5z9fX7969WwYHB00/9fT0yKWXXvqS6KemG9QOHjwotVpN+vv7zd/7+/tlcHDwFLWqeciyTLZs2SKXXXaZnH/++SIiMjg4KK2trdLb22u2PR377Gtf+5o8+uijsm3bNm8d+2mGp556Su644w4555xz5Ac/+IG8613vkve+971y9913i4jU++Kl+htsOushEmbTpk3y2GOPyQMPPHCqm9J07N27V973vvfJfffdJ+3t7ae6OU1LlmWyfv16+djHPiYiIhdeeKE89thjcuedd8p11113ilu3cJruSW3ZsmVSqVS8N1JDQ0MyMDBwilrVHGzevFm++93vyo9+9CM588wz638fGBiQyclJGR4eNtufbn22c+dOOXDggLzmNa+RarUq1WpV7r//frntttukWq1Kf38/+0lEVq5cKa94xSvM384991zZs2ePiEi9L16qv8GmG9RaW1vloosuku3bt9f/lmWZbN++XTZs2HAKW3bqcM7J5s2b5Rvf+Ib88Ic/lLVr15r1F110kbS0tJg+27Vrl+zZs+e06rPLL79cfvWrX8nPf/7z+r/169fLtddeW//MfhK57LLLvJCgJ554Ql72speJiMjatWtlYGDA9NPo6Kg89NBDL41+OtVvKmbja1/7mmtra3Nf/OIX3eOPP+7e+c53ut7eXjc4OHiqm3ZKeNe73uV6enrcj3/8Y7d///76v6NHj9a3+bu/+zu3Zs0a98Mf/tA98sgjbsOGDW7Dhg2nsNXNgX776Rz7yTnnHn74YVetVt1HP/pR9+STT7ovf/nLbtGiRe7f/u3f6tt8/OMfd729ve5b3/qW++Uvf+muvPJKt3btWnfs2LFT2PK50ZSDmnPOffrTn3Zr1qxxra2t7pJLLnEPPvjgqW7SKUNm6mp5/+666676NseOHXPvfve73ZIlS9yiRYvcn//5n7v9+/efukY3CTiosZ9m+M53vuPOP/9819bW5tatW+c+97nPmfVZlrmbbrrJ9ff3u7a2Nnf55Ze7Xbt2naLWFoN+aoSQUtF0mhohhCwEDmqEkFLBQY0QUio4qBFCSgUHNUJIqeCgRggpFRzUCCGlgoMaIaRUcFAjhJQKDmqEkFLBQY0QUir+f7OSPL7BW8HQAAAAAElFTkSuQmCC",
|
| 256 |
+
"text/plain": [
|
| 257 |
+
"<Figure size 640x480 with 1 Axes>"
|
| 258 |
+
]
|
| 259 |
+
},
|
| 260 |
+
"metadata": {},
|
| 261 |
+
"output_type": "display_data"
|
| 262 |
+
}
|
| 263 |
+
],
|
| 264 |
+
"source": [
|
| 265 |
+
"plt.imshow((train_dataset[5][0][0]))"
|
| 266 |
+
]
|
| 267 |
+
},
|
| 268 |
+
{
|
| 269 |
+
"cell_type": "code",
|
| 270 |
+
"execution_count": 8,
|
| 271 |
+
"id": "eba16b15-b762-4b65-9386-e64ad666e41e",
|
| 272 |
+
"metadata": {},
|
| 273 |
+
"outputs": [],
|
| 274 |
+
"source": [
|
| 275 |
+
"class ConvLayer(nn.Module):\n",
|
| 276 |
+
" def __init__(self, in_channels, out_channels):\n",
|
| 277 |
+
" super(ConvLayer, self).__init__()\n",
|
| 278 |
+
" self.conv_layers = nn.Sequential(\n",
|
| 279 |
+
" nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False),\n",
|
| 280 |
+
" nn.BatchNorm2d(out_channels),\n",
|
| 281 |
+
" nn.ReLU(),\n",
|
| 282 |
+
" nn.MaxPool2d(kernel_size=2, stride=2),\n",
|
| 283 |
+
" )\n",
|
| 284 |
+
"\n",
|
| 285 |
+
" def forward(self, x):\n",
|
| 286 |
+
" x = self.conv_layers(x)\n",
|
| 287 |
+
" return x\n",
|
| 288 |
+
"\n",
|
| 289 |
+
"\n",
|
| 290 |
+
"class AudioClassifierCNN(nn.Module):\n",
|
| 291 |
+
" def __init__(self):\n",
|
| 292 |
+
" super(AudioClassifierCNN, self).__init__()\n",
|
| 293 |
+
" \n",
|
| 294 |
+
" self.conv_layers = nn.Sequential(\n",
|
| 295 |
+
" ConvLayer(1, 16),\n",
|
| 296 |
+
" ConvLayer(16, 32),\n",
|
| 297 |
+
" ConvLayer(32, 64),\n",
|
| 298 |
+
" ConvLayer(64, 128),\n",
|
| 299 |
+
" ConvLayer(128, 256),\n",
|
| 300 |
+
" ConvLayer(256, 256)\n",
|
| 301 |
+
" )\n",
|
| 302 |
+
"\n",
|
| 303 |
+
"\n",
|
| 304 |
+
" self.fc_layers = nn.Sequential(\n",
|
| 305 |
+
" nn.Flatten(),\n",
|
| 306 |
+
" nn.Linear(256, 32),\n",
|
| 307 |
+
" nn.ReLU(),\n",
|
| 308 |
+
" nn.Dropout(0.4),\n",
|
| 309 |
+
" nn.Linear(32, 1)\n",
|
| 310 |
+
" )\n",
|
| 311 |
+
"\n",
|
| 312 |
+
" def forward(self, x):\n",
|
| 313 |
+
" x = self.conv_layers(x)\n",
|
| 314 |
+
" x = self.fc_layers(x)\n",
|
| 315 |
+
" return x.squeeze(1)"
|
| 316 |
+
]
|
| 317 |
+
},
|
| 318 |
+
{
|
| 319 |
+
"cell_type": "code",
|
| 320 |
+
"execution_count": 9,
|
| 321 |
+
"id": "37214be6-cf2a-472f-8c59-8a57d4efb7a1",
|
| 322 |
+
"metadata": {},
|
| 323 |
+
"outputs": [
|
| 324 |
+
{
|
| 325 |
+
"data": {
|
| 326 |
+
"text/plain": [
|
| 327 |
+
"tensor([0.4159], grad_fn=<SqueezeBackward1>)"
|
| 328 |
+
]
|
| 329 |
+
},
|
| 330 |
+
"execution_count": 9,
|
| 331 |
+
"metadata": {},
|
| 332 |
+
"output_type": "execute_result"
|
| 333 |
+
}
|
| 334 |
+
],
|
| 335 |
+
"source": [
|
| 336 |
+
"model = AudioClassifierCNN()\n",
|
| 337 |
+
"a, b = train_dataset[3]\n",
|
| 338 |
+
"model(a.unsqueeze(0))"
|
| 339 |
+
]
|
| 340 |
+
},
|
| 341 |
+
{
|
| 342 |
+
"cell_type": "code",
|
| 343 |
+
"execution_count": 10,
|
| 344 |
+
"id": "93a17a9d-203b-4c61-ba2c-63deebe6c42e",
|
| 345 |
+
"metadata": {},
|
| 346 |
+
"outputs": [],
|
| 347 |
+
"source": [
|
| 348 |
+
"# (To find mean and std for normalization)\n",
|
| 349 |
+
"if 0:\n",
|
| 350 |
+
" mean = []\n",
|
| 351 |
+
" std = []\n",
|
| 352 |
+
" mean_b = []\n",
|
| 353 |
+
" std_b = []\n",
|
| 354 |
+
" for a, b in train_dataset:\n",
|
| 355 |
+
" mean.append(a.mean((-1,-2)))\n",
|
| 356 |
+
" std.append(a.std((-1,-2)))\n",
|
| 357 |
+
" print(np.mean(mean, 0))\n",
|
| 358 |
+
" print(np.mean(std, 0))"
|
| 359 |
+
]
|
| 360 |
+
},
|
| 361 |
+
{
|
| 362 |
+
"cell_type": "code",
|
| 363 |
+
"execution_count": 11,
|
| 364 |
+
"id": "9d74c1d8-0f3d-4802-9a15-5c62464a3fcc",
|
| 365 |
+
"metadata": {},
|
| 366 |
+
"outputs": [
|
| 367 |
+
{
|
| 368 |
+
"name": "stdout",
|
| 369 |
+
"output_type": "stream",
|
| 370 |
+
"text": [
|
| 371 |
+
"Epoch 1/50\n",
|
| 372 |
+
"----------\n",
|
| 373 |
+
"train Loss: 0.2585 Acc: 0.9038\n",
|
| 374 |
+
"val Loss: 0.2161 Acc: 0.9196\n",
|
| 375 |
+
"Model saved to checkpoints2/model_epoch_1.pth\n",
|
| 376 |
+
"Epoch 2/50\n",
|
| 377 |
+
"----------\n",
|
| 378 |
+
"train Loss: 0.2139 Acc: 0.9247\n",
|
| 379 |
+
"val Loss: 0.1747 Acc: 0.9382\n",
|
| 380 |
+
"Model saved to checkpoints2/model_epoch_2.pth\n",
|
| 381 |
+
"Epoch 3/50\n",
|
| 382 |
+
"----------\n",
|
| 383 |
+
"train Loss: 0.1972 Acc: 0.9321\n",
|
| 384 |
+
"val Loss: 0.1415 Acc: 0.9491\n",
|
| 385 |
+
"Model saved to checkpoints2/model_epoch_3.pth\n",
|
| 386 |
+
"Epoch 4/50\n",
|
| 387 |
+
"----------\n",
|
| 388 |
+
"train Loss: 0.1855 Acc: 0.9351\n",
|
| 389 |
+
"val Loss: 0.1346 Acc: 0.9515\n",
|
| 390 |
+
"Model saved to checkpoints2/model_epoch_4.pth\n",
|
| 391 |
+
"Epoch 5/50\n",
|
| 392 |
+
"----------\n",
|
| 393 |
+
"train Loss: 0.1786 Acc: 0.9380\n",
|
| 394 |
+
"val Loss: 0.1483 Acc: 0.9521\n",
|
| 395 |
+
"Model saved to checkpoints2/model_epoch_5.pth\n",
|
| 396 |
+
"Epoch 6/50\n",
|
| 397 |
+
"----------\n"
|
| 398 |
+
]
|
| 399 |
+
},
|
| 400 |
+
{
|
| 401 |
+
"ename": "KeyboardInterrupt",
|
| 402 |
+
"evalue": "",
|
| 403 |
+
"output_type": "error",
|
| 404 |
+
"traceback": [
|
| 405 |
+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
| 406 |
+
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
|
| 407 |
+
"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",
|
| 408 |
+
"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",
|
| 409 |
+
"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",
|
| 410 |
+
"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",
|
| 411 |
+
"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",
|
| 412 |
+
"\u001b[0;31mKeyboardInterrupt\u001b[0m: "
|
| 413 |
+
]
|
| 414 |
+
}
|
| 415 |
+
],
|
| 416 |
+
"source": [
|
| 417 |
+
"# Paramètre apprentissage\n",
|
| 418 |
+
"EPOCHS = 20\n",
|
| 419 |
+
"LEARNING_RATE = 0.001\n",
|
| 420 |
+
"\n",
|
| 421 |
+
"# Initialiser le modèle, la loss, et l'optimiseur\n",
|
| 422 |
+
"num_classes = 2 # Ajustez selon vos besoins\n",
|
| 423 |
+
"model = AudioClassifierCNN()\n",
|
| 424 |
+
"criterion = nn.BCEWithLogitsLoss()\n",
|
| 425 |
+
"optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE)\n",
|
| 426 |
+
"\n",
|
| 427 |
+
"# Entraîner le modèle\n",
|
| 428 |
+
"model = train_model(model, dataloaders, criterion, optimizer, num_epochs=50, device=\"cuda\", save_dir=\"checkpoints2\", csv_file=\"valid2.csv\")\n"
|
| 429 |
+
]
|
| 430 |
+
},
|
| 431 |
+
{
|
| 432 |
+
"cell_type": "code",
|
| 433 |
+
"execution_count": 12,
|
| 434 |
+
"id": "7e854804-ae5e-46e1-88fb-53f5acfd9429",
|
| 435 |
+
"metadata": {},
|
| 436 |
+
"outputs": [
|
| 437 |
+
{
|
| 438 |
+
"name": "stderr",
|
| 439 |
+
"output_type": "stream",
|
| 440 |
+
"text": [
|
| 441 |
+
"[codecarbon WARNING @ 01:53:44] Multiple instances of codecarbon are allowed to run at the same time.\n",
|
| 442 |
+
"[codecarbon INFO @ 01:53:44] [setup] RAM Tracking...\n",
|
| 443 |
+
"[codecarbon INFO @ 01:53:44] [setup] CPU Tracking...\n",
|
| 444 |
+
"[codecarbon WARNING @ 01:53:44] No CPU tracking mode found. Falling back on CPU constant mode. \n",
|
| 445 |
+
" Linux OS detected: Please ensure RAPL files exist at \\sys\\class\\powercap\\intel-rapl to measure CPU\n",
|
| 446 |
+
"\n",
|
| 447 |
+
"[codecarbon INFO @ 01:53:45] CPU Model on constant consumption mode: AMD Ryzen 9 5900X 12-Core Processor\n",
|
| 448 |
+
"[codecarbon INFO @ 01:53:45] [setup] GPU Tracking...\n",
|
| 449 |
+
"[codecarbon INFO @ 01:53:45] Tracking Nvidia GPU via pynvml\n",
|
| 450 |
+
"[codecarbon INFO @ 01:53:45] >>> Tracker's metadata:\n",
|
| 451 |
+
"[codecarbon INFO @ 01:53:45] Platform system: Linux-6.1.0-26-amd64-x86_64-with-glibc2.36\n",
|
| 452 |
+
"[codecarbon INFO @ 01:53:45] Python version: 3.11.2\n",
|
| 453 |
+
"[codecarbon INFO @ 01:53:45] CodeCarbon version: 2.8.3\n",
|
| 454 |
+
"[codecarbon INFO @ 01:53:45] Available RAM : 31.259 GB\n",
|
| 455 |
+
"[codecarbon INFO @ 01:53:45] CPU count: 24\n",
|
| 456 |
+
"[codecarbon INFO @ 01:53:45] CPU model: AMD Ryzen 9 5900X 12-Core Processor\n",
|
| 457 |
+
"[codecarbon INFO @ 01:53:45] GPU count: 1\n",
|
| 458 |
+
"[codecarbon INFO @ 01:53:45] GPU model: 1 x NVIDIA GeForce RTX 3080\n",
|
| 459 |
+
"[codecarbon INFO @ 01:53:49] Saving emissions data to file /home/kangourou/frugal/emissions.csv\n"
|
| 460 |
+
]
|
| 461 |
+
}
|
| 462 |
+
],
|
| 463 |
+
"source": [
|
| 464 |
+
"from codecarbon import EmissionsTracker\n",
|
| 465 |
+
"tracker = EmissionsTracker(allow_multiple_runs=True)"
|
| 466 |
+
]
|
| 467 |
+
},
|
| 468 |
+
{
|
| 469 |
+
"cell_type": "code",
|
| 470 |
+
"execution_count": 19,
|
| 471 |
+
"id": "f23a1000-90e0-4777-825f-38d270128ae7",
|
| 472 |
+
"metadata": {},
|
| 473 |
+
"outputs": [
|
| 474 |
+
{
|
| 475 |
+
"name": "stderr",
|
| 476 |
+
"output_type": "stream",
|
| 477 |
+
"text": [
|
| 478 |
+
"[codecarbon WARNING @ 01:55:10] Already started tracking\n",
|
| 479 |
+
"100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 119/119 [00:00<00:00, 173.09it/s]\n",
|
| 480 |
+
"[codecarbon INFO @ 01:55:10] Energy consumed for RAM : 0.000160 kWh. RAM Power : 11.722217559814453 W\n",
|
| 481 |
+
"[codecarbon INFO @ 01:55:10] Energy consumed for all CPUs : 0.000717 kWh. Total CPU Power : 52.5 W\n",
|
| 482 |
+
"[codecarbon INFO @ 01:55:10] Energy consumed for all GPUs : 0.001315 kWh. Total GPU Power : 238.54231240370862 W\n",
|
| 483 |
+
"[codecarbon INFO @ 01:55:10] 0.002192 kWh of electricity used since the beginning.\n"
|
| 484 |
+
]
|
| 485 |
+
},
|
| 486 |
+
{
|
| 487 |
+
"name": "stdout",
|
| 488 |
+
"output_type": "stream",
|
| 489 |
+
"text": [
|
| 490 |
+
"0.05850168950330892\n"
|
| 491 |
+
]
|
| 492 |
+
}
|
| 493 |
+
],
|
| 494 |
+
"source": [
|
| 495 |
+
"mel_transform = torchaudio.transforms.MelSpectrogram(\n",
|
| 496 |
+
" sample_rate=SAMPLE_RATE,\n",
|
| 497 |
+
" n_fft=2048,\n",
|
| 498 |
+
" hop_length=512,\n",
|
| 499 |
+
" n_mels=100\n",
|
| 500 |
+
").cuda()\n",
|
| 501 |
+
"X_train\n",
|
| 502 |
+
"model.cuda()\n",
|
| 503 |
+
"preds = []\n",
|
| 504 |
+
"\n",
|
| 505 |
+
"tracker.start()\n",
|
| 506 |
+
"tracker.start_task(\"inference\")\n",
|
| 507 |
+
"with torch.inference_mode():\n",
|
| 508 |
+
" bs=128\n",
|
| 509 |
+
" for i in tqdm(range(0, X_test.shape[0], bs)):\n",
|
| 510 |
+
" batch = X_test[i:i+bs]\n",
|
| 511 |
+
" mel = mel_transform(torch.as_tensor(batch).cuda())\n",
|
| 512 |
+
" mel = torch.log10(1+mel)\n",
|
| 513 |
+
" #mel_spectrogram = mel_spectrogram[:,:50]\n",
|
| 514 |
+
" #mfcc = self.mfcc_transform(waveform).mean(-1).squeeze(0)\n",
|
| 515 |
+
" \n",
|
| 516 |
+
"\n",
|
| 517 |
+
" # Normaliser le spectrogramme\n",
|
| 518 |
+
" mel = (mel - MEAN)/STD\n",
|
| 519 |
+
" mel = mel.unsqueeze(1)\n",
|
| 520 |
+
" #pred = np.argmax(model(mel).cpu().numpy(), -1)\n",
|
| 521 |
+
" pred = torch.sigmoid(model(mel)).cpu().numpy()\n",
|
| 522 |
+
" preds.append(pred)\n",
|
| 523 |
+
"preds = np.concatenate(preds)\n",
|
| 524 |
+
"\n",
|
| 525 |
+
"emissions_data = tracker.stop_task()\n",
|
| 526 |
+
"print(emissions_data.energy_consumed * 1000)"
|
| 527 |
+
]
|
| 528 |
+
},
|
| 529 |
+
{
|
| 530 |
+
"cell_type": "code",
|
| 531 |
+
"execution_count": 20,
|
| 532 |
+
"id": "bc710afc-392d-4591-b129-07d3419f8696",
|
| 533 |
+
"metadata": {},
|
| 534 |
+
"outputs": [
|
| 535 |
+
{
|
| 536 |
+
"data": {
|
| 537 |
+
"text/plain": [
|
| 538 |
+
"np.float64(0.9478174603174603)"
|
| 539 |
+
]
|
| 540 |
+
},
|
| 541 |
+
"execution_count": 20,
|
| 542 |
+
"metadata": {},
|
| 543 |
+
"output_type": "execute_result"
|
| 544 |
+
}
|
| 545 |
+
],
|
| 546 |
+
"source": [
|
| 547 |
+
"((preds>0.5)==labels_test).sum()/preds.size"
|
| 548 |
+
]
|
| 549 |
+
},
|
| 550 |
+
{
|
| 551 |
+
"cell_type": "code",
|
| 552 |
+
"execution_count": null,
|
| 553 |
+
"id": "d6f3d8e7-3315-4f78-b7a4-789d75eb1eac",
|
| 554 |
+
"metadata": {},
|
| 555 |
+
"outputs": [],
|
| 556 |
+
"source": [
|
| 557 |
+
"np.save(\"preds_nn.npy\", preds)"
|
| 558 |
+
]
|
| 559 |
+
}
|
| 560 |
+
],
|
| 561 |
+
"metadata": {
|
| 562 |
+
"kernelspec": {
|
| 563 |
+
"display_name": "Python 3 (ipykernel)",
|
| 564 |
+
"language": "python",
|
| 565 |
+
"name": "python3"
|
| 566 |
+
},
|
| 567 |
+
"language_info": {
|
| 568 |
+
"codemirror_mode": {
|
| 569 |
+
"name": "ipython",
|
| 570 |
+
"version": 3
|
| 571 |
+
},
|
| 572 |
+
"file_extension": ".py",
|
| 573 |
+
"mimetype": "text/x-python",
|
| 574 |
+
"name": "python",
|
| 575 |
+
"nbconvert_exporter": "python",
|
| 576 |
+
"pygments_lexer": "ipython3",
|
| 577 |
+
"version": "3.11.2"
|
| 578 |
+
}
|
| 579 |
+
},
|
| 580 |
+
"nbformat": 4,
|
| 581 |
+
"nbformat_minor": 5
|
| 582 |
+
}
|
notebooks/XGBoost_train.ipynb
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "code",
|
| 5 |
+
"execution_count": 1,
|
| 6 |
+
"id": "d3e9ed94-07af-482e-a610-03eb8eec8608",
|
| 7 |
+
"metadata": {},
|
| 8 |
+
"outputs": [],
|
| 9 |
+
"source": [
|
| 10 |
+
"from datasets import load_from_disk\n",
|
| 11 |
+
"from IPython.display import Audio\n",
|
| 12 |
+
"import matplotlib.pyplot as plt\n",
|
| 13 |
+
"import librosa\n",
|
| 14 |
+
"import numpy as np\n",
|
| 15 |
+
"import torchaudio\n",
|
| 16 |
+
"import torch\n",
|
| 17 |
+
"\n",
|
| 18 |
+
"from preprocess import get_raw_data, basic_stats_dataset, get_batch_generator\n",
|
| 19 |
+
"from sklearn.decomposition import PCA\n",
|
| 20 |
+
"from tqdm import tqdm"
|
| 21 |
+
]
|
| 22 |
+
},
|
| 23 |
+
{
|
| 24 |
+
"cell_type": "code",
|
| 25 |
+
"execution_count": 2,
|
| 26 |
+
"id": "a786f85c-649d-4c5f-8677-1e2aaff1717f",
|
| 27 |
+
"metadata": {},
|
| 28 |
+
"outputs": [],
|
| 29 |
+
"source": [
|
| 30 |
+
"dataset = load_from_disk(\"audio\")\n",
|
| 31 |
+
"SR = 12000"
|
| 32 |
+
]
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"cell_type": "code",
|
| 36 |
+
"execution_count": 3,
|
| 37 |
+
"id": "f55a78dd-2946-4b74-8c6d-8c9d9ba125a7",
|
| 38 |
+
"metadata": {},
|
| 39 |
+
"outputs": [],
|
| 40 |
+
"source": [
|
| 41 |
+
"signals_train, labels_train, sizes_train = get_raw_data(dataset[\"train\"], pad=\"reflect\")\n",
|
| 42 |
+
"signals_test, labels_test, sizes_test = get_raw_data(dataset[\"test\"], pad=\"reflect\")"
|
| 43 |
+
]
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"cell_type": "code",
|
| 47 |
+
"execution_count": 4,
|
| 48 |
+
"id": "543acf10-a35b-4ba0-bbfc-e72264e54242",
|
| 49 |
+
"metadata": {},
|
| 50 |
+
"outputs": [],
|
| 51 |
+
"source": [
|
| 52 |
+
"import scipy\n",
|
| 53 |
+
"def get_mfcc_features(signals, labels, bs, do_mixup=False, n_mels=50, nfft = 512, hop=128):\n",
|
| 54 |
+
" features = np.zeros((signals.shape[0], n_mels*2), dtype=np.float32)\n",
|
| 55 |
+
" transform = torchaudio.transforms.MFCC(\n",
|
| 56 |
+
" sample_rate=SR,\n",
|
| 57 |
+
" n_mfcc=n_mels,\n",
|
| 58 |
+
" log_mels=True,\n",
|
| 59 |
+
" melkwargs={\"n_fft\": nfft, \"hop_length\": hop, \"n_mels\": n_mels}#\"f_min\":0, \"f_max\":4000},\n",
|
| 60 |
+
" ).cuda()\n",
|
| 61 |
+
" \n",
|
| 62 |
+
" for i in tqdm(range(0, signals.shape[0], bs)):\n",
|
| 63 |
+
" batch = signals[i:i+bs]\n",
|
| 64 |
+
" batch_tensor = torch.as_tensor(batch).cuda()\n",
|
| 65 |
+
" mfcc_batch = transform(batch_tensor)\n",
|
| 66 |
+
"\n",
|
| 67 |
+
" features[i:i+bs,:n_mels] = mfcc_batch.mean(-1).cpu().numpy()\n",
|
| 68 |
+
" features[i:i+bs,n_mels:n_mels*2] = mfcc_batch.std(-1).cpu().numpy()\n",
|
| 69 |
+
" \n",
|
| 70 |
+
" return features\n",
|
| 71 |
+
"\n",
|
| 72 |
+
"\n",
|
| 73 |
+
"def get_mel_features(signals, bs):\n",
|
| 74 |
+
" features = np.zeros((signals.shape[0], 55*3), dtype=np.float32)\n",
|
| 75 |
+
" \n",
|
| 76 |
+
" transform = torchaudio.transforms.MelSpectrogram(\n",
|
| 77 |
+
" sample_rate=12000,\n",
|
| 78 |
+
" n_fft=1024,\n",
|
| 79 |
+
" hop_length=512,\n",
|
| 80 |
+
" n_mels=55\n",
|
| 81 |
+
" ).cuda()\n",
|
| 82 |
+
"\n",
|
| 83 |
+
" for i in tqdm(range(0, signals.shape[0], bs)):\n",
|
| 84 |
+
" batch = signals[i:i+bs]\n",
|
| 85 |
+
"\n",
|
| 86 |
+
" batch_tensor = torch.as_tensor(batch).cuda()\n",
|
| 87 |
+
" \n",
|
| 88 |
+
" mel_batch = transform(batch_tensor)\n",
|
| 89 |
+
" mel_batch_delta = torchaudio.functional.compute_deltas(mel_batch)\n",
|
| 90 |
+
" mel_batch_delta_delta = torchaudio.functional.compute_deltas(mel_batch_delta)\n",
|
| 91 |
+
"\n",
|
| 92 |
+
" feat_all = np.hstack((\n",
|
| 93 |
+
" mel_batch.mean(-1).cpu(),\n",
|
| 94 |
+
" mel_batch.std(-1).cpu(),\n",
|
| 95 |
+
" #mel_batch_delta.mean(-1).cpu(),\n",
|
| 96 |
+
" mel_batch_delta.std(-1).cpu(),\n",
|
| 97 |
+
" #scipy.stats.skew(mel_batch_delta.cpu().numpy(), -1),\n",
|
| 98 |
+
" #mel_batch_delta_delta.mean(-1).cpu(),\n",
|
| 99 |
+
" #mel_batch_delta_delta.std(-1).cpu(),\n",
|
| 100 |
+
" ))\n",
|
| 101 |
+
" features[i:i+bs, :] = feat_all\n",
|
| 102 |
+
" return features\n",
|
| 103 |
+
"\n",
|
| 104 |
+
"\n",
|
| 105 |
+
"\n",
|
| 106 |
+
"def get_spectral_features(signals, bs):\n",
|
| 107 |
+
" features = []\n",
|
| 108 |
+
" for i in tqdm(range(0, signals.shape[0], bs)):\n",
|
| 109 |
+
" batch = signals[i:i+bs]\n",
|
| 110 |
+
"\n",
|
| 111 |
+
" a = librosa.feature.spectral_contrast(y=batch, sr=12000, fmin=50, n_bands=3)\n",
|
| 112 |
+
" #b = librosa.feature.spectral_bandwidth(y=batch, sr=12000).mean((-1))\n",
|
| 113 |
+
" #c = librosa.feature.spectral_centroid(y=batch, sr=12000).mean((-1))\n",
|
| 114 |
+
" #d = librosa.feature.spectral_flatness(y=batch).mean((-1))\n",
|
| 115 |
+
" #e = librosa.feature.spectral_rolloff(y=batch, sr=12000).mean((-1))\n",
|
| 116 |
+
" #f = librosa.feature.chroma_cens(y=batch, sr=12000).mean(-1)\n",
|
| 117 |
+
" #g = librosa.feature.tonnetz(y=batch, sr=12000).mean(-1)\n",
|
| 118 |
+
" #features.append(np.hstack((a, b, c, d, e, f, g)))\n",
|
| 119 |
+
" features.append(a.mean(-1))\n",
|
| 120 |
+
" #features.append(np.hstack((a.mean(-1))))\n",
|
| 121 |
+
" #features.append(np.hstack((a, b, c, d, e, f, g)))\n",
|
| 122 |
+
" features = np.concatenate(features)\n",
|
| 123 |
+
" return features"
|
| 124 |
+
]
|
| 125 |
+
},
|
| 126 |
+
{
|
| 127 |
+
"cell_type": "code",
|
| 128 |
+
"execution_count": 5,
|
| 129 |
+
"id": "cc7e6fc1-db81-4a68-a5dc-9e33105098e6",
|
| 130 |
+
"metadata": {},
|
| 131 |
+
"outputs": [
|
| 132 |
+
{
|
| 133 |
+
"name": "stderr",
|
| 134 |
+
"output_type": "stream",
|
| 135 |
+
"text": [
|
| 136 |
+
"100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 552/552 [00:01<00:00, 488.45it/s]\n",
|
| 137 |
+
"100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 35/35 [00:00<00:00, 57.30it/s]\n"
|
| 138 |
+
]
|
| 139 |
+
}
|
| 140 |
+
],
|
| 141 |
+
"source": [
|
| 142 |
+
"train_mfcc = get_mfcc_features(signals_train, labels_train, 64, do_mixup=False, n_mels=55, nfft=1024, hop=256)\n",
|
| 143 |
+
"train_mels = get_mel_features(signals_train, 1024)\n",
|
| 144 |
+
"#train_pitch =get_pitch_features(signals_train, 2048)\n",
|
| 145 |
+
"#train_spectral_features = get_spectral_features(signals_train, 1024)"
|
| 146 |
+
]
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"cell_type": "code",
|
| 150 |
+
"execution_count": 6,
|
| 151 |
+
"id": "37fcb3f8-5984-48fd-9cff-f6430ac45269",
|
| 152 |
+
"metadata": {},
|
| 153 |
+
"outputs": [
|
| 154 |
+
{
|
| 155 |
+
"name": "stderr",
|
| 156 |
+
"output_type": "stream",
|
| 157 |
+
"text": [
|
| 158 |
+
"[codecarbon WARNING @ 02:00:34] Multiple instances of codecarbon are allowed to run at the same time.\n",
|
| 159 |
+
"[codecarbon INFO @ 02:00:34] [setup] RAM Tracking...\n",
|
| 160 |
+
"[codecarbon INFO @ 02:00:34] [setup] CPU Tracking...\n",
|
| 161 |
+
"[codecarbon WARNING @ 02:00:34] No CPU tracking mode found. Falling back on CPU constant mode. \n",
|
| 162 |
+
" Linux OS detected: Please ensure RAPL files exist at \\sys\\class\\powercap\\intel-rapl to measure CPU\n",
|
| 163 |
+
"\n",
|
| 164 |
+
"[codecarbon INFO @ 02:00:35] CPU Model on constant consumption mode: AMD Ryzen 9 5900X 12-Core Processor\n",
|
| 165 |
+
"[codecarbon INFO @ 02:00:35] [setup] GPU Tracking...\n",
|
| 166 |
+
"[codecarbon INFO @ 02:00:35] Tracking Nvidia GPU via pynvml\n",
|
| 167 |
+
"[codecarbon INFO @ 02:00:35] >>> Tracker's metadata:\n",
|
| 168 |
+
"[codecarbon INFO @ 02:00:35] Platform system: Linux-6.1.0-26-amd64-x86_64-with-glibc2.36\n",
|
| 169 |
+
"[codecarbon INFO @ 02:00:35] Python version: 3.11.2\n",
|
| 170 |
+
"[codecarbon INFO @ 02:00:35] CodeCarbon version: 2.8.3\n",
|
| 171 |
+
"[codecarbon INFO @ 02:00:35] Available RAM : 31.259 GB\n",
|
| 172 |
+
"[codecarbon INFO @ 02:00:35] CPU count: 24\n",
|
| 173 |
+
"[codecarbon INFO @ 02:00:35] CPU model: AMD Ryzen 9 5900X 12-Core Processor\n",
|
| 174 |
+
"[codecarbon INFO @ 02:00:35] GPU count: 1\n",
|
| 175 |
+
"[codecarbon INFO @ 02:00:35] GPU model: 1 x NVIDIA GeForce RTX 3080\n",
|
| 176 |
+
"[codecarbon INFO @ 02:00:38] Saving emissions data to file /home/kangourou/frugal/emissions.csv\n"
|
| 177 |
+
]
|
| 178 |
+
}
|
| 179 |
+
],
|
| 180 |
+
"source": [
|
| 181 |
+
"from codecarbon import EmissionsTracker\n",
|
| 182 |
+
"tracker = EmissionsTracker(allow_multiple_runs=True)"
|
| 183 |
+
]
|
| 184 |
+
},
|
| 185 |
+
{
|
| 186 |
+
"cell_type": "code",
|
| 187 |
+
"execution_count": 7,
|
| 188 |
+
"id": "3880dbe6-16ad-4143-a296-92339b723d81",
|
| 189 |
+
"metadata": {},
|
| 190 |
+
"outputs": [
|
| 191 |
+
{
|
| 192 |
+
"name": "stderr",
|
| 193 |
+
"output_type": "stream",
|
| 194 |
+
"text": [
|
| 195 |
+
"100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 237/237 [00:00<00:00, 649.63it/s]\n",
|
| 196 |
+
"100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 237/237 [00:00<00:00, 727.40it/s]\n",
|
| 197 |
+
"[codecarbon INFO @ 02:00:39] Energy consumed for RAM : 0.000002 kWh. RAM Power : 11.722217559814453 W\n",
|
| 198 |
+
"[codecarbon INFO @ 02:00:39] Energy consumed for all CPUs : 0.000010 kWh. Total CPU Power : 52.5 W\n",
|
| 199 |
+
"[codecarbon INFO @ 02:00:39] Energy consumed for all GPUs : 0.000036 kWh. Total GPU Power : 182.93542388234846 W\n",
|
| 200 |
+
"[codecarbon INFO @ 02:00:39] 0.000048 kWh of electricity used since the beginning.\n"
|
| 201 |
+
]
|
| 202 |
+
},
|
| 203 |
+
{
|
| 204 |
+
"name": "stdout",
|
| 205 |
+
"output_type": "stream",
|
| 206 |
+
"text": [
|
| 207 |
+
"0.04825051408887344\n"
|
| 208 |
+
]
|
| 209 |
+
}
|
| 210 |
+
],
|
| 211 |
+
"source": [
|
| 212 |
+
"tracker.start()\n",
|
| 213 |
+
"tracker.start_task(\"inference\")\n",
|
| 214 |
+
"test_mfcc = get_mfcc_features(signals_test, labels_test, 64, do_mixup=False, n_mels=55, nfft=1024, hop=256)\n",
|
| 215 |
+
"test_mels = get_mel_features(signals_test, 64)\n",
|
| 216 |
+
"#test_pitch =get_pitch_features(signals_test, 2048)\n",
|
| 217 |
+
"#test_spectral_features = get_spectral_features(signals_test, 1024)\n",
|
| 218 |
+
"emissions_data = tracker.stop_task()\n",
|
| 219 |
+
"print(emissions_data.energy_consumed * 1000)"
|
| 220 |
+
]
|
| 221 |
+
},
|
| 222 |
+
{
|
| 223 |
+
"cell_type": "code",
|
| 224 |
+
"execution_count": 8,
|
| 225 |
+
"id": "c609655a-e4f2-4450-970a-e9a813c9c349",
|
| 226 |
+
"metadata": {},
|
| 227 |
+
"outputs": [],
|
| 228 |
+
"source": [
|
| 229 |
+
"X_train = np.hstack((train_mfcc, train_mels))\n",
|
| 230 |
+
"X_test = np.hstack((test_mfcc, test_mels))\n",
|
| 231 |
+
"\n",
|
| 232 |
+
"Y_train = labels_train\n",
|
| 233 |
+
"Y_test = labels_test"
|
| 234 |
+
]
|
| 235 |
+
},
|
| 236 |
+
{
|
| 237 |
+
"cell_type": "code",
|
| 238 |
+
"execution_count": 9,
|
| 239 |
+
"id": "d3314f22-c8ed-4480-a513-462528e9a837",
|
| 240 |
+
"metadata": {},
|
| 241 |
+
"outputs": [
|
| 242 |
+
{
|
| 243 |
+
"name": "stdout",
|
| 244 |
+
"output_type": "stream",
|
| 245 |
+
"text": [
|
| 246 |
+
"0.9536375661375661\n"
|
| 247 |
+
]
|
| 248 |
+
},
|
| 249 |
+
{
|
| 250 |
+
"name": "stderr",
|
| 251 |
+
"output_type": "stream",
|
| 252 |
+
"text": [
|
| 253 |
+
"/home/kangourou/.local/share/virtualenvs/kangourou-v5SGOwnr/lib/python3.11/site-packages/xgboost/core.py:158: UserWarning: [02:01:00] WARNING: /workspace/src/common/error_msg.cc:58: Falling back to prediction using DMatrix due to mismatched devices. This might lead to higher memory usage and slower performance. XGBoost is running on: cuda:0, while the input data is on: cpu.\n",
|
| 254 |
+
"Potential solutions:\n",
|
| 255 |
+
"- Use a data structure that matches the device ordinal in the booster.\n",
|
| 256 |
+
"- Set the device for booster before call to inplace_predict.\n",
|
| 257 |
+
"\n",
|
| 258 |
+
"This warning will only be shown once.\n",
|
| 259 |
+
"\n",
|
| 260 |
+
" warnings.warn(smsg, UserWarning)\n"
|
| 261 |
+
]
|
| 262 |
+
}
|
| 263 |
+
],
|
| 264 |
+
"source": [
|
| 265 |
+
"from xgboost import XGBClassifier, XGBRegressor\n",
|
| 266 |
+
"\n",
|
| 267 |
+
"model = XGBRegressor(n_estimators=5000,\n",
|
| 268 |
+
" learning_rate=0.02,\n",
|
| 269 |
+
" device=\"cuda\",\n",
|
| 270 |
+
" tree_method=\"hist\",\n",
|
| 271 |
+
" subsample=0.5,\n",
|
| 272 |
+
" objective='binary:logistic',\n",
|
| 273 |
+
" #colsample_bytree=0.5,\n",
|
| 274 |
+
" #reg_alpha=0,\n",
|
| 275 |
+
" #max_depth=5\n",
|
| 276 |
+
" )\n",
|
| 277 |
+
"\n",
|
| 278 |
+
"model.fit((X_train), Y_train)\n",
|
| 279 |
+
"pred1 = model.predict(X_test)\n",
|
| 280 |
+
"print((labels_test == (pred1>0.5)).sum()/labels_test.size)"
|
| 281 |
+
]
|
| 282 |
+
},
|
| 283 |
+
{
|
| 284 |
+
"cell_type": "code",
|
| 285 |
+
"execution_count": 10,
|
| 286 |
+
"id": "c283f121-e9c1-450d-8527-2334477f9346",
|
| 287 |
+
"metadata": {},
|
| 288 |
+
"outputs": [],
|
| 289 |
+
"source": [
|
| 290 |
+
"model.save_model(\"xgboost_params.json\")"
|
| 291 |
+
]
|
| 292 |
+
},
|
| 293 |
+
{
|
| 294 |
+
"cell_type": "code",
|
| 295 |
+
"execution_count": 11,
|
| 296 |
+
"id": "97c19677-00ec-4e23-8b5c-5916078c420e",
|
| 297 |
+
"metadata": {},
|
| 298 |
+
"outputs": [
|
| 299 |
+
{
|
| 300 |
+
"data": {
|
| 301 |
+
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAiwAAAGdCAYAAAAxCSikAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABbjUlEQVR4nO3deXxU5b0/8M8smZnsIQQSAmERkX2RLQYXsOYavFhFW0VqlaLVasVisVzFKra1vVhbrQu01NufW6uCVMUNsewqBJAAssi+JSRkJ9skk1nO+f0xc86cMzNZBiaz5Hzer1ckTs5MzpzM8pnv832eoxNFUQQRERFRFNNHegeIiIiIOsLAQkRERFGPgYWIiIiiHgMLERERRT0GFiIiIop6DCxEREQU9RhYiIiIKOoxsBAREVHUM0Z6B0JBEASUlZUhOTkZOp0u0rtDREREnSCKIhobG5GdnQ29vv0aSrcILGVlZcjJyYn0bhAREdEFKCkpQb9+/drdplsEluTkZADuO5ySkhLhvaELYrUC2dnu78vKgMTEyO5Pd8XjHD481uHB4xzTGhoakJOTI7+Pt6dbBBZpGCglJYWBJVYZDN7vU1L4otNVeJzDh8c6PHicu4XOtHOw6ZaIiIiiHgMLERERRT0GFiIiIop6DCxEREQU9RhYiIiIKOoxsBAREVHUY2AhIiKiqMfAQkRERFGPgYWIiIiiHgMLERERRT0GFiIiIop6DCxEREQU9RhYiGLQ/rP1eH3rKQiCGOldISIKi25xtmYirfnNJwdRdOY8xvRLw4QBPSK9O0REXY4VFqIYZG11qv4lIuruGFiIYpAgiqp/iYi6OwYWohgkta4wrhCRVjCwEMUg0VNZEVlhISKNYGAhikFSTmFeISKtYGAhikFSTuGsZiLSCgYWohgkcEiIiDSGgYUoBnlnCUV4R4iIwoSBhSgGeQsrTCxEpA0MLEQxSAosrLAQkVYwsBDFIO+05gjvCBFRmDCwEMUgQa6wMLEQkTYwsBDFIHmWUIT3g4goXBhYiGKQFFQ4rZmItIKBhSgGsYeFiLSGgYUoBonsYSEijWFgIYpBAissRKQxDCxEMYizhIhIaxhYiGKQyFlCRKQxDCxEMUgqrHCWEBFpBQMLUQxiDwsRaQ0DC1EMknIKzyVERFrBwEIUg7wr3TKxEJE2MLAQxSCerZmItIaBhSgGiaLvN0RE3dsFBZZly5Zh4MCBsFgsyM3Nxc6dO9vdftWqVRg2bBgsFgtGjx6NNWvWqH7e1NSEefPmoV+/foiPj8eIESOwfPnyC9k1Ik2QhoRYYSEirQg6sKxcuRILFizA008/jd27d2Ps2LEoKChAZWVlwO23bduG2bNn495778WePXswc+ZMzJw5EwcOHJC3WbBgAdauXYt//etfOHToEB555BHMmzcPH3/88YXfM6JujCc/JCKtCTqwvPDCC7jvvvswd+5cuRKSkJCA1157LeD2L730EqZPn46FCxdi+PDheOaZZzB+/HgsXbpU3mbbtm2YM2cOpk2bhoEDB+L+++/H2LFjO6zcEGkVKyxEpDVBBRa73Y6ioiLk5+d7b0CvR35+PgoLCwNep7CwULU9ABQUFKi2nzJlCj7++GOUlpZCFEVs2rQJR48exfXXXx/wNltbW9HQ0KD6ItISeeG4yO4GEVHYBBVYqqur4XK5kJmZqbo8MzMT5eXlAa9TXl7e4favvPIKRowYgX79+sFkMmH69OlYtmwZrrnmmoC3uWTJEqSmpspfOTk5wdwNopimHAbikBARaUVUzBJ65ZVXsH37dnz88ccoKirC888/j4ceegjr168PuP2iRYtQX18vf5WUlIR5j4kiRzkMxLxCRFphDGbjjIwMGAwGVFRUqC6vqKhAVlZWwOtkZWW1u31LSwueeOIJfPjhh5gxYwYAYMyYMdi7dy/+/Oc/+w0nAYDZbIbZbA5m14m6DWVVhWdrJiKtCKrCYjKZMGHCBGzYsEG+TBAEbNiwAXl5eQGvk5eXp9oeANatWydv73A44HA4oNerd8VgMEAQhGB2j0gTlBUWNt0SkVYEVWEB3FOQ58yZg4kTJ2Ly5Ml48cUXYbVaMXfuXADA3Xffjb59+2LJkiUAgPnz52Pq1Kl4/vnnMWPGDKxYsQK7du3Cq6++CgBISUnB1KlTsXDhQsTHx2PAgAHYsmUL3nrrLbzwwgshvKtE3YNyOX4uzU9EWhF0YJk1axaqqqqwePFilJeXY9y4cVi7dq3cWFtcXKyqlkyZMgXvvPMOnnzySTzxxBMYMmQIVq9ejVGjRsnbrFixAosWLcKdd96J2tpaDBgwAH/4wx/wwAMPhOAuEnUvIntYiEiDdGI3mGbQ0NCA1NRU1NfXIyUlJdK7QxfCagWSktzfNzUBiYmR3Z8o1mx3YsTiLwAAv7r+Msz73pDOX5nHOXx4rMODxzmmBfP+HRWzhIio80T2sBCRBjGwEMUYQbUOSwR3hIgojBhYiGKMMqNwWjMRaQUDC1GMERWz/RlXiEgrGFiIYozApfmJSIMYWIhijDKiMK8QkVYwsBDFGIFL8xORBjGwEMUY1ZBQBPeDiCicGFiIYo1qHRZGFiLSBgYWohijWiyOeYWINIKBhSjGKE94yAoLEWkFAwtRjBF48kMi0iAGFqIYIwjKCksEd4SIKIwYWIhimMgmFiLSCAYWohjDkx8SkRYxsBDFGFHVw8LEQkTawMBCFGPUK91GcEeIiMKIgYUoxqhmCbGHhYg0goGFKOawwkJE2sPAQhRjuA4LEWkRAwtRjGHTLRFpEQMLUYzhtGYi0iIGFqIYo54lxMRCRNrAwEIUY1RDQpHbDSKisGJgIYoxysDCCgsRaQUDC1GMUa29wrxCRBrBwEIUYwRWWIhIgxhYiGKMapZQBPeDiCicGFiIYoy6hyVy+0FEFE4MLEQxRlStw8LEQkTawMBCFGO4ND8RaREDC1GMUVVY2MVCRBrBwEIUY1SzhITI7QcRUTgxsBDFGGVVhRUWItIKBhaiGMNZQkSkRQwsRDGGZ2smIi1iYCGKMaqTHzKxEJFGMLAQxRiudEtEWsTAQhRjlCGF5xIiIq1gYCGKMSJ7WIhIgxhYiGKMcu0VVliISCsYWIhiDCMKEWkRAwtRjFFWVVhhISKtYGAhijEiT35IRBrEwEIUY0RWWIhIgxhYiGKMwAoLEWkQAwtRjFGd/JCBhYg0goGFKMaoKiycM0REGsHAQhRj1D0sEdwRIqIwYmAhijE8+SERaREDC1GMEVhhISINYmAhijGqCkvkdoOIKKwYWIhijKA6+SEjCxFpAwMLUYzhSrdEpEUMLEQxRjmVmSvdEpFWMLAQxRiudEtEWsTAQhRjlCGFFRYi0goGFqIYw5BCRFrEwEIUY3i2ZiLSIgYWohijjCjMK0SkFQwsRDFGEFhhISLtYWAhijFiG98TEXVnDCxEMYbTmolIixhYiGKMyKX5iUiDGFiIYox6HZbI7QcRUTgxsBDFGNXJD9nFQkQawcBCFGOUEUUQIrYbRERhdUGBZdmyZRg4cCAsFgtyc3Oxc+fOdrdftWoVhg0bBovFgtGjR2PNmjV+2xw6dAg33XQTUlNTkZiYiEmTJqG4uPhCdo+oW+NUZiLSoqADy8qVK7FgwQI8/fTT2L17N8aOHYuCggJUVlYG3H7btm2YPXs27r33XuzZswczZ87EzJkzceDAAXmbEydO4KqrrsKwYcOwefNm7Nu3D0899RQsFsuF3zOibornEiIiLdKJQU4zyM3NxaRJk7B06VIAgCAIyMnJwcMPP4zHH3/cb/tZs2bBarXi008/lS+74oorMG7cOCxfvhwAcMcddyAuLg7//Oc/L+hONDQ0IDU1FfX19UhJSbmg26AIs1qBpCT3901NQGJiZPcnii3deAx//s9RAEBWigXbn7iu81fmcQ4fHuvw4HGOacG8fwdVYbHb7SgqKkJ+fr73BvR65Ofno7CwMOB1CgsLVdsDQEFBgby9IAj47LPPcNlll6GgoAC9e/dGbm4uVq9e3eZ+tLa2oqGhQfVFpBUCKyxEpEFBBZbq6mq4XC5kZmaqLs/MzER5eXnA65SXl7e7fWVlJZqamvDss89i+vTp+M9//oNbbrkFt956K7Zs2RLwNpcsWYLU1FT5KycnJ5i7QRTTOK2ZiLQo4rOEBM80h5tvvhm//OUvMW7cODz++OO48cYb5SEjX4sWLUJ9fb38VVJSEs5dJooodVWFiYWItMEYzMYZGRkwGAyoqKhQXV5RUYGsrKyA18nKymp3+4yMDBiNRowYMUK1zfDhw/H1118HvE2z2Qyz2RzMrhN1G8q2M1ZYiEgrgqqwmEwmTJgwARs2bJAvEwQBGzZsQF5eXsDr5OXlqbYHgHXr1snbm0wmTJo0CUeOHFFtc/ToUQwYMCCY3SPSBFV9hT0sRKQRQVVYAGDBggWYM2cOJk6ciMmTJ+PFF1+E1WrF3LlzAQB33303+vbtiyVLlgAA5s+fj6lTp+L555/HjBkzsGLFCuzatQuvvvqqfJsLFy7ErFmzcM011+Daa6/F2rVr8cknn2Dz5s2huZdE3YjACgsRaVDQgWXWrFmoqqrC4sWLUV5ejnHjxmHt2rVyY21xcTH0em/hZsqUKXjnnXfw5JNP4oknnsCQIUOwevVqjBo1St7mlltuwfLly7FkyRL84he/wNChQ/H+++/jqquuCsFdJOpe1GdrZmIhIm0Ieh2WaMR1WLoBrqXQac9+fhjLt5wAACSbjdj/24LOX5nHOXx4rMODxzmmddk6LEQUeaLq5IdERNrAwEIUY1QnP4z9AikRUacwsBDFGEHRxMK8QkRawcBCFGO4ND8RaREDC1GMEcEeFiLSHgYWohgjclozEWkQAwtRjFHNEmJeISKNYGAhijHsYSEiLWJgIYoxAtdhISINYmAhijHqkx9GbDeIiMKKgYUoxvg22rLxloi0gIGFKMb45hOesZmItICBhSjG+DbassJCRFrAwEIUY3wrKqywEJEWMLAQxRjfgorIuUJEpAEMLEQxxr/pNkI7QkQURgwsRDHGN58wsBCRFjCwEMUY36ZbrnZLRFrAwEIUY3ybbBlXiEgLGFiIYoxvDwsrLESkBQwsRDHGb5YQ8woRaQADC1GM4cJxRKRFDCxEMYYVFiLSIgYWohjDWUJEpEUMLEQxxm8dlojsBRFReDGwEMUYzhIiIi1iYCGKMX4nO2ReISINYGAhijH+FZYI7QgRURgxsBDFGP+VbplYiKj7Y2AhijG+8YQVFiLSAgYWohjjOyTEheOISAsYWIhijP9KtxHaESKiMGJgIYoxXOmWiLSIgYUoxnClWyLSIgYWohjjV2GJzG4QEYUVAwtRjPENLKywEJEWMLAQxRg23RKRFjGwEMUYv5X5mViISAMYWIhijF+FJUL7QUQUTgwsRDHGd2Vb9rAQkRYwsBDFGvawEJEGMbAQxRhWWIhIixhYiGKM79mZmVeISAsYWIhijCCo/5+BhYi0gIGFKMb4zxJiYiGi7o+BhSjG+fa0EBF1RwwsRDHGf6VbJhYi6v4YWIhijP+5hCKzH0RE4cTAQhRj/KcxM7EQUffHwEIUY1hhISItYmAhijH+Jz+MyG4QEYUVAwtRjPEdEuJKt0SkBQwsRDHGN58wrxCRFjCwEMUYTmsmIi1iYCGKMX4VlsjsBhFRWDGwEMUY34oKe1iISAsYWIhijO80ZuYVItICBhaiGCOd7FCvc/8/KyxEpAUMLEQxRqqwGDyJhXGFiLSAgYUoBij7VqTv9Tqd38+IiLorBhaiKLd04zFM+sN6FNc0A/D2rMgVFuYVItIABhaiKLfxcCWqm+z49mwdAG/PisFTYeG5hIhICxhYiKKczSEA8AYVKaDo9RwSIiLtYGAhinI2pwsA4PIkFSmgSENCrLAQkRYwsBBFOZvdN7C4L5eabjlPiIi0gIGFKMrZnO4hITmweC43ssJCRBrCwEIU5WwOT4VF7mFRDwmxhYWItOCCAsuyZcswcOBAWCwW5ObmYufOne1uv2rVKgwbNgwWiwWjR4/GmjVr2tz2gQcegE6nw4svvnghu0bUrYiiKAcWQVAHFr3n2cuVbolIC4IOLCtXrsSCBQvw9NNPY/fu3Rg7diwKCgpQWVkZcPtt27Zh9uzZuPfee7Fnzx7MnDkTM2fOxIEDB/y2/fDDD7F9+3ZkZ2cHf0+IuiG7S5CHfJw+PSzeac0MLETU/QUdWF544QXcd999mDt3LkaMGIHly5cjISEBr732WsDtX3rpJUyfPh0LFy7E8OHD8cwzz2D8+PFYunSparvS0lI8/PDDePvttxEXF3dh94aom5GmNAMBmm6lkwkREWlAUIHFbrejqKgI+fn53hvQ65Gfn4/CwsKA1yksLFRtDwAFBQWq7QVBwF133YWFCxdi5MiRHe5Ha2srGhoaVF9E3VGrZzgI8FZSpJMfssJCRFoSVGCprq6Gy+VCZmam6vLMzEyUl5cHvE55eXmH2//xj3+E0WjEL37xi07tx5IlS5Camip/5eTkBHM3iGKGusLi/tfv5IfMK0SkARGfJVRUVISXXnoJb7zxBnS6zpW4Fy1ahPr6evmrpKSki/eSKDJaFBUWl6Be8VbPpfmJSEOCCiwZGRkwGAyoqKhQXV5RUYGsrKyA18nKymp3+6+++gqVlZXo378/jEYjjEYjzpw5g0cffRQDBw4MeJtmsxkpKSmqL6LuyKYKLO5/pYqK0cCl+YlIO4IKLCaTCRMmTMCGDRvkywRBwIYNG5CXlxfwOnl5eartAWDdunXy9nfddRf27duHvXv3yl/Z2dlYuHAhvvjii2DvD1G3ogosoqgKJ1KFhXmFiLTAGOwVFixYgDlz5mDixImYPHkyXnzxRVitVsydOxcAcPfdd6Nv375YsmQJAGD+/PmYOnUqnn/+ecyYMQMrVqzArl278OqrrwIAevbsiZ49e6p+R1xcHLKysjB06NCLvX9EMU1a5RZwDwkpw4ncw8Kl+YlIA4IOLLNmzUJVVRUWL16M8vJyjBs3DmvXrpUba4uLi6HXews3U6ZMwTvvvIMnn3wSTzzxBIYMGYLVq1dj1KhRobsXRN1Ui109JKScEWRgDwsRaUjQgQUA5s2bh3nz5gX82ebNm/0uu+2223Dbbbd1+vZPnz59IbtF1O20OtXTmpXhRPpcwCEhItKCiM8SIqK2qZtuRdXwj0HPdViISDsYWIiimO9Kt8psIjfdhnuniIgigIGFKIq1+FZYAjXdssJCRBrAwEIUxXynNQdqumVeISItYGAhimKqISGXOrDo2cNCRBrCwEIUxfwWjlP8zMhzCRGRhjCwEEUxZWARBBGit+DCCgsRaQoDC1EUUwYWpxC4h4WISAsYWIiimKqHxWdIiOuwEJGWMLAQRTGbUz0kJPDkh0SkUQwsRFFMfS4h7zosOp37C+C5hIhIGxhYiKKY+mzNorxInA6AZ0SIZ2smIk1gYCGKYq1+C8e5v9frdNCBQ0JEpB0MLERRrK2TH+p1OsXZmplYiKj7Y2AhimK+5xKS+1V08n/Yw0JEmsDAQhTF/M/WLFVYFD0sDCxEpAEMLERRTLXSraiYJQSdYpYQEwsRdX8MLERRShBEtPrMEhJUFRZP021E9o6IKLwYWIiilDKsAOp1WNyzhNzYdEtEWsDAQhSllMNBgDStWR4Tgo4r3RKRhjCwEEUp5bL8AOASvMM/eh17WIhIWxhYiKKUcoYQALgEwbvSLXtYiEhjGFiIopTyPEKAeh0WZQ8LKyxEpAUMLERRyndISBChaLoF9N6TCRERdXsMLERRyrfp1ikIimoKKyxEpC0MLERRqtWnh0UQ1BUWzhIiIi1hYCGKUtJ5hBJMBgC+C8cpZwlFZPeIiMKKgYUoStnkwGIE4F6HRV6GRXkuITaxEJEGMLAQRSlppdtEs7fCIoUT9ywhDgkRkXYwsBBFKafLHVjMRvfTVDmtGVCerZmJhYi6PwYWoijl9KQTs9FdYRGUPSx6QGpiYQ8LEWkBAwtRlHJ5kojJU2Fx+pz8kD0sRKQlDCxEUUqqsJgMniEhUfQuzQ/vSiyssBCRFjCwEEUp3wqLIIiqkx96e1gisHNERGHGwEIUpZwuqYfFW2ERpHKKTm5hYdMtEWkCAwtRlHIJ7llCUoVFFN2hBZAWjuO0ZiLSDgYWoijl9BkSArxVF72iwsJzCRGRFjCwEEUpl8+0ZsB9AkTA3XCrlyos4d81IqKwY2AhilLedVi8T1OHp8Ki04FnayYiTWFgIYpSvrOEAO+QkE7nrbCwxKJtTpeAH/9jB579/HCkd4WoSzGwEEUpafhHWodFeRl7WEhystqKr49X492dxZHeFaIuxcBCFKVcAYaEvE23illC4d81iiIOzzmnpHNPEXVXDCxEUUoKJ0aDXl4kTm66VfWwRGDnKGpIjxMHHwjUzTGwEEUpqcJi1Otg8CQWh6qHxb0dF47TNqk528XAQt0cAwtRlJLeiAyKwCKV/d09LFw4jryPCZcgMrxSt8bAQhSl5AqLQQeDJ5xIIUYH8GzNBEBdWZEqcETdEQMLUZSS+lUMeh30PkNCep13mpDAXktNU/auOPlgoG6MgYUoSgXqYZHK/zodKyzk5lKEFFZYqDtjYCGKUt4eFj2MUoVF8Dbd6jzzhNhrqW3KkMKpzdSdMbAQRSllhUVa1VbZdOudJRSR3aMo4VQGFqZX6sYYWIiilPRGpJwl5JKbbnXySrecGaJtTtWQECss1H0xsBBFqfbWYdHrwZVuCYC6wsK1WKg7Y2AhilLKWULewOJpupU7WHguIa3jtGbSCgYWoijV7josOsh9Lcwr2uZQDAlxWjN1ZwwsRFFKOUtI77fSrY5nayYA6gqLkxUW6sYYWIiilLKHRZrWHKjCQtqmHAZi0y11ZwwsRFFKeS4hKZw4WGEhHy7VkBAfC9R9MbAQRanAK916zyXEkx8SwAoLaQcDC1GUCjRLSLrMvdKtGyss2sZpzaQVDCxEUcrlkiosev91WDhLiDxUQ0JsuqVujIGFKEope1ikac0uRdOtjkvzE9Rna+aQEHVnDCxEUUq5Dove80xVNt3ybM0E+Exr5pAQdWMMLERRSllhMXoSizKwgGdrJqirKqywUHfGwEIUpVRna/Y5+SFUZ2tmYtEyLhxHWsHAQhSlVLOEPOHE23TrXZuFFRZtU05r5tL81J0xsBBFKW+FRQ+DZ0hIntYMZdMtE4uWKWcJ8eSH1J1dUGBZtmwZBg4cCIvFgtzcXOzcubPd7VetWoVhw4bBYrFg9OjRWLNmjfwzh8OBxx57DKNHj0ZiYiKys7Nx9913o6ys7EJ2jajbUM0S8jxTnYGmNUdk7yhacB0W0oqgA8vKlSuxYMECPP3009i9ezfGjh2LgoICVFZWBtx+27ZtmD17Nu69917s2bMHM2fOxMyZM3HgwAEAQHNzM3bv3o2nnnoKu3fvxgcffIAjR47gpptuurh7RhTDBEGUpysrV7qVzsyr1+mknlsuHKdxnNZMWhF0YHnhhRdw3333Ye7cuRgxYgSWL1+OhIQEvPbaawG3f+mllzB9+nQsXLgQw4cPxzPPPIPx48dj6dKlAIDU1FSsW7cOt99+O4YOHYorrrgCS5cuRVFREYqLiy/u3hHFKOX0VIPB268if5rmwnHkwXMJkVYEFVjsdjuKioqQn5/vvQG9Hvn5+SgsLAx4ncLCQtX2AFBQUNDm9gBQX18PnU6HtLS0gD9vbW1FQ0OD6ouoO1GW9pVna251CvJl3qX5w713FE1UTbessFA3FlRgqa6uhsvlQmZmpuryzMxMlJeXB7xOeXl5UNvbbDY89thjmD17NlJSUgJus2TJEqSmpspfOTk5wdyNLsHGRwol5WwPg2Jac1OrEwCQYDIqKix87GmZSzUkxMcCdV9RNUvI4XDg9ttvhyiK+Nvf/tbmdosWLUJ9fb38VVJSErZ9FEURj/17H579/LB8mc3hQv4LW/Dwu3vCth/UvakrLHp5aX67p8JiiTNwaX4CoO5b4bRm6s6MwWyckZEBg8GAiooK1eUVFRXIysoKeJ2srKxObS+FlTNnzmDjxo1tVlcAwGw2w2w2B7PrIVPdZMfKXe6AtLBgKAx6HUpqm3GiyoqKhtaI7BN1P8peBL3OvTy/UrwysHCekKZx4TjSiqAqLCaTCRMmTMCGDRvkywRBwIYNG5CXlxfwOnl5eartAWDdunWq7aWwcuzYMaxfvx49e/YMZrfCyuZwyd+3Ot3f2z2fcKRPv0QXS7nKrU6xSJwk3qSHjkvzE9QhhUNC1J0FVWEBgAULFmDOnDmYOHEiJk+ejBdffBFWqxVz584FANx9993o27cvlixZAgCYP38+pk6diueffx4zZszAihUrsGvXLrz66qsA3GHlhz/8IXbv3o1PP/0ULpdL7m9JT0+HyWQK1X0NCbui/NpidyHBZJRfJOwuAaIoQufz5kIULOUaLMp/JfFxhphZmr/WaocgishIikxVtLtzKIaBXBwSom4s6MAya9YsVFVVYfHixSgvL8e4ceOwdu1aubG2uLgYer23cDNlyhS88847ePLJJ/HEE09gyJAhWL16NUaNGgUAKC0txccffwwAGDdunOp3bdq0CdOmTbvAu9Y1Wh3eFwSbp6KiPvmYCJORgYUujjTbQ5od5FthcfewRP+0Zpcg4oaXvoTTJWL7E9chzhBVbXPdgqrpluU26saCDiwAMG/ePMybNy/gzzZv3ux32W233Ybbbrst4PYDBw6M+k+ISr4VFgBwONVnSzUZ+aJMF8e3wmL0rbCYFBWWsO5ZcJpsTrm363yzHb2TLRHeo+6H05pJK/jOGiRln4rUz6IMMexjoVCQe1g8FYlAQ0K6GFjptsnulL9vbnW1syVdKNXCcexhoW6MgSVIgQKL8hOOnZ9wKASkNx4pqOgDBpboHxJqsnkDi7SGDIWWqumWQ0LUjTGwBMnu8n5KbJEqLE5WWCi0lLOElP9KLCaDYqXb6H2TUoYUKwNLl3AKHBIibWBgCZK6wuLfdMsKC4WCtACYoY2mW/csoeivsChDSrOdQ0JdwenT9E/UXTGwBKlVEVhaAvSw8GypFAq+FZb2eliiuWldWWHhkFDXUFVYOK2ZujEGliAF7mHhkBCFVkfrsCSYFBWW8O5aUDgk1PWUgcXFHhbqxhhYgqSspsiBxckKC4WWt8ISeJaQxWSQv4/mHhZlSLFySKhLOFjhJY1gYAlSR7OEWllhoRDwq7B0gx4WVli6Bs8lRFrBwBIkVQ+L3XMOIQ4JUYhJa2tIJz1UTms26nWIM+gV67CEffc6rZGBpctxWnP4fFtSh4WrvkVloy3Su6JJDCxBUlVYnP49LOzSp1DwXYdFOa05Ps49HOStsETvY049JMTA0hWcqoXj+IGpK72+9RRWFZ3Fmn3nIr0rmsTAEiS7qsLCdVioa/jOElJWWKT+Fan6Es19C1bF6rZWrnQbcoIgqipsHBLqWlITOfuxIoOBJUjK4Z/WgBWW6H3zoNjRXg+LVGGxeP61OaL3MdfIlW67lNNnCMjBac1dSmoJYK9iZDCwBClQhUW1ND8fyBQC/rOEvD+TAov0r90lRO10VvXCcQwsoea77kq0Pg66C2mihfRhlcKLgSVIrQFWurVzpVsKMf91WLxPVWlIyBLnvSxaX0CVfStNHBIKOd8KC4eEupb0mt8axVXN7oyBJUj2ACvdOtjDQiEmzxKSA4v3Z/GeoGIxetdiidZhIeXJDzlLKPR8AwqHpLsWKyyRxcASpIALx7HCQiHmW2HRB+hh0et1MHmSjPRYVIqG4QFl30ozA0vI+c4K8q24UGhJM0NZYYkMBpYg2RXJOtDCcQ5WWCgE5B4WgzSt2ftUTTAZ5e/NnmpLi09gWb2nFKN/8wW2HK1q9/c4XALO1FhDss+BWHkuoS7l13TLD0xdSgoqbLqNDAaWIAU6WzN7WCjUvOuw+DfdSrODAG+1xbfCsvV4NZrtLnxzqrbd3/PbTw5i6p82Y/vJmlDstoogiKrpn1a7K6rXjIlFvkNC7GHpWtLzLFBFk7oeA0uQlIFEPluzk4GFQstvHRblkJBJ0YDbxtRmqZrR0Vj70fImAMDJqtBXWXwXinMJIj+ZhpjvLCGerblr2TitOaIYWIKkHLvk2Zqpq7R3tuZ4RYVFminU6vOJTwosHTXjNsrbhf4To7RQnPK8jWy8DS3/ISGRVawuIgii/PrOptvIYGAJUqAKCxeOo1DznyXUVmBxf+/bwyIt2NZREGlqdbi364IXYCk0JZmN8j5ztdvQkoaATIoxQ/bddo1AS1pQeDGwdEJJbTP++6Wv8OGes6oKSqvcw8KF4yi02quwSOuwAJ0ZEmr/8dhk61wl5kIoA0ui2ai6jEJDGgJSrsnDD01dQ1lVYYUlMhhYOuGrY9X47lwDPthd6tev4hJErsNCIefbwxJoaX5AGVh8hoQ6UWERRVGuxPgOKYWCNPyTZDEiyezeT652G1pSsFU2YnNqc9dQhnr2sESGseNNSHqRtbY6/R6oNoeLZ2umkPNWWKRZQm0EFqNnHRZnGz0s7bywtjoF+fd0RQ+LtA+JZiOMekF1GYWGNCSkCiyssHQJ5XOEs4Qig4GlE6Rxd2ury28WUItPYGHyplDwXYdFFVg6GBISBNE7JNTOC6vyxIRdMiRk8w4JxXkCC3tYQksKJ+ohIX5o6go21ZAQX+cjgYGlE5od7hfeplan35CPu8KiWDiOn24oBLzrsHimNSt7WALMElJ+4lNOJ26vwtJkcyi264IhIbs3sBj1Lr99o4vnVJwk06jXwSmInNrcRVRDQmy6jQgGlk5obvW+2AYKLHZOa6YQ85sl1EYPS6CF45TDLu1VWJoU4aHF3rVDQlLg4rTm0JLCidGgg9HgCSyssHQJ5XOp1eleBFGneF5S12Ng6YRmuzQk5JSnDOp17umDNoegCimssFAotLsOS8AhIUVgUQz1tFe6tto6V4m5UMohISlwMbCElhROjHod4vR62CDwNaiLKJ8jgugeejMZGVjCibOEOkFqunW4RLm3ICU+DoB/DwtXuqVQ8Jsl1EbTrTlAD0tjq7I3pb0elq5tIrQGmNZs7YJKjpaphoQ8/U7RcNLL7sj3OcKpzeHHwNIJzQFeZFMs7sDiO0uIQ0IUCu3OEjK138PSZOtcYFEOCXXFtOYmz1BqotmIRLO0cBwrLKHkVDRnGz2Lx7HpNjQEQcTxyiZ55WD/wMLX+nBjYOmEQGtHpHoqLM12ddMtKywUCp2tsFiM/ivdNrV2bvaPVdl02wVNhN4Ki4ELx3URaZaQQa9DnOcxwqbb0Pj7lyeR/8IW/LvoLAD/gMKpzeHHHpZO8K2w6HSQPzEqP80CrLBQaPj1sLTVdGvyHxJS97C03RyoCjZdUN5u9Cz7n+ypRgKssISa9DiJM+hh8AwJscISGscr3ScGPeb517cKyQpL+DGwdIJvYDEZ9PKbRoPiUyrAplsKDZdi9gfQ8ZCQcjxd2cPSXnNgUyd7XS6UsulW2ufi2paQ/x4tU05/j/MMH3LhuNCQKusNLZ7zbflUITm1OfwYWDrBd0jIbNTLL8ANLaywUOi1tw6L2egdyZWGhNrqYQHc1ROT0X/0t7GTQ0cXqlGxNH9OegIA4FhFI2wOl2otGbpw0vBPnGdas/syVlhCQWoQlz6U+ob6rqhKUvvYw9IJzT6rc5qMBvmNotGvwsIXC7p4vj0smclmDMtKxrShvVTDO4FWupXOwCxp65OgtYtnCUkr6SZbjMhOtSA90QSnIOJweWPIf5dWeac162HUS023/NAUCi1yhUU6zYXPkBArLGHHCksHRFFEs8+Ludmol8+Y6zskxAoLhYLvLCGjQY81v7gavq0oZs+QUFtNt0DbYaRREWxanQIEQVRVci6WVOlJNsdBp9NhVN9UfHm0CgdK6zEuJy1kv0fLnIoFBuM4rTmkpNNISK/xvgGF05rDjxWWDrQ6Bb8XAJNR0cPiOyTkEuRpcEQXyrfCAriHhXybZwOtdNvoMyTU1gurbwNsKJsInS5BDlFJFvfnotF9UwAAB0rrQ/Z7tI7TmruO1AogPZ/8Kiz8cBp2DCwdCLQGi8mgl5sdpfStfGPhCwZdLOmTs6GDikfgISHfCkvgF1bfYBPKYSHlPiSZpcCSCgDYz8ASMt5eJ738GsRpzaEh97C00XTLac3hx8DSgUBrsCgrLNKLvrTOBMC1WOjiBaqwBCIFltZ2mm7bqrD4BRuf7d7YegprD5zr3A77kJ4XZqNebvgd5QksRysaWU6/QC5BxK1/3Yr739oFURQV05p1iDNIs4T4gSkUmj3PjwabA6IocuG4KMAelg4ErLAY9fIbRV2LHQCQaDKg3pPEHU4BMIdvH6n78V2HpS3ySrfO9npY2mi6bXUBMATcrqS2Gb/55DskmgwoGJkV9EnepH1ItnhfYvqmxaNHQhzONztwpLwRY/qlBXWbBJw934zdxXUAgNM1zaqF46THCptuL54geHsXHS4RNofgP62ZgSXsWGHpQFtDQtK5hGqa3IHFEmeQXzBYYaGL5VL0JrRHmq3mcInym5dU3ZCyTkcVFimLKD9Blta510ux2l2osdqD3n/vDCHvonE6nQ4jst19LEcrmoK+TVIP4205Uik/TuIMernpltOaL57N6YKyFbHB5vB7HnXF6SyofQwsHWgOsDKnyahXLc0PqF8wOFOILpayN6E9ykXkpLPJSlPt0xNN7svbqLBIb3bpCdJ23hfgigab/P25OhuCJU2tTjKri7hZKfEAgMrG4G+zs0RR7LaN71IVFwC2HK2S++UMep08rZkLx108q89SFg0tDnmWULLnMc0KS/gxsHSgrSEhKbBI4ow6mDxjyKyw0MXqbA+LchE5m8O9DL9UOclIMsuXt0WvA9ISpBN5eh+3ysBSVh/86rSNilVulXqnuPepsqE16NvsDEEQcfvfC3HT0q0ormnukt8RSQ2KwFJ4skbusYvTexeOY9P/xfPtXWywOeRh11TP84UVlvBjYOmAtY2mW+lFXr7M4G0ujNYKy183H8efvzgS6d2gTujsLCGdTieHFpvDhRaHC9KIQM8kd+WkvU+CymXzlX0w5fXeQHGu7sIDi7KHBXAvgAd0XYWlsrEV35w+j/2l9Zj51604dK6hS35PpCgrLDaHgMKTNQDc6/RITbdch+Xi+VdYnHLwlz6sssISfgwsHWjxVFgSFaV3syFAhcWglyss0dj0ZnO48KcvjmDppuOobOi6cjyFRmcrLIB6anOTon8lLcBQj69kS5x3eX9FNbFCESjO1V/IkJB3WX6l3ikWAF1XYVFWhmqtdizdeLxLfk+kKAMLAJzxVJHcQ0KeCgunNV+0gBUWTwVSeu3ntObwY2DpgDQXX3qhBQIPCZmM0V1hqbHa5SaycgaWqNfZWUKAYqaQw+U9f4/ZqFhUru3HY7LF6A08igpLRb1ySOgCAou8yq1PYJErLF0fWABv83B3Ia37pPwABUjnEuK05lCx2gP0sDhZYYk0BpYOSOeT6JXknacsrcMSp5jBEacoyUZjD0ttk3emR0UXfbql0PFWWDp+iipXu21SzM6RhoraW/MkyWxUBB5FD4uiwlJ+AT0s3mnN6mDfO9kd/CsabF3SGFvhCUK9PMGo6iKDkSiK+GD3WZyqtl70voWCVGEZP6CH6nLVwnFR+PoTa3wnWzTYnH4VFgaW8GNg6YCUtHulKAKLQQ+dTqeqssQZdFFeYfG+cLPCEv2Cq7B4KylS5SI90SRf3mJ34a3C0/j1h/vxu08Oqq6blhAHs8/y/qIoqkJt2QXMEpIqAf5DQu7nUatTQIPNvz/sYknDndKqulWNrRcVjL46Vo0F732LJz7YH5L9u1j1nlOBXO5zLibl2Zod7GG5aH4VFpvDr4eFQ0Lhx4XjOiD1sPhWWAD3A7faU7lQVliisUu/RlFhYQ9L9JM+JXe0DgsAVeAoqXX3NOSkx8uVk01HKuV1T+LtNixWXLdfjwTvuVI8nyDrmh2q0F3RYINLEDsVniRNbcwSssQZkGIxosHmRFWjzW9o9WJJQ0Ijs1Ow8XAl7C4BDS1OeWZHsA6WuZt2T1ZHx7ox0iyhnPQEZCSZ5Ncfg1650m30fWCKNX49LC0OuaKSwgpLxLDC0gHpBHFSiRlQBxb5siifJVRrVQ4JMbBEu6AqLNIsIacLJec9gaVHAsyeZtoTVW0PZ/TrEa/qgQG8FbjU+DgY9Do4BRHVTcENrQRa6VYi9YN1xdCkdJs56QlI8fzuqqYLf7yfqHIHlcrG1qh4XktDQqnxcbgkI0m+PE7vbfpv4Sf/i+Y7S0g5tOgdEuJxDjcGlg5IyzMnmgxyo5v0RqAeEtIr1mGJvgdytWJIiD0s0U9ewbQzPSwm79BPSa2736RfeoIcRKTbkh6fSv16xHt7YDwvwFKgzU6Ll6chlwXZvNrWtGYAyEzpuqnN0r5npljkDxkX0+B7vNIdWEQxOoK+NNSWGh+Hwb0T5csNeh0u6eX+/+/KutdU7kiQKixS03igwNJeMzt1DQaWDkjNVwlmo3yCw0AVljijt4fF4Yy+ISF1023kX3ipfXKFpRNDQvK0ZKeAs3KFJV7uYZFMHNjD77r9eiQoTqDofgH2vumb0SfNvTJtR1ObBUFEjaIKI09rNvsPxUiNt10xtVkKJ5kpZvn3XGjjrSiKcoUFCO2Mo38XncUfPvsOQpD9JtKQUEp8HAb38lZYjAYdLu/v/vseKGvgp/+LJFVYslI9j1XPY0iv8w5z8hiHHwNLB6SVbhNMBvmBGjCwKCosrVE4hlzDIaGYEtw6LJ7HnaqHJUEOMpKJA9P9rhtoSEiqwGWlWNDH84LdUYXl/319ChN+vx7/LjoLoO2VbgHv1OZQV/panS556DMz2XLRM4WqGltV5+4JtsrUFkEQ8fRHB/B/X53Ct2frOn09URRVQ0KqwKLXY2DPBPRIiIPdKeDQucaQ7KtWtTjcf3ffwGKJM8AsP9+i73W+u2Ng6UCzvHCct8Ji9gSTVM/CXIC73B4nV1ii74GsDCznm/1P5EXRQxRFObAEM0uorM4mz27omxYvv7BKRvRJkYd/AHeYSI2PU8wyUvew9E6xINtTYemourDxcCUA4IX/HIHdKcjnM2qvhyXUQ0JSMDEZ3CtRX2xgOV6lbrS9kAX0Aimta5H/TkfKOx8sbA5Bbuj3rbAY9O5Vj6Uqy+4z50Oyr1olVVikwC49Hy1xBm9FMgpf57s7BpYOSEvzx5sM8nL8CWb/HhaTUR/V5xKqtapftLtqpdFY8/j7+/DfL32F81Y7rK1OrD1wLuIrFSuXVg9mpdtjle43v97JZvcnQZ8KS+8UM3LS4+X/z06zuJf2l6Y/ewKLNIssK8WCEX3cZ1f++lh1m79fFEUcqXD/7rJ6G1Z+Uyy/mAcMLEH0lhwpb+x04KiQg5YZOp3uogOLb7NyqIaEjlY0Kr7v/Owjqbpi0OuQaDKgbw/v37LcE6bG908DAOwpqbv4HdUwqYclKzVedbnZqFedCoPCi9OaO9CiqLA8/L0hGJSRiGlDewMIMCRk9KyDEIXJW5rWbPTM+qhosCEnPSHCexVZh8sbsOKbEgDA69tO43hlI9bsL8ftE/vhuR+Ojdh+ORWBpTMVFqnpVjpvjvR3tfhUWHonm1V/c+kNT55l5Clxn/Ys994nzYIJA3ogzqDDscomHK9sxKW9k/1+f1VTq2oW2nOK81UltjMk1NH0+iPljZjx8lcY3icFnzx8VbvbAt4hpkxPBUf6PVVBznCSnPA03KYnmlBrtYdsSOiIKrB0vsKiHA7S6XRQtjdJb6xShWVPMSssF0PuYVGscA5A9UGAFZbwY4WlA9K05niTAZMHpeN3N4+Sx+XbniXU/gO5rtmOz/efC9s0yRa7Sx7aurS3u4zcHWcK2RwuOWB2xpvbzsjf/9+XJ7FmfzkA4L1dZ7H2wLmQ719nHfN86tbrvP1S7ZnoWfVUWpMjxxNEfCssvZLN6K+osPT1DPcoh4SsrU650XRkdgpSLHG46tIMAMDnnuPjSxrW6JsWj/REk9z34V4N2n//MxXTmttb1G3tgXI4BRH7S+txrhOr7SqbhaX7C1xMhcV9HKT7H6rAclQxDHQkiMAizRBKUVStPvvFVXjm5pG4fkQmAGBMv1TodMDZ8y1yPxN52Z1CpxqdpQpLr2QzlJ8ZlBUWDquHHwNLB6QyeaLZ4Pcz35Vu5aX52wkiZ883Y+ayrXjw7d14Z8eZNrcLJWmVW5NBL0997G6NtzaHC/kvbMENL33ZqVJtfbMDq/eUAnBPXZT+ztKn8kUf7Jf7MMLtpQ3HAADfH5vtFzoCmTa0N7JTvZ8EA1VY0hLiYDYakJPunQrrF1icAg6WNUAU3WP30iybG0b3AQCsOdB+YBndNxV3XTFAvjxQdQVwV25MBj1aHC755H2BbDxSKX9feKKmze0kUgiX9vtipzVLwfHqIe7AUnq+JSSnEziiGAaqamzFeUV1qj31zd4Ki2RkdiruyhsIveddNdkShwmeKstD7+z2WwBNy05XW3HNc5twy1+3dvh3lHqMksxGDMzwPmeUs+psDoFnxg4zBpZ22J3eJreEOP8X37QEnx4WOXkHDiw1Ta24bXmhXHLffLQq1LsckFSuT080eT/ddsEaGJFUdOY8zp5vwemaZny0t7TD7Vd8U4wWhwvDspLx2A3DALhngq1+6Er0T0/A+WYHtoTp76O0/2w91h+qgF4H/OK6IZ26jkGvwx2T+8v/n9NDCizesCOt1Jyj6HvITpUCi3eW0T7PrBVpaXsA+K/hmTDodTh0rgGnA5xT57AnsAzNSsZded7A0tZic2ajAaP7uW+/qI3m0OqmVnlfAGDbiRp8sPssXlp/zO9N4nS1FXNf34kV3xQD8FZwpPtca7UH3Zd0vLIJ5Q02xBl0uHaYewjYandd9OkEnC5BHmqSjntnh4XqFVOa2/P87WPRIyEO+87W49cfHriIvY2Mc/UtnQ5xnVVrtWPuG9+gvMGGb8/WY9/Z+na3l5azSDQbsOK+K7D8x+Ox/Mfj8fxtY1XN7Jc9+TkWvLeXqwuHCQNLO1yCiBvH9MH3hvWW+wSUfIeEpBkV35yuDXh77+woxrl6GzKS3LOLdp6qDUuDp9S/0jPJJI/JVoRoxkO02Hrc2xT6xrYz7X6CsrY68eqXJwEA91w5CLMm5eCR/CFYdud4ZKfF44ZRWQCADYcq27yNrtBgc+Cx9/cBAG4e11c1C6QjsyblyP0u/dKlISHv01s6h09/RQ9Ltie8KE+euL/U/UI+pp83sPRINCF3kHtKtDQbSEl6wx2WlYyMJLNcxWvPBM8wVlEbvRabj1RBFL334T8Hy/GrVd/iL+uPYs1+73BdWV0L7vzHDmw6UoU6TwViVF93o3CPBJPctKw8NUVnrD9UAQDIG5yBjCQz0hPdz9mz55vbfXMqPFGDZZuOt1nlO1PbDLtLQHycAVdc0hOA+7G7Ymdxhz098pBQB4FlQM9E/P2uiQCA1XtLY2po6ERVE67982bcvGyr3zHcfrIGNy/bim3H224A99Voc2DBe3tx1R83qk5g+cXBwNVCiVVezsKI3ikWTB/VB9NH9UFqQpzqeeUSRHywuxTzVzK0hAMDSzviTQYs/dF4vPaTSQF7CXwDy4zRfWAy6HGwrAEHStUJXhBEvFfkbvB8bPowpCXEodnuwu4z57FqVwmOBTGWHUh9iwMLVu7FC+uOotnuhLXVKYehGkWFZUBP9xvWlqNVIf8Uc7yyCVf87wYs+fxQSG+3M7YqhgwOnWvAf76raPMF5M3C06ix2jGgZwJuGd8XcQY9Hsm/DNd6mqnzPf0AGw9XdumLkPskgzacPd+Mr49V457Xv8F35xqQkWTCo9dfFtRtZaZYsOiGYfj+2GxM8qy3oqywSMMkUqgGgP491ZUYm0PAfs8nz9H90lS3Lx2bTUfUgcUliHJgGZrlbsh9c+5kjO6bit/dPLLN/R3fzvRbQRDlUHLXFQMQZ9ChweaEVFh5ZeMxCIKILw6W47blhSita8GgjES8ec9k/OeX1+DqIb0AAHq9DhlJ/n0sNoerw76Wdd+5A8t/DXff7+w09/G75a/bcM1zm/ye3wDw0d5S/Pj/7cCfvjiCv6w7GvB2pf6VIZlJGJblDlYvbzyOxz/Yj6v+uAn/u+ZQm2Fb2XTbkcmD0nHVpRkQReCdncUdbh/IrtO1eP4/R8I6G+ZPa4/A5hBQXNuMFT77/Zd1R/FtSR1+9q+iTp89+y/rjuGD3aVotrtwSUYifvG9SwF0HFikobRArQAmgx4js1PQIyEOP582GHEGHT7bdw7vXuBxjoSS2uag+v2iBWcJXQRLnAEmox52p4A4gw49Ek34r5GZ+GzfOazaVYJRfVOx8XAF/rLuGC7vn4aS2hYkm424cUw2Nh6uxOcHyjF/xV6UN9hgNurx3A/H4OZxfdv9nX/fcgJbT9Tg2VtHIzstHqIoQhCB+Sv2YPMR9xDGG1tPoanViUSTEc/9cIw8pblnognXDc/EZZlJOFrRhD/95wj+95bRnb6/NocLW45WIW9wT6RY/F80X1x/FOUNNvx9y0lMHpiO78oa4BREPDB1MFZ+U4yvj1fjZ1MHy2+ooVLf4sB+z/DB1Mt6YcvRKvzsn0VIthjx82mX4p6rBsJsNMDhEvDpvjIs33wCADD/uiEBm0LH9++BHglxON/swK4z5+VPwqH2/H+OYumm46rLks1GvHnPZPTrEfwMrp9efYnq/9WBxf3GbVTcX+lvKA1NVDW1ysMtyiEhALh2WC/8Yc0h7DhZi2a7EwkmIwRBxMfflsLmEGCJ02NAT3dlJSc9ocNZPeMHpAFwN5022BzyvlQ1tuKRlXuw9bg7gN48ri/2ldZj56laJJmN0OncU4HzX9iCk543rZz0ePzrp7lyT45Sr2Qzyhts2HaiGlmpFizbdBzv7z6LRpsTl/dPw0+mDMRNY7Oh03k7K6ubWrHbU/mRwmu/tAQcKG2A3SmgrN6G25YX4q93jpeHi97bVYLH3t8HKWv84+tTuGVoGob57M93nplcl2UmY2iWt4KWbDai0VP5G903Fd8fm+13X4IJLADw4ysG4Ovj1XjvmxI8kj/Erx/qk2/L0OJw4bYJ/VT3H3CHxvkr9qK0rgXxJgN+Pu3STv3Oi7G7+DzWKoLEXzefwB2T+8MSZ0BZXQt2nHJXrhttTtz31i58+vBVfqs5K5232uVhwpfuGIebxmajqdWJ5VtO4kSVFb/+cD9anQJ+e9NIVb+VqhXA5P8WqdPpsPqhK6GD+/mUkWTG7z79Dv/31SnMntxf9RyLRp98W4ZfrNiDSQPSsfJnV/j97aMZA8tFSo2PQ1VjqzxDaNbEHHy27xxW7y3DDyb0w/wVe9Foc8ql9pvGZSPeZEDe4J74/EC5vEhXq1PA/BV74XSJ+MGEfvLtn6624sX1R5ESH4ehWclY8vlhAMDP/lmEKy5Jx9s7ipFgMqK6qRWWOD16Jprl9SIaW5148O3d8m31TDIjzqDHMzePwqxXt+PdncVIMhtxz5WD5BUdfdU0taK0rgWjslPx87d3Y+PhSvRKNiN/eG/sOFWLSzKS8PD3LkWyxYjPFKX6e9/cJX//2tZT8syR9Ycqcc+Vg/DUjcPbfKLc/vdCLP3pVThe1YRlm47joWmXYvyAHlj5TQnG9+8h9z9IdpysgSACgzIS8fuZo7Dw399i39l6NNqc+OPaw/j42zK8dc9kPPTObuz0vOiN6JPSZjg06N19Cx/sLsW/i85i0sD0oM5U3J5NhytxpsaKyYN6YvkWd3AyGfXomWhC3uCe+OlVl2BEdkpIfpeydK08eaf/du4XfSmsSLN9lAb3SkLftHiU1rWg8EQNrrw0A/e++Y0cLC7P6RHUMeqdbEH/9AQU1zZjb3EdrrmsF0rrWvDjf+zAqWorLHF6/PamkRjdLxW3Xt4X35yuxZMzhqOs3oaXNxzDyWorTEY97rt6EB669tKAbywA8P2xfbC/tB7Prj2MpZuOq1au3VNchz3Fe/FW4Rk898Mx8hDcuu8qIIruoaU+nj6fed+7FGkJcZhyaQZW7SrBV8eqcf8/d+HPt43F2fMt+JNnKvePcvujpqkVXxyswK8/3I/3FfvidAn4YLe7vyp3UDquvDQDWSkWjOmXij/fPhb/+OoUXt5wDM99cRjFtc3YdqIai28cKVeuGlrc+x7ow0Ig+cN7IyvFgvIGGx74ZxHunjJQrpS9vvUUfvvJdwDcr2EFI7NU191+qkZ+HXnt69O458pBsMQZ8G1JHfadrUNKfBxyB/X0e90oq2vB9pM1yB+R2en9BNyf+H+16lsAwC2X98WOkzUoq7fhuue3YPKgdHlIc0SfFFQ3teJ4ZRP+vuUkHpw2GKcrGiHVIw+U1iOzjxG9ks14q/AMmu0ujOiTIofSZEscplzaE5uPVOHtHe4wMzQzGfdd4w37ykblhACtAABUH3RmT+6PVzYeQ3FtM55cfQAHyxowZ8pA/FDxOg64X8s//rYMq/eWYkjvJPzhltFyBbCrNdudOFFpRWmd+ziLIrDzdC0+2XcON3nCsSCIeHtnMd4vOouqxlZc0isRT/z3cJyqtuJUtRV35Q0I6m/aFRhYLlKaJ7BID+ArL81ATno8SmpbcNPSrQDcbwBlnmmZd0xyN0dOGez91D5jTB/0SjLjjW2n8evV7tS//WQNyutt2FtS5zdN2qDXYX9pvRyCpCnLz946BgUjs7DvbB36pSfgja2n8H9fnZKvJ70J5V7SE7Mn98e7O4vx6pcn8c6OYrw4a5z8aVJSeKIGP3+7COebHRjVNwUHSt2fDqsaW/HuTvfw1skqK9YfqkBqfBxE0T0F9HSNFWfPtyA90d1DUOkJdNdcloH1hyrx2tZTuLx/mupTZElNM3I83+8/W4+F/96HA6X1qLHasftMHS7LTMK3Z+thNurx2k8m4cpLM3CiqgmffFuGz/adk49pTnoCVtyfB0EQ8eGeUvzvmkM4dK4B3/vzZjS2OpFkNuLBaYNxV96Adt9g/3tUHzmwfFtSh2dmjgq60uJ0Cfj2bD2+PFqFXslmtDoFPPOp+03CZNDDKYjIH56Jf8yZGNTtdpaq6badwOL7KfVyz+JjSjqdDtcO64V/bS/Gh3tK8f7us9h6vAYJJgPuuXIQfnr1oKD3b8KAHiiubcb/rjmEN7adxq7TtWiwOdE3LR5v3jNJXvPljsn9cfO4vog3GdDU6kRlgw29k824K29gu/cLAO67+hIU1zbjX9uL0WhzYmR2ChYWDMWIPilY8U0Jlm85gaIz5zFz2Vb8+baxSDYb8YfP3EOa0xVv4qP6puLZH4wBANwwKguPrNiLz/afw/wVe+Vt5l45EItvHIHyBhu2n6zFd2XeYd4Pdp9FXEoySuvcz4vvj82GJc6AwkXfk4P7A1MvwYqdxSip9Qagn771Df78w7H4/EA5tp90h8POVliMBj0evu5S/PrDA9h0pAqbjlThjkk5SEsw4e9fnpC3++3HB7H7zHlsP1WL4VnJ+O/RffDR3jL559VNrfjdp9+huKYZXyv6R5LNRrzyo8sxbWhvtDpd+P2nh7Dim2I4XCJ6JZsxfWQWDpe7XzN6J1twy+V9cXn/NByrbEJdswN2lwCTQY9D5xrw9o4zqG6yo0+qBY/fMAzbTlTjlyu/RWldCz7c422iv/OK/ki2xOEX7+7B37Ycx9qD5Th9phLSIPRtywvhsMRjWJ9k+fQED04brPpwdGfuAGw+UoWMJDOqm1rxrx1ncO9Vg2B3CThYVo/zVncly2TUB6zA+oo3GXB33kC8tOGYvK7TY+/vQ59UC668NAOFJ2rwxIf7VcNYJ6usKDpTh7zBPdFid+HQuQZcN7w3fnvTSHy0twyVjTbcnTdQfm6W1DZDr9ehb1o8ztW34N2dJdhTfB6ZKRb8fNpgHK9swvGqJgxIT0Te4J5ITzThzW2n8cGeUjTaHDhT06xqVu+ZaEKN1Y5n1xzCV0erUNnYiuqmVhxUnDiztK4FN7z0lfz/K78pwdIfXY4xPsPF4aQTQzFPL8IaGhqQmpqK+vp6pKSE5tNpZ/3pi8P4d9FZfDzvKnl2wuHyBjyyYi8Olzci0WTA5/OvQYPNgUabE3meoCKKIm5bXojqpla8/+AU9EgwYc7rO/FVgBVFrx6SgbK6FpyosmLK4J54cNpg3PPGN0g0G/GHmaPRIyEOcUZ9wKGWb07XYunG49hdfB5v3jNZ7h0QBBGbjlTi5Q3H8K2nb2Fwr0Rkp8Vj6mW9cKLKilW7SlSLmAHA4htHwCkIOFPTjLzBPbHxcCU+3lsmb/f+g3lISzBhzb5zmDUpByajHu/tKsHVQ3pheJ8UvLj+KF5cfwzpiSZcO7Q3Dpc3QBCBM8WV+O6FHwIARj36PpqM7jcivQ7wnTkYZ9AhLcHk14fwz3sny/0LkoNl9bh9eSGsdheMeh3evGcyrvSsq9EeURTx+tbTeGnDMbkUP21oL6TFu5d8H5SRhBlj+sDmcOHjvWVosDlQ3+LAySoraqx2NLQ4UNFg8zt+gDus2F0CTEY91v9yqtxL0hWG/HoNHC4R7953hfuxZ7UCSZ6hiKYmIDERLkHEDS99ieomO24c0wcPThssVxaUNhyqUFXO4gzu4zllcMfHM5AP95zFL1d+q7rs0t5JeOueyapem4slCCL+39enYDEZMHtSjqpkX15vw7x3dmOXTy/NFZek4/WfTA7YbA8ADpeABe99i0/3lWFUdip+ML4v5kwZKL8xHiyrx/1/24Ktv78ZADD8l/+G3RIPlyBi3rWX4lcFQwPe7qpdJVj4731INhuRZDEGPB3AG3MnyYtXdsbBsnq8900J3tp+BspX+x/l9seWI1UBV/A16HVwCSJmjOkjfyCQLr/qUvfr0bHKJuh1wFM3jsDhc41Yucv9Zp0aHyc/Z4IxvE8KXv/JJLlqU9XYioNl9Vj0wX6cq3fP2Prm1/lIjY/DrL9vx07P5IZ4uw2H/uJ+7Rj+y3+jxeSt+lw7tBf+7+6JfsM0DTYHDDodrliyAY02J24YlYUNhypVHw6TLUbs/01Bp/a9pqkV//WXL2FtdWJ4nxTsLalDanwc7sztj9e2noLN4W4bmDwoHdNH9cFb207jWKX/KseTB6XLVeBhWcmYPioLB0rrsf5QJcxGPX5z00i8uP5ou+topSXE4ftjsvHP7eplMzKSTEixxGFEdgoWf38Ebnplq1zhlySYDFjwX5dhVN9U/OOrk1h/qBI9E00wGfXy32DtI9cENSGgI8G8fzOwhIAoin7DG3angI/2lmJYVorfEIbyeoLoXc1UmvZc22zH7RNzMKZfKnJ6JGBMv1S0OgXsOFWL3EHp8phuksXY6RJdoH0E3C+8z3z6Hd4qDLwmzE1jszF7cn/8Zf1RjOmbil/P8B/KqbXase67ciSZ4zBjTJ9298PuFHDT0q/lqbAS5YvO8x8U4ZUd52DQ6/DufVfg1S9PoqS2GX++bSxeXH8UGzwzVQx6HaZe1gvXDe+N3EHpAVdhBYBtx6vxp/8cwT1XDgrYG9Ce+hYHnv38kFxRUko0GeBwie0uFJhsNuKay3rhRFUTDpc34ufTBssl5KmX9e7weF2sib9fj+qmVnz1P9e612cJEFgAyI2e7Y1nO1wCFn2wH9+W1KHR5sSTNw7HjWOCO55Koiii6Mx5nKhqQqtTwMjsVIzpl9qpT7Wh1Op04X8/O4TP9p9DjdWO7w3tjVd+dHmbw0wSURTR6hTa7KM4faYSAwe6q5aTF61GpWCEUa/D1se/J3+4CWTnqVoMzEhArdWOH/x1G5odLtwwKgtj+6UhM8WC74/NvqAhyi+PVmHxRwfQt0c8fpw7ANNHZWHz0Src/9Yu5KQn4L6rL8G+s/Vy8+igjER8+vBVuPMfO9Bgc2D6yCzMntwfOekJaHW68OsPD8gnuwTcHy7+9uMJmDa0F97eXozi2maMzUmFxWjA3pI6vLPTXeXqn56AjCST3P+XmWLBtUN74/tjswMGxLK6Fjy5+gAmDUzHg9MGA3A31s/+v+0Y0jsJw1MM+N2dVwAAHn1tK+6/YTQOnWvA5f3T5L6qtvzuk+/w2lZvFTojySQvwAgAp5+d0enjW93UCoNOh3iTAXe8uh17FadHmDa0F5b+aLy86KjN4cLGw5Uoq2uBTqdDk82Jv6z3NmpLPU1tGdwrEXfnDcR/vivH1uM1yEgy4YpLeuJgWYOqkvOzay7B1KG9MLBnot+HgG3Hq/G3LScwIjsFg3slQRRFXDWkl9wL5j5buRX9esSj1SHgf97/FknmODx/e2hXAWdgiWEuQYQOkBeCCpfimmacrWvGd2UN2HK0CmkJJvw4tz8mD0oPeVPWkfJG/Objg7gsMwlXDekFvQ64LFGPnAHuT4228/VYsqUYY/qlqfp5APeT6GhFExwuAdkBei26yp7i8zhQWg+bQ0BFgw1fHquSzwMzcUAPjMxOQaJnkanMFAuSzEZkp1mQmWyBXq+DKIpoanUiOcxjwF8ercK5+hbM8gxFthVYyM3hEkIXmBTHurSkEn8pLMP4/j3wo9z+HVzR61x9C5wusUtPo1Hf7ECSxSiHoK+OVeHVL0/ip1dfgqmX9WrzeqIo4tUvT+LZtYchisDjNwzDA1MHt7m9u5lVaHNBwWBJfytnQyOMqe7X/ebaOiT0CPwBMZDT1VbMePkrGPQ6/OGW0bhxTB98cbAcj72/HwUjMy/4FB0tdhc+2HMW/y46i/7pCfjjD8a02yAMAM+tPYz/9/UpPHr9Zbh1fD/846tTaLQ5kJ5owo1jsvHyhmP4bP85DOyZgPd+lofeKRaIooiqplb0SDAhzqCHzeHCk6vdQXJO3gD85qaRIXv9FkURDpfYqdW3gxHU+7d4AZYuXSoOGDBANJvN4uTJk8UdO3a0u/17770nDh06VDSbzeKoUaPEzz77TPVzQRDEp556SszKyhItFot43XXXiUePHu30/tTX14sAxPr6+gu5OxQNmppEEXB/NTVFem86JAiC+M2pGnFfSV2kdyU4MXacY5pGjvXOUzXih7vPioIgRGYHLvI4l9e3iA0tdtVlDqcrIven1eFq82dOlyB+ebRSrLPa29xG0pltokUw799BR6WVK1diwYIFePrpp7F7926MHTsWBQUFqKwMvMjWtm3bMHv2bNx7773Ys2cPZs6ciZkzZ+LAAe8KjM899xxefvllLF++HDt27EBiYiIKCgpgs3Wvxc2o+9DpdJg4ML3N4T4irZg0MB0zL+8bU9NjlTJTLH6VT6NBH5H70171wqDX4eohvZCa0HGVtjPbxKKgh4Ryc3MxadIkLF26FAAgCAJycnLw8MMP4/HHH/fbftasWbBarfj000/ly6644gqMGzcOy5cvhyiKyM7OxqOPPopf/epXAID6+npkZmbijTfewB133NHhPnWnISHN4lBFePA4hw+PdXjwOMe0YN6/g6qw2O12FBUVIT8/33sDej3y8/NRWFgY8DqFhYWq7QGgoKBA3v7UqVMoLy9XbZOamorc3Nw2b7O1tRUNDQ2qLyIiIuq+ggos1dXVcLlcyMxUr9eRmZmJ8vLASx2Xl5e3u730bzC3uWTJEqSmpspfOTk5AbcjIiKi7iG61xBuw6JFi1BfXy9/lZT4TzklIiKi7iOowJKRkQGDwYCKigrV5RUVFcjKygp4naysrHa3l/4N5jbNZjNSUlJUX0RERNR9BRVYTCYTJkyYgA0bNsiXCYKADRs2IC8vL+B18vLyVNsDwLp16+TtBw0ahKysLNU2DQ0N2LFjR5u3SURERNoS9Ao+CxYswJw5czBx4kRMnjwZL774IqxWK+bOnQsAuPvuu9G3b18sWbIEADB//nxMnToVzz//PGbMmIEVK1Zg165dePXVVwG4p4c+8sgj+P3vf48hQ4Zg0KBBeOqpp5CdnY2ZM2eG7p4SERFRzAo6sMyaNQtVVVVYvHgxysvLMW7cOKxdu1Zumi0uLoZe7y3cTJkyBe+88w6efPJJPPHEExgyZAhWr16NUaNGydv8z//8D6xWK+6//37U1dXhqquuwtq1a2GxtL18NREREWkHl+an6MC1FMKDxzl8eKzDg8c5pnXZOixEREREkcDAQkRERFGPgYWIiIiiHgMLERERRb2gZwlFI6lvmOcUimFWq/f7hgbA5YrcvnRnPM7hw2MdHjzOMU163+7M/J9uMUvo7NmzPJ8QERFRjCopKUG/fv3a3aZbBBZBEFBWVobk5GTodLqQ3nZDQwNycnJQUlLCKdMXgccxdHgsQ4PHMTR4HENDq8dRFEU0NjYiOztbtYZbIN1iSEiv13eYzC4Wz1kUGjyOocNjGRo8jqHB4xgaWjyOqampndqOTbdEREQU9RhYiIiIKOoxsHTAbDbj6aefhtlsjvSuxDQex9DhsQwNHsfQ4HEMDR7HjnWLplsiIiLq3lhhISIioqjHwEJERERRj4GFiIiIoh4DCxEREUU9BpYOLFu2DAMHDoTFYkFubi527twZ6V2Kar/5zW+g0+lUX8OGDZN/brPZ8NBDD6Fnz55ISkrCD37wA1RUVERwj6PDl19+ie9///vIzs6GTqfD6tWrVT8XRRGLFy9Gnz59EB8fj/z8fBw7dky1TW1tLe68806kpKQgLS0N9957L5qamsJ4LyKvo+P4k5/8xO/xOX36dNU2PI7AkiVLMGnSJCQnJ6N3796YOXMmjhw5otqmM8/l4uJizJgxAwkJCejduzcWLlwIp9MZzrsSUZ05jtOmTfN7TD7wwAOqbbR+HCUMLO1YuXIlFixYgKeffhq7d+/G2LFjUVBQgMrKykjvWlQbOXIkzp07J399/fXX8s9++ctf4pNPPsGqVauwZcsWlJWV4dZbb43g3kYHq9WKsWPHYtmyZQF//txzz+Hll1/G8uXLsWPHDiQmJqKgoAA2m03e5s4778TBgwexbt06fPrpp/jyyy9x//33h+suRIWOjiMATJ8+XfX4fPfdd1U/53EEtmzZgoceegjbt2/HunXr4HA4cP3118OqONFgR89ll8uFGTNmwG63Y9u2bXjzzTfxxhtvYPHixZG4SxHRmeMIAPfdd5/qMfncc8/JP+NxVBCpTZMnTxYfeugh+f9dLpeYnZ0tLlmyJIJ7Fd2efvppcezYsQF/VldXJ8bFxYmrVq2SLzt06JAIQCwsLAzTHkY/AOKHH34o/78gCGJWVpb4pz/9Sb6srq5ONJvN4rvvviuKoih+9913IgDxm2++kbf5/PPPRZ1OJ5aWloZt36OJ73EURVGcM2eOePPNN7d5HR7HwCorK0UA4pYtW0RR7Nxzec2aNaJerxfLy8vlbf72t7+JKSkpYmtra3jvQJTwPY6iKIpTp04V58+f3+Z1eBy9WGFpg91uR1FREfLz8+XL9Ho98vPzUVhYGME9i37Hjh1DdnY2LrnkEtx5550oLi4GABQVFcHhcKiO6bBhw9C/f38e03acOnUK5eXlquOWmpqK3Nxc+bgVFhYiLS0NEydOlLfJz8+HXq/Hjh07wr7P0Wzz5s3o3bs3hg4digcffBA1NTXyz3gcA6uvrwcApKenA+jcc7mwsBCjR49GZmamvE1BQQEaGhpw8ODBMO599PA9jpK3334bGRkZGDVqFBYtWoTm5mb5ZzyOXt3i5Iddobq6Gi6XS/UgAYDMzEwcPnw4QnsV/XJzc/HGG29g6NChOHfuHH7729/i6quvxoEDB1BeXg6TyYS0tDTVdTIzM1FeXh6ZHY4B0rEJ9FiUflZeXo7evXurfm40GpGens5jqzB9+nTceuutGDRoEE6cOIEnnngCN9xwAwoLC2EwGHgcAxAEAY888giuvPJKjBo1CgA69VwuLy8P+JiVfqY1gY4jAPzoRz/CgAEDkJ2djX379uGxxx7DkSNH8MEHHwDgcVRiYKGQuuGGG+Tvx4wZg9zcXAwYMADvvfce4uPjI7hnRMAdd9whfz969GiMGTMGgwcPxubNm3HddddFcM+i10MPPYQDBw6oetEoeG0dR2V/1OjRo9GnTx9cd911OHHiBAYPHhzu3YxqHBJqQ0ZGBgwGg1/Xe0VFBbKysiK0V7EnLS0Nl112GY4fP46srCzY7XbU1dWptuExbZ90bNp7LGZlZfk1gzudTtTW1vLYtuOSSy5BRkYGjh8/DoDH0de8efPw6aefYtOmTejXr598eWeey1lZWQEfs9LPtKSt4xhIbm4uAKgekzyObgwsbTCZTJgwYQI2bNggXyYIAjZs2IC8vLwI7llsaWpqwokTJ9CnTx9MmDABcXFxqmN65MgRFBcX85i2Y9CgQcjKylIdt4aGBuzYsUM+bnl5eairq0NRUZG8zcaNGyEIgvwCSP7Onj2Lmpoa9OnTBwCPo0QURcybNw8ffvghNm7ciEGDBql+3pnncl5eHvbv368KgOvWrUNKSgpGjBgRnjsSYR0dx0D27t0LAKrHpNaPoyzSXb/RbMWKFaLZbBbfeOMN8bvvvhPvv/9+MS0tTdWtTWqPPvqouHnzZvHUqVPi1q1bxfz8fDEjI0OsrKwURVEUH3jgAbF///7ixo0bxV27dol5eXliXl5ehPc68hobG8U9e/aIe/bsEQGIL7zwgrhnzx7xzJkzoiiK4rPPPiumpaWJH330kbhv3z7x5ptvFgcNGiS2tLTItzF9+nTx8ssvF3fs2CF+/fXX4pAhQ8TZs2dH6i5FRHvHsbGxUfzVr34lFhYWiqdOnRLXr18vjh8/XhwyZIhos9nk2+BxFMUHH3xQTE1NFTdv3iyeO3dO/mpubpa36ei57HQ6xVGjRonXX3+9uHfvXnHt2rVir169xEWLFkXiLkVER8fx+PHj4u9+9ztx165d4qlTp8SPPvpIvOSSS8RrrrlGvg0eRy8Glg688sorYv/+/UWTySROnjxZ3L59e6R3KarNmjVL7NOnj2gymcS+ffuKs2bNEo8fPy7/vKWlRfz5z38u9ujRQ0xISBBvueUW8dy5cxHc4+iwadMmEYDf15w5c0RRdE9tfuqpp8TMzEzRbDaL1113nXjkyBHVbdTU1IizZ88Wk5KSxJSUFHHu3LliY2NjBO5N5LR3HJubm8Xrr79e7NWrlxgXFycOGDBAvO+++/w+gPA4igGPIQDx9ddfl7fpzHP59OnT4g033CDGx8eLGRkZ4qOPPio6HI4w35vI6eg4FhcXi9dcc42Ynp4ums1m8dJLLxUXLlwo1tfXq25H68dRohNFUQxfPYeIiIgoeOxhISIioqjHwEJERERRj4GFiIiIoh4DCxEREUU9BhYiIiKKegwsREREFPUYWIiIiCjqMbAQERFR1GNgISIioqjHwEJERERRj4GFiIiIoh4DCxEREUW9/w+0a3isSa4pDAAAAABJRU5ErkJggg==",
|
| 302 |
+
"text/plain": [
|
| 303 |
+
"<Figure size 640x480 with 1 Axes>"
|
| 304 |
+
]
|
| 305 |
+
},
|
| 306 |
+
"metadata": {},
|
| 307 |
+
"output_type": "display_data"
|
| 308 |
+
}
|
| 309 |
+
],
|
| 310 |
+
"source": [
|
| 311 |
+
"plt.plot(model.feature_importances_)\n",
|
| 312 |
+
"for i in range(1,5):\n",
|
| 313 |
+
" plt.axvline(i*55, c=\"r\")\n",
|
| 314 |
+
"#plt.axhline(0,c=\"r\")\n",
|
| 315 |
+
"#plt.axvline(30, c=\"g\")\n",
|
| 316 |
+
"#plt.axvline(30+130, c=\"g\")"
|
| 317 |
+
]
|
| 318 |
+
},
|
| 319 |
+
{
|
| 320 |
+
"cell_type": "code",
|
| 321 |
+
"execution_count": 12,
|
| 322 |
+
"id": "22fb4073-ec59-4157-bef9-15902e1698d5",
|
| 323 |
+
"metadata": {},
|
| 324 |
+
"outputs": [
|
| 325 |
+
{
|
| 326 |
+
"name": "stdout",
|
| 327 |
+
"output_type": "stream",
|
| 328 |
+
"text": [
|
| 329 |
+
"(array([0.95674822, 0.95139442]), array([0.93418619, 0.96825765]), array([0.94533261, 0.95975197]), array([6488, 8632]))\n",
|
| 330 |
+
"0.9536375661375661\n"
|
| 331 |
+
]
|
| 332 |
+
}
|
| 333 |
+
],
|
| 334 |
+
"source": [
|
| 335 |
+
"import sklearn\n",
|
| 336 |
+
"pred1 = model.predict(X_test)\n",
|
| 337 |
+
"#pred=pred<0.5\n",
|
| 338 |
+
"\n",
|
| 339 |
+
"print(sklearn.metrics.precision_recall_fscore_support(labels_test, pred1>0.5))\n",
|
| 340 |
+
"print((labels_test == (pred1>0.5)).sum()/labels_test.size)"
|
| 341 |
+
]
|
| 342 |
+
}
|
| 343 |
+
],
|
| 344 |
+
"metadata": {
|
| 345 |
+
"kernelspec": {
|
| 346 |
+
"display_name": "Python 3 (ipykernel)",
|
| 347 |
+
"language": "python",
|
| 348 |
+
"name": "python3"
|
| 349 |
+
},
|
| 350 |
+
"language_info": {
|
| 351 |
+
"codemirror_mode": {
|
| 352 |
+
"name": "ipython",
|
| 353 |
+
"version": 3
|
| 354 |
+
},
|
| 355 |
+
"file_extension": ".py",
|
| 356 |
+
"mimetype": "text/x-python",
|
| 357 |
+
"name": "python",
|
| 358 |
+
"nbconvert_exporter": "python",
|
| 359 |
+
"pygments_lexer": "ipython3",
|
| 360 |
+
"version": "3.11.2"
|
| 361 |
+
}
|
| 362 |
+
},
|
| 363 |
+
"nbformat": 4,
|
| 364 |
+
"nbformat_minor": 5
|
| 365 |
+
}
|