{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":75344,"databundleVersionId":8300769,"sourceType":"competition"}],"dockerImageVersionId":30698,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport numpy as np # linear algebra\nimport torch\nfrom torch import nn\nfrom torch.utils.data import Dataset, DataLoader\n\nimport torchaudio\n        \ntrain_path = \"/kaggle/input/deepfake-detection-ufg/audios/train/\"\ntest_path = \"/kaggle/input/deepfake-detection-ufg/audios/test/\"\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-04-23T14:00:48.377014Z","iopub.execute_input":"2024-04-23T14:00:48.377720Z","iopub.status.idle":"2024-04-23T14:00:52.429098Z","shell.execute_reply.started":"2024-04-23T14:00:48.377676Z","shell.execute_reply":"2024-04-23T14:00:52.428215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Dataset para o treinamento","metadata":{}},{"cell_type":"code","source":"class AudioDataset(Dataset):\n    def __init__(self, data_dir):\n        self.data_dir = data_dir\n        self.classes = [\"real\", \"fake\"]\n        self.audio_files = []\n        self.labels = []\n\n        for class_idx, class_name in enumerate(self.classes):\n            class_dir = os.path.join(data_dir, class_name)\n            for file in os.listdir(class_dir):\n                if file.endswith(\".mp3\"):\n                    self.audio_files.append(os.path.join(class_dir, file))\n                    self.labels.append(class_idx)\n\n        self.mel_spectrogram = torchaudio.transforms.MelSpectrogram(\n            sample_rate=TARGET_SAMPLE_RATE, n_fft=1024, hop_length=512, n_mels=64\n        )\n\n    def __len__(self):\n        return len(self.audio_files)\n\n    def __getitem__(self, idx):\n        audio_file = self.audio_files[idx]\n        label = self.labels[idx]\n\n        # Load audio\n        audio, sr = torchaudio.load(audio_file)\n        # Convert to mono\n        if audio.shape[0] > 1:\n            audio = torch.mean(audio, dim=0).unsqueeze(0)\n\n        if sr != TARGET_SAMPLE_RATE:\n            audio = torchaudio.transforms.Resample(sr, TARGET_SAMPLE_RATE)(audio)\n\n        # Pad or truncate the audio to a fixed length\n        fixed_length = (\n            TARGET_SAMPLE_RATE * 3\n        )  # Adjust this value based on your requirements\n        if audio.shape[1] < fixed_length:\n            audio = torch.nn.functional.pad(audio, (0, fixed_length - audio.shape[1]))\n        else:\n            audio = audio[:, :fixed_length]\n\n        audio = self.mel_spectrogram(audio)\n\n        return audio, label","metadata":{"execution":{"iopub.status.busy":"2024-04-23T13:28:31.795398Z","iopub.execute_input":"2024-04-23T13:28:31.795887Z","iopub.status.idle":"2024-04-23T13:28:31.809169Z","shell.execute_reply.started":"2024-04-23T13:28:31.795858Z","shell.execute_reply":"2024-04-23T13:28:31.808030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Dataset para inferência no conjunto de testes","metadata":{}},{"cell_type":"code","source":"class TestDataset(Dataset):\n    def __init__(self, data_dir):\n        self.data_dir = data_dir\n        self.audio_files = []\n\n        for file in os.listdir(data_dir):\n            if file.endswith(\".mp3\"):\n                self.audio_files.append(os.path.join(data_dir, file)) \n\n        self.mel_spectrogram = torchaudio.transforms.MelSpectrogram(\n            sample_rate=TARGET_SAMPLE_RATE, n_fft=1024, hop_length=512, n_mels=64\n        )\n\n    def __len__(self):\n        return len(self.audio_files)\n\n    def __getitem__(self, idx):\n        audio_file = self.audio_files[idx]\n\n        audio, sr = torchaudio.load(audio_file)\n        if audio.shape[0] > 1:\n            audio = torch.mean(audio, dim=0).unsqueeze(0)\n\n        if sr != TARGET_SAMPLE_RATE:\n            audio = torchaudio.transforms.Resample(sr, TARGET_SAMPLE_RATE)(audio)\n\n        fixed_length = TARGET_SAMPLE_RATE * 3\n        if audio.shape[1] < fixed_length:\n            audio = torch.nn.functional.pad(audio, (0, fixed_length - audio.shape[1]))\n        else:\n            audio = audio[:, :fixed_length]\n\n        audio = self.mel_spectrogram(audio)\n\n        return audio, audio_file","metadata":{"execution":{"iopub.status.busy":"2024-04-23T13:39:12.837592Z","iopub.execute_input":"2024-04-23T13:39:12.838876Z","iopub.status.idle":"2024-04-23T13:39:12.848738Z","shell.execute_reply.started":"2024-04-23T13:39:12.838834Z","shell.execute_reply":"2024-04-23T13:39:12.847833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Modelo","metadata":{}},{"cell_type":"code","source":"class CNNNetwork(nn.Module):\n    def __init__(self):\n        super().__init__()\n        # 4 conv blocks -> flatten -> 1 dense layer (linear) -> output\n        self.conv1 = nn.Sequential(\n            nn.Conv2d(\n                in_channels=1, out_channels=16, kernel_size=3, stride=1, padding=2\n            ),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2),\n        )\n        self.conv2 = nn.Sequential(\n            nn.Conv2d(\n                in_channels=16, out_channels=32, kernel_size=3, stride=1, padding=2\n            ),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2),\n        )\n        self.conv3 = nn.Sequential(\n            nn.Conv2d(\n                in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=2\n            ),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2),\n        )\n        self.conv4 = nn.Sequential(\n            nn.Conv2d(\n                in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=2\n            ),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2),\n        )\n        self.flatten = nn.Flatten()\n        self.linear = nn.Linear(128 * 5 * 7, 2)\n        self.log_softmax = nn.LogSoftmax(dim=1)\n\n    def forward(self, input_data):\n        x = input_data\n        x = self.conv1(x)\n        x = self.conv2(x)\n        x = self.conv3(x)\n        x = self.conv4(x)\n        x = self.flatten(x)\n        x = self.linear(x)\n        output = self.log_softmax(x)\n\n        return output","metadata":{"execution":{"iopub.status.busy":"2024-04-23T13:28:34.533930Z","iopub.execute_input":"2024-04-23T13:28:34.534550Z","iopub.status.idle":"2024-04-23T13:28:34.545587Z","shell.execute_reply.started":"2024-04-23T13:28:34.534518Z","shell.execute_reply":"2024-04-23T13:28:34.544535Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Treinamento","metadata":{}},{"cell_type":"code","source":"TARGET_SAMPLE_RATE = 16000\n\nnum_epochs = 10\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2024-04-23T13:44:19.946593Z","iopub.execute_input":"2024-04-23T13:44:19.947335Z","iopub.status.idle":"2024-04-23T13:44:19.951830Z","shell.execute_reply.started":"2024-04-23T13:44:19.947303Z","shell.execute_reply":"2024-04-23T13:44:19.950794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef train():\n    # Usage\n    dataset = AudioDataset(train_path)\n    dataloader = DataLoader(dataset, batch_size=32, shuffle=True)\n\n    from torch.optim import Adam\n\n    # Create model, loss function, and optimizer\n    model = CNNNetwork()\n    criterion = nn.NLLLoss()\n    optimizer = Adam(model.parameters(), lr=0.001)\n\n    # Training loop\n    print(device)\n    model.to(device)\n\n    for epoch in range(num_epochs):\n        model.train()\n        running_loss = 0.0\n        running_acc = 0.0\n\n        for audio, labels in dataloader:\n            audio = audio.to(device)\n            labels = labels.to(device).long()\n\n            optimizer.zero_grad()\n            outputs = model(audio)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            optimizer.step()\n\n            running_loss += loss.item()\n            running_acc += (outputs.argmax(1) == labels).sum().item()\n\n        epoch_loss = running_loss / len(dataloader)\n        epoch_acc = running_acc / len(dataset)\n\n        print(\n            f\"Epoch [{epoch+1}/{num_epochs}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_acc:.4f}\"\n        )\n    torch.save(model.state_dict(), \"model.pth\")","metadata":{"execution":{"iopub.status.busy":"2024-04-23T13:28:35.762853Z","iopub.execute_input":"2024-04-23T13:28:35.763233Z","iopub.status.idle":"2024-04-23T13:28:35.773900Z","shell.execute_reply.started":"2024-04-23T13:28:35.763205Z","shell.execute_reply":"2024-04-23T13:28:35.772532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train()","metadata":{"execution":{"iopub.status.busy":"2024-04-23T13:28:37.130769Z","iopub.execute_input":"2024-04-23T13:28:37.131148Z","iopub.status.idle":"2024-04-23T13:35:21.066975Z","shell.execute_reply.started":"2024-04-23T13:28:37.131109Z","shell.execute_reply":"2024-04-23T13:35:21.066009Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Carregar o modelo, caso já tenha treinado e queira continuar daqui","metadata":{}},{"cell_type":"code","source":"model = CNNNetwork()\nmodel.load_state_dict(torch.load(\"model.pth\"))\nmodel.eval()\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel.to(device)","metadata":{"execution":{"iopub.status.busy":"2024-04-23T13:45:19.925484Z","iopub.execute_input":"2024-04-23T13:45:19.926329Z","iopub.status.idle":"2024-04-23T13:45:19.941241Z","shell.execute_reply.started":"2024-04-23T13:45:19.926296Z","shell.execute_reply":"2024-04-23T13:45:19.940439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = TestDataset(test_path)\ntest_dataloader = DataLoader(test_dataset, batch_size=32, shuffle=False)\n\nresults = []\n\nwith torch.no_grad():\n    for audio, audio_file in test_dataloader:\n        audio = audio.to(device)\n        outputs = model(audio)\n\n        _, preds = torch.max(outputs, 1)\n\n        for i in range(len(outputs)):\n            results.append((audio_file[i], torch.exp(outputs[i][1]).item()))\n\nwith open(\"submission.csv\", \"w\") as f:\n    f.write(\"filename,fake_prob\\n\")\n    for result in results:\n        f.write(result[0].split(\"/\")[-1] + \",\" + str(result[1]) + \"\\n\")\n","metadata":{"execution":{"iopub.status.busy":"2024-04-23T13:45:24.191276Z","iopub.execute_input":"2024-04-23T13:45:24.191848Z","iopub.status.idle":"2024-04-23T13:45:48.559564Z","shell.execute_reply.started":"2024-04-23T13:45:24.191818Z","shell.execute_reply":"2024-04-23T13:45:48.558634Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}