{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":16880,"databundleVersionId":858837,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install torch torchvision transformers pillow matplotlib opencv-python pandas","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install tqdm","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport cv2\nimport torch\nimport json\nfrom tqdm import tqdm  # For progress bar\nfrom sklearn.model_selection import train_test_split  # For splitting dataset\nfrom torchvision import transforms\nfrom torch.utils.data import Dataset, DataLoader, Subset\nfrom PIL import Image\nfrom transformers import AutoImageProcessor, AutoModelForImageClassification\n\n# Paths\ntrain_videos_path = \"/kaggle/input/deepfake-detection-challenge/train_sample_videos\"  # Update this to the actual path\nmetadata_path = \"/kaggle/input/deepfake-detection-challenge/train_sample_videos/metadata.json\"  # Update this to the actual metadata.json path\n\n# Load Metadata\nwith open(metadata_path, 'r') as f:\n    metadata = json.load(f)\n\n# Dataset Class\nclass DeepfakeDataset(Dataset):\n    def __init__(self, video_dir, metadata, processor, frame_count=5, transform=None):\n        self.video_dir = video_dir\n        self.metadata = metadata\n        self.processor = processor\n        self.frame_count = frame_count\n        self.transform = transform or transforms.Compose([\n            transforms.Resize((224, 224)),\n            transforms.ToTensor()\n        ])\n        self.data = list(metadata.keys())\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        video_name = self.data[idx]\n        label = 1 if self.metadata[video_name][\"label\"] == \"FAKE\" else 0\n        video_path = os.path.join(self.video_dir, video_name)\n\n        # Extract frames from video\n        cap = cv2.VideoCapture(video_path)\n        frames = []\n        for _ in range(self.frame_count):\n            ret, frame = cap.read()\n            if not ret:\n                break\n            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)  # Convert BGR to RGB\n            frame = Image.fromarray(frame)  # Convert NumPy array to PIL image\n            frames.append(self.transform(frame))\n        cap.release()\n\n        # Pad frames if less than required (for videos with fewer frames)\n        while len(frames) < self.frame_count:\n            frames.append(torch.zeros_like(frames[0]))\n\n        # Stack frames into a 5D tensor (batch_size, num_frames, channels, height, width)\n        frames_tensor = torch.stack(frames)\n\n        # Aggregate frames by averaging across the frame dimension (dim=1)\n        aggregated_frame = frames_tensor.mean(dim=0)  # Shape: [channels, height, width]\n\n        # Process the aggregated frame to ensure it fits the model input format\n        inputs = self.processor(images=aggregated_frame, return_tensors=\"pt\", do_rescale=False)\n\n        # Ensure the shape of pixel_values is [batch_size, channels, height, width]\n        pixel_values = inputs['pixel_values'].squeeze(0)  # Remove the extra batch dimension\n\n        return pixel_values, torch.tensor(label)\n\n# Initialize Dataset and DataLoader\nprocessor = AutoImageProcessor.from_pretrained(\"Wvolf/ViT_Deepfake_Detection\")\ntrain_dataset = DeepfakeDataset(train_videos_path, metadata, processor)\n\n# Split into training and validation sets (80% train, 20% validation)\ntrain_indices, val_indices = train_test_split(range(len(train_dataset)), test_size=0.2, random_state=42)\n\ntrain_subset = Subset(train_dataset, train_indices)\nval_subset = Subset(train_dataset, val_indices)\n\ntrain_loader = DataLoader(train_subset, batch_size=64, shuffle=True)\nval_loader = DataLoader(val_subset, batch_size=64, shuffle=False)\n\n# Model Setup\nmodel = AutoModelForImageClassification.from_pretrained(\"Wvolf/ViT_Deepfake_Detection\")\nmodel.config.num_labels = 2  # Set for binary classification (REAL vs FAKE)\n\n# Training Setup\noptimizer = torch.optim.AdamW(model.parameters(), lr=5e-5)\ncriterion = torch.nn.CrossEntropyLoss()\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel.to(device)\n\n# Function to calculate accuracy\ndef calculate_accuracy(preds, labels):\n    _, predicted = torch.max(preds, 1)\n    correct = (predicted == labels).sum().item()\n    accuracy = correct / len(labels)\n    return accuracy\n\n# Validation loop\ndef evaluate(model, val_loader, criterion, device):\n    model.eval()\n    val_loss = 0.0\n    val_accuracy = 0.0\n    with torch.no_grad():\n        for pixel_values, labels in val_loader:\n            pixel_values, labels = pixel_values.to(device), labels.to(device)\n\n            # Forward pass through the model\n            outputs = model(pixel_values=pixel_values)\n            loss = criterion(outputs.logits, labels)\n\n            # Calculate accuracy\n            accuracy = calculate_accuracy(outputs.logits, labels)\n\n            # Accumulate loss and accuracy for validation\n            val_loss += loss.item()\n            val_accuracy += accuracy\n\n    # Calculate the average validation loss and accuracy\n    val_loss /= len(val_loader)\n    val_accuracy /= len(val_loader)\n    return val_loss, val_accuracy\n\n# Training Loop with Progress Bar and Epoch Display\nfor epoch in range(20):  # Number of epochs\n    model.train()\n    epoch_loss = 0.0\n    epoch_accuracy = 0.0\n    \n    # Progress bar using tqdm with epoch display\n    with tqdm(train_loader, unit=\"batch\", desc=f\"Epoch {epoch+1}\") as tepoch:\n        for pixel_values, labels in tepoch:\n            pixel_values, labels = pixel_values.to(device), labels.to(device)\n\n            # Forward pass through the model\n            outputs = model(pixel_values=pixel_values)\n            loss = criterion(outputs.logits, labels)\n            \n            # Calculate accuracy\n            accuracy = calculate_accuracy(outputs.logits, labels)\n            \n            # Backpropagation\n            optimizer.zero_grad()\n            loss.backward()\n            optimizer.step()\n\n            # Update progress bar description with loss and accuracy\n            tepoch.set_postfix(loss=loss.item(), accuracy=accuracy)\n            \n            # Accumulate loss and accuracy for the epoch\n            epoch_loss += loss.item()\n            epoch_accuracy += accuracy\n\n    # Calculate average loss and accuracy for the epoch\n    epoch_loss /= len(train_loader)\n    epoch_accuracy /= len(train_loader)\n    print(f\"Epoch {epoch+1} completed. Loss: {epoch_loss:.4f}, Accuracy: {epoch_accuracy:.4f}\")\n\n    # Evaluate on validation data\n    val_loss, val_accuracy = evaluate(model, val_loader, criterion, device)\n    print(f\"Validation Loss: {val_loss:.4f}, Validation Accuracy: {val_accuracy:.4f}\")\n\n# Save the Fine-tuned Model\nmodel.save_pretrained(\"fine_tuned_deepfake_vit\")\nprocessor.save_pretrained(\"fine_tuned_deepfake_vit\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T15:31:16.705024Z","iopub.execute_input":"2024-12-16T15:31:16.706360Z","iopub.status.idle":"2024-12-16T15:54:04.857977Z","shell.execute_reply.started":"2024-12-16T15:31:16.706301Z","shell.execute_reply":"2024-12-16T15:54:04.857024Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport cv2\nimport torch\nimport json\nfrom tqdm import tqdm  # For progress bar\nfrom torchvision import transforms\nfrom torch.utils.data import Dataset, DataLoader\nfrom PIL import Image\nfrom transformers import AutoImageProcessor, AutoModelForImageClassification\n\n# Paths\ntest_videos_path = \"/kaggle/input/deepfake-detection-challenge/test_videos\"  # Update this to the actual path\n\n# Since there is no metadata, we will create a list of video names (assuming video files are present in the test directory)\ntest_video_files = os.listdir(test_videos_path)\n\n# Dataset Class (same as before)\nclass DeepfakeDataset(Dataset):\n    def __init__(self, video_dir, video_files, processor, frame_count=5, transform=None):\n        self.video_dir = video_dir\n        self.video_files = video_files\n        self.processor = processor\n        self.frame_count = frame_count\n        self.transform = transform or transforms.Compose([\n            transforms.Resize((224, 224)),\n            transforms.ToTensor()\n        ])\n\n    def __len__(self):\n        return len(self.video_files)\n\n    def __getitem__(self, idx):\n        video_name = self.video_files[idx]\n        video_path = os.path.join(self.video_dir, video_name)\n\n        # Extract frames from video\n        cap = cv2.VideoCapture(video_path)\n        frames = []\n        for _ in range(self.frame_count):\n            ret, frame = cap.read()\n            if not ret:\n                break\n            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)  # Convert BGR to RGB\n            frame = Image.fromarray(frame)  # Convert NumPy array to PIL image\n            frames.append(self.transform(frame))\n        cap.release()\n\n        # Pad frames if less than required (for videos with fewer frames)\n        while len(frames) < self.frame_count:\n            frames.append(torch.zeros_like(frames[0]))\n\n        # Stack frames into a 5D tensor (batch_size, num_frames, channels, height, width)\n        frames_tensor = torch.stack(frames)\n\n        # Aggregate frames by averaging across the frame dimension (dim=1)\n        aggregated_frame = frames_tensor.mean(dim=0)  # Shape: [channels, height, width]\n\n        # Process the aggregated frame to ensure it fits the model input format\n        inputs = self.processor(images=aggregated_frame, return_tensors=\"pt\", do_rescale=False)\n\n        # Ensure the shape of pixel_values is [batch_size, channels, height, width]\n        pixel_values = inputs['pixel_values'].squeeze(0)  # Remove the extra batch dimension\n\n        return pixel_values, video_name  # Return video name for saving predictions later\n\n# Initialize Dataset and DataLoader for Test Data\nprocessor = AutoImageProcessor.from_pretrained(\"Wvolf/ViT_Deepfake_Detection\")\ntest_dataset = DeepfakeDataset(test_videos_path, test_video_files, processor)\n\ntest_loader = DataLoader(test_dataset, batch_size=8, shuffle=False)\n\n# Model Setup (load the trained model)\nmodel = AutoModelForImageClassification.from_pretrained(\"fine_tuned_deepfake_vit\")  # Load the fine-tuned model\nmodel.to(device)  # Ensure model is on the correct device\n\n# Test loop with Progress Bar\ndef test(model, test_loader, device):\n    model.eval()  # Set the model to evaluation mode\n    predictions = []\n    with torch.no_grad():\n        with tqdm(test_loader, unit=\"batch\") as tepoch:\n            for pixel_values, video_names in tepoch:\n                pixel_values = pixel_values.to(device)\n\n                # Forward pass through the model\n                outputs = model(pixel_values=pixel_values)\n                \n                # Get predicted class (0 or 1)\n                _, predicted = torch.max(outputs.logits, 1)\n\n                # Store predictions along with video names\n                for video_name, pred in zip(video_names, predicted):\n                    predicted_class = \"FAKE\" if pred == 1 else \"REAL\"\n                    predictions.append((video_name, predicted_class))\n                \n                # Update progress bar with batch completion\n                tepoch.set_postfix()\n\n    return predictions\n\n# Run test on the test set\npredictions = test(model, test_loader, device)\n\n# Print predictions (video name and predicted label)\nfor video_name, label in predictions:\n    print(f\"{video_name}: {label}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-16T16:14:15.427554Z","iopub.execute_input":"2024-12-16T16:14:15.427912Z","iopub.status.idle":"2024-12-16T16:15:17.398781Z","shell.execute_reply.started":"2024-12-16T16:14:15.427882Z","shell.execute_reply":"2024-12-16T16:15:17.397832Z"}},"outputs":[],"execution_count":null}]}