{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":111732,"databundleVersionId":13386980,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nfrom glob import glob\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torchvision import transforms, models\nfrom torch.utils.data import Dataset, DataLoader\n\nfrom PIL import Image\nimport pandas as pd\n\n# Конфигурация\nDATA_DIR_TRAIN = '/kaggle/input/offzone-deepfakes/train/app/hakaton/Hackaton/train/'\nDATA_DIR_TEST = '/kaggle/input/offzone-deepfakes/test/app/hakaton/Hackaton/test'\nBATCH_SIZE = 32\nIMAGE_SIZE = 224\nEPOCHS = 10\nLEARNING_RATE = 0.001\nDEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Датасет для обучения и валидации\nclass TrainDataset(Dataset):\n    def __init__(self, root_dir, label_dir, split):\n        \"\"\"\n        Args:\n            root_dir (str): Путь к папке с изображениями.\n            label_dir (str): Путь к папке с лейблами.\n            split(str): Разделение на обучающую или валидационную выборку\n        \"\"\"\n        image_paths = glob(root_dir+'*/*.png', recursive=True)\n        self.image_paths_slit = image_paths[:int(0.8*len(image_paths))] if split==\"train\" else image_paths[int(0.8*len(image_paths)):]\n        self.labels = pd.read_csv(label_dir)\n        \n        # Если нет трансформаций, задаём стандартные (ресайз + тензор)\n        self.transform = transforms.Compose([\n                transforms.Resize((224, 224)),  # Пример размера для CNN\n                transforms.ToTensor(),           # Конвертируем в тензор [0, 1]\n            ])\n\n    def __len__(self):\n        return len(self.image_paths_slit)\n\n    def __getitem__(self, idx):\n        img_path = self.image_paths_slit[idx]\n        label = self.labels[self.labels[\"folder_id\"]==int(img_path.split(\"/\")[-2])][\"df_category\"].values[0]\n        image = self.transform(Image.open(img_path).convert(\"RGB\")) \n        return image, label","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Датасет для тестирования \nclass TestDataset(Dataset):\n    def __init__(self, root_dir, label_dir):\n        \"\"\"\n        Args:\n            root_dir (str): Путь к папке с изображениями.\n            label_dir (str): Путь к папке с индексами папок.\n        \"\"\"\n        self.root =  root_dir\n        self.labels = pd.read_csv(label_dir)\n        # Если нет трансформаций, задаём стандартные (ресайз + тензор)\n        self.transform = transforms.Compose([\n                transforms.Resize((224, 224)),  # Пример размера для CNN\n                transforms.ToTensor(),           # Конвертируем в тензор [0, 1]\n            ])\n\n    def __len__(self):\n        return len(self.labels)\n\n    def __getitem__(self, idx):\n        folder_id = self.labels[\"folder_id\"][idx]\n        batch_path  = os.path.join(self.root, str(folder_id))\n        image = [self.transform(Image.open(os.path.join(batch_path,i)).convert(\"RGB\")) for i in os.listdir(batch_path)] \n        return torch.stack(image), folder_id","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    # Подготовка данных\ndef prepare_data():\n        train_dataset = TrainDataset(DATA_DIR_TRAIN, \"/kaggle/input/offzone-deepfakes/train_metadata.csv\", \"train\")\n        val_dataset = TrainDataset(DATA_DIR_TRAIN, \"/kaggle/input/offzone-deepfakes/train_metadata.csv\", \"val\")\n        test_dataset = TestDataset(DATA_DIR_TEST, \"/kaggle/input/offzone-deepfakes/submission.csv\")\n    \n        train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)\n        val_loader = DataLoader(val_dataset, batch_size=BATCH_SIZE, shuffle=False)\n        test_loader = DataLoader(test_dataset, batch_size=1, shuffle=False)\n    \n        return train_loader, val_loader, test_loader","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# Модель\ndef create_model(num_classes=1):\n    model = models.resnet18()\n    \n    # Заменяем последний слой\n    num_ftrs = model.fc.in_features\n    model.fc = nn.Sequential(\n        nn.Linear(num_ftrs, 512),\n        nn.ReLU(),\n        nn.Dropout(0.2),\n        nn.Linear(512, num_classes)\n    )\n    \n    return model.to(DEVICE)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Обучение\ndef train_model(model, train_loader, criterion, optimizer, epoch):\n    model.train()\n    running_loss = 0.0\n    correct = 0\n    total = 0\n    \n    for images, labels in train_loader:\n        images, labels = images.to(DEVICE), labels.float().to(DEVICE)\n        \n        optimizer.zero_grad()\n        outputs = model(images).squeeze()\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        \n        # Считаем accuracy\n        predicted = (outputs > 0.5).float()  \n        batch_correct = (predicted == labels).sum().item()\n        \n        running_loss += loss.item()\n        correct += batch_correct\n        total += labels.size(0)\n        \n        # Вывод статистики по батчу\n        print(f'Train Loss: {loss.item():.4f}, Accuracy: {batch_correct/labels.size(0):.2%}')\n    \n    # Вывод статистики по эпохе\n    epoch_loss = running_loss / len(train_loader)\n    epoch_acc = correct / total\n    \n    print(f'Epoch {epoch+1} Summary:')\n    print(f'Avg Loss: {epoch_loss:.4f}, Accuracy: {epoch_acc:.2%}\\n')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Валидация\ndef val_model(model, val_loader, criterion, epoch):\n    model.eval()\n    running_loss = 0.0\n    correct = 0\n    total = 0\n    with torch.no_grad():\n        for images, labels in val_loader:\n            images, labels = images.to(DEVICE), labels.float().to(DEVICE)\n            \n            outputs = model(images).squeeze()\n            loss = criterion(outputs, labels)\n            \n            # Считаем accuracy\n            predicted = (outputs > 0.5).float()  # Порог 0.5 для бинарной классификации\n            batch_correct = (predicted == labels).sum().item()\n            \n            running_loss += loss.item()\n            correct += batch_correct\n            total += labels.size(0)\n            \n            # Вывод статистики по батчу\n            print(f'Val Loss: {loss.item():.4f}, Accuracy: {batch_correct/labels.size(0):.2%}')\n    \n    # Вывод статистики по эпохе\n    epoch_loss = running_loss / len(train_loader)\n    epoch_acc = correct / total","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Тестирование\ndef test_model(model, test_loader):\n    model.eval()\n    test_labels = pd.read_csv(\"/kaggle/input/offzone-deepfakes/submission.csv\")\n    test_labels[\"df_category\"] = 0\n    with torch.no_grad():\n        for images, index in test_loader:\n            images = images.squeeze().to(DEVICE)\n            outputs = model(images).squeeze()\n            predicted = (outputs > 0.5).float()\n            mode,_ = torch.mode(predicted)\n            test_labels.loc[test_labels[\"folder_id\"]==int(index), \"df_category\"] = mode.item()\n            \n    test_labels.to_csv(\"/kaggle/working/submission.csv\",index=False, encoding='utf-8')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Подготовка данных\ntrain_loader, val_loader, test_loader = prepare_data()\n\n# Создание модели\nmodel = create_model(num_classes=1)\ncriterion = nn.BCEWithLogitsLoss()\noptimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE)\nfor epoch in range(EPOCHS):\n    train_model(model, train_loader, criterion, optimizer, epoch=epoch)\n    if epoch%2==0:\n       val_model(model, val_loader, criterion, epoch=epoch)\n\n# Тестирование\nprint('\\nTesting model...')\ntest_accuracy = test_model(model, test_loader)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}