{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "4c4eb645", "metadata": {}, "outputs": [], "source": [ "import torch\n", "print(\"CUDA Available:\", torch.cuda.is_available())\n", "print(\"CUDA Device Name:\", torch.cuda.get_device_name(0) if torch.cuda.is_available() else \"No GPU Found\")" ] }, { "cell_type": "code", "execution_count": null, "id": "bff87546", "metadata": {}, "outputs": [], "source": [ "# ViT Training Script for Digital Forensics using DFD Frame Dataset with Intel GPU (XPU)\n", "\n", "import os\n", "import glob\n", "import torch\n", "import torch.nn as nn\n", "import torch.optim as optim\n", "from torch.utils.data import Dataset, DataLoader\n", "from torchvision import transforms\n", "from PIL import Image\n", "import timm\n", "from tqdm import tqdm\n", "import random\n", "import intel_extension_for_pytorch as ipex\n", "\n", "# ----------------------------\n", "# CONFIGURATION\n", "# ----------------------------\n", "DATASET_DIR = 'frames' # Path to 'frames/real' and 'frames/fake'\n", "BATCH_SIZE = 32\n", "EPOCHS = 10\n", "LEARNING_RATE = 3e-5\n", "NUM_CLASSES = 2\n", "IMG_SIZE = 224\n", "DEVICE = 'xpu' if torch.xpu.is_available() else 'cpu'\n", "MODEL_SAVE_PATH = './vit_digital_forensics_xpu.pth'\n", "\n", "print(\"--- Starting ViT Training on Digital Forensics Frames ---\")\n", "print(\"Using device:\", DEVICE)\n", "if DEVICE == 'xpu':\n", " print(\"Intel Extension for PyTorch (IPEX) is active.\")\n", "\n", "# ----------------------------\n", "# DATASET CLASS\n", "# ----------------------------\n", "class ForgeryImageDataset(Dataset):\n", " def __init__(self, root_dir, transform=None):\n", " self.samples = []\n", " self.transform = transform\n", " for label, name in enumerate(['real', 'fake']):\n", " folder = os.path.join(root_dir, name)\n", " for img_path in glob.glob(os.path.join(folder, '*.jpg')):\n", " self.samples.append((img_path, label))\n", "\n", " real_samples = [s for s in self.samples if s[1] == 0]\n", " fake_samples = [s for s in self.samples if s[1] == 1]\n", " min_len = min(len(real_samples), len(fake_samples))\n", "\n", " self.samples = random.sample(real_samples, min_len) + random.sample(fake_samples, min_len)\n", " random.shuffle(self.samples)\n", "\n", " def __len__(self):\n", " return len(self.samples)\n", "\n", " def __getitem__(self, idx):\n", " img_path, label = self.samples[idx]\n", " image = Image.open(img_path).convert('RGB')\n", " if self.transform:\n", " image = self.transform(image)\n", " return image, label\n", "\n", "# ----------------------------\n", "# TRANSFORMS & LOADER\n", "# ----------------------------\n", "transform = transforms.Compose([\n", " transforms.Resize((IMG_SIZE, IMG_SIZE)),\n", " transforms.RandomHorizontalFlip(),\n", " transforms.RandomRotation(10),\n", " transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2),\n", " transforms.ToTensor(),\n", " transforms.Normalize([0.5]*3, [0.5]*3)\n", "])\n", "\n", "dataset = ForgeryImageDataset(DATASET_DIR, transform=transform)\n", "loader = DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=4, pin_memory=True)\n", "\n", "# ----------------------------\n", "# MODEL SETUP with IPEX Optimizations\n", "# ----------------------------\n", "model = timm.create_model('vit_base_patch16_224', pretrained=True, num_classes=NUM_CLASSES)\n", "model = model.to(memory_format=torch.channels_last)\n", "model.to(DEVICE)\n", "\n", "criterion = nn.CrossEntropyLoss()\n", "optimizer = optim.AdamW(model.parameters(), lr=LEARNING_RATE)\n", "\n", "# Apply Intel IPEX optimization\n", "model, optimizer = ipex.optimize(model, optimizer=optimizer)\n", "\n", "# Enable Automatic Mixed Precision (AMP)\n", "scaler = torch.cuda.amp.GradScaler(enabled=False) if DEVICE != 'cuda' else torch.cuda.amp.GradScaler()\n", "\n", "# ----------------------------\n", "# TRAINING LOOP\n", "# ----------------------------\n", "def train():\n", " model.train()\n", " for epoch in range(EPOCHS):\n", " total_loss, correct = 0, 0\n", " for imgs, labels in tqdm(loader, desc=f\"Epoch {epoch+1}/{EPOCHS}\"):\n", " imgs, labels = imgs.to(DEVICE, non_blocking=True), labels.to(DEVICE, non_blocking=True)\n", "\n", " optimizer.zero_grad()\n", "\n", " # AMP not yet fully supported on all XPU devices, so we avoid scaler here\n", " outputs = model(imgs)\n", " loss = criterion(outputs, labels)\n", " loss.backward()\n", " optimizer.step()\n", "\n", " total_loss += loss.item()\n", " preds = torch.argmax(outputs, dim=1)\n", " correct += (preds == labels).sum().item()\n", "\n", " acc = 100. * correct / len(dataset)\n", " print(f\"Epoch {epoch+1}: Loss={total_loss:.4f} | Accuracy={acc:.2f}%\")\n", "\n", " torch.save(model.state_dict(), MODEL_SAVE_PATH)\n", " print(f\"Model saved to {MODEL_SAVE_PATH}\")\n", "\n", "# ----------------------------\n", "# MAIN EXECUTION\n", "# ----------------------------\n", "if __name__ == '__main__':\n", " train()\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "c07737e2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", ">>> DEVICE selected: xpu\n", ">>> Intel Arc GPU is active ✅ (watch Task Manager!)\n", ">>> Loaded 20 images (10 real + 10 fake)\n", "\n", ">>> Warm‑up pass …\n", ">>> Warm‑up done.\n", "\n", ">>> Quick training run (1 epoch) …\n", "Batch loss: 2.2140\n", "Batch loss: 0.3490\n", "Batch loss: 0.0285\n", "Batch loss: 0.0046\n", "Batch loss: 0.0039\n", "Batch loss: 6.5563\n", "Batch loss: 6.2575\n", "Batch loss: 4.4933\n", "Batch loss: 2.5277\n", "Batch loss: 0.9984\n", "\n", "✅ Finished. Check GPU utilisation in TaskManager.\n" ] } ], "source": [ "\"\"\"\n", "Mini‑ViT training smoke‑test on Intel Arc (XPU)\n", "\n", "• Loads first 10 images from frames/real and frames/fake\n", "• Runs one epoch, batch size 2\n", "• Prints the device in use so you can look for GPU activity\n", "\"\"\"\n", "\n", "import os, glob, torch, random\n", "import torch.nn as nn\n", "from torch.utils.data import Dataset, DataLoader\n", "from torchvision import transforms\n", "from PIL import Image\n", "import timm # Requires timm>=0.9\n", "import intel_extension_for_pytorch as ipex # Already installed\n", "\n", "# ---------------- CONFIG ----------------\n", "ROOT_DIR = \"frames\" # frames/real and frames/fake\n", "IMG_SIZE = 224\n", "MAX_SAMPLES = 10 # ← first 10 from each class\n", "BATCH_SIZE = 2\n", "EPOCHS = 5 # just a quick smoke-test\n", "LR = 3e-5\n", "DEVICE = torch.device(\"xpu\" if torch.xpu.is_available() else \"cpu\")\n", "\n", "print(f\"\\n>>> DEVICE selected: {DEVICE}\")\n", "if DEVICE.type == \"xpu\":\n", " print(\">>> Intel Arc GPU is active ✅ (watch Task Manager!)\")\n", "else:\n", " print(\">>> Falling back to CPU ❌\")\n", "\n", "# ------------- DATASET ------------------\n", "class FirstKForgeryDataset(Dataset):\n", " def __init__(self, root, k=10, transform=None):\n", " self.items, self.transform = [], transform\n", " for label, sub in enumerate([\"real\", \"fake\"]):\n", " files = sorted(glob.glob(os.path.join(root, sub, \"*.jpg\")))[:k]\n", " self.items += [(p, label) for p in files]\n", "\n", " def __len__(self): return len(self.items)\n", "\n", " def __getitem__(self, idx):\n", " path, label = self.items[idx]\n", " img = Image.open(path).convert(\"RGB\")\n", " return (self.transform(img) if self.transform else img), label\n", "\n", "basic_tf = transforms.Compose([\n", " transforms.Resize((IMG_SIZE, IMG_SIZE)),\n", " transforms.ToTensor(),\n", " transforms.Normalize([0.5]*3, [0.5]*3),\n", "])\n", "\n", "ds = FirstKForgeryDataset(ROOT_DIR, k=MAX_SAMPLES, transform=basic_tf)\n", "dl = DataLoader(ds, batch_size=BATCH_SIZE, shuffle=False,\n", " num_workers=0, pin_memory=False)\n", "\n", "print(f\">>> Loaded {len(ds)} images ({len(ds)//2} real + {len(ds)//2} fake)\")\n", "\n", "# ------------- MODEL --------------------\n", "model = timm.create_model(\"vit_tiny_patch16_224\",\n", " pretrained=True, num_classes=2)\n", "model = model.to(memory_format=torch.channels_last).to(DEVICE)\n", "\n", "criterion = nn.CrossEntropyLoss()\n", "optimizer = torch.optim.AdamW(model.parameters(), lr=LR)\n", "model, optimizer = ipex.optimize(model, optimizer=optimizer)\n", "\n", "# ------------- WARM‑UP ------------------\n", "print(\"\\n>>> Warm‑up pass …\")\n", "with torch.no_grad():\n", " model(torch.randn(1, 3, IMG_SIZE, IMG_SIZE).to(DEVICE))\n", "print(\">>> Warm‑up done.\\n\")\n", "\n", "# ------------- TRAIN --------------------\n", "print(\">>> Quick training run (1 epoch) …\")\n", "model.train()\n", "for imgs, labels in dl:\n", " imgs, labels = imgs.to(DEVICE), labels.to(DEVICE)\n", " out = model(imgs)\n", " loss = criterion(out, labels)\n", " loss.backward()\n", " optimizer.step(); optimizer.zero_grad()\n", " print(f\"Batch loss: {loss.item():.4f}\")\n", "print(\"\\n✅ Finished. Check GPU utilisation in TaskManager.\")\n" ] }, { "cell_type": "code", "execution_count": null, "id": "e04da6d6", "metadata": {}, "outputs": [], "source": [ "import os\n", "import cv2\n", "\n", "def extract_frames_from_folder(input_folder, output_folder, label, sample_rate=30):\n", " # Ensure the input path points to the 'ViT Project' directory\n", " input_path = os.path.join(input_folder) # no need to join 'ViT Project' here, assuming it's already the root folder\n", " output_path = os.path.join(output_folder, label) # frames will be created inside the same directory as 'ViT Project'\n", " \n", " # Create the frames folder if it doesn't exist\n", " os.makedirs(output_path, exist_ok=True)\n", "\n", " for video_file in os.listdir(input_path):\n", " if not video_file.lower().endswith(('.mp4', '.mov', '.avi')):\n", " continue\n", " video_path = os.path.join(input_path, video_file)\n", " cap = cv2.VideoCapture(video_path)\n", " count, saved = 0, 0\n", " while cap.isOpened():\n", " ret, frame = cap.read()\n", " if not ret:\n", " break\n", " if count % sample_rate == 0:\n", " frame_name = f\"{video_file[:-4]}_frame_{saved:05d}.jpg\"\n", " cv2.imwrite(os.path.join(output_path, frame_name), frame)\n", " saved += 1\n", " count += 1\n", " cap.release()\n", "\n", "# Run extraction with updated directory paths\n", "extract_frames_from_folder('DFD_original sequences', 'frames', 'real')\n", "extract_frames_from_folder('DFD_manipulated_sequences', 'frames', 'fake')\n" ] }, { "cell_type": "code", "execution_count": null, "id": "1f70dea7", "metadata": {}, "outputs": [], "source": [ "import os\n", "import cv2\n", "\n", "def extract_fake_frames(sample_rate=30):\n", " input_folder = \"DFD_manipulated_sequences\"\n", " output_folder = os.path.join(\"frames\", \"fake\")\n", "\n", " # Ensure input folder exists\n", " if not os.path.exists(input_folder):\n", " raise FileNotFoundError(f\"Input folder not found: {input_folder}\")\n", "\n", " # Create output folder if it doesn't exist\n", " os.makedirs(output_folder, exist_ok=True)\n", "\n", " for video_file in os.listdir(input_folder):\n", " if not video_file.lower().endswith(('.mp4', '.mov', '.avi')):\n", " continue\n", " video_path = os.path.join(input_folder, video_file)\n", " cap = cv2.VideoCapture(video_path)\n", " count, saved = 0, 0\n", " while cap.isOpened():\n", " ret, frame = cap.read()\n", " if not ret:\n", " break\n", " if count % sample_rate == 0:\n", " frame_name = f\"{video_file[:-4]}_frame_{saved:05d}.jpg\"\n", " cv2.imwrite(os.path.join(output_folder, frame_name), frame)\n", " saved += 1\n", " count += 1\n", " cap.release()\n", "\n", "# Run extraction\n", "extract_fake_frames()\n" ] }, { "cell_type": "code", "execution_count": null, "id": "d044ac20", "metadata": {}, "outputs": [], "source": [ "import torch\n", "import openvino as ov\n", "import intel_extension_for_pytorch as ipex # Just to check if installed\n", "\n", "def check_environment():\n", " print(\"=== Environment Verification ===\")\n", " \n", " # PyTorch checks\n", " print(\"\\nPyTorch:\")\n", " print(f\"Version: {torch.__version__}\")\n", " print(f\"CUDA available: {torch.cuda.is_available()}\")\n", " print(f\"XPU available: {hasattr(torch, 'xpu') and torch.xpu.is_available()}\")\n", " \n", " # OpenVINO checks\n", " print(\"\\nOpenVINO:\")\n", " print(f\"Version: {ov.__version__}\")\n", " core = ov.Core()\n", " devices = core.available_devices\n", " print(\"Available devices:\", devices)\n", " \n", " # Intel Arc specific checks\n", " if \"GPU\" in devices:\n", " print(\"\\nIntel Arc GPU Info:\")\n", " gpu_properties = core.get_property(\"GPU\", \"FULL_DEVICE_NAME\")\n", " print(f\"GPU Name: {gpu_properties}\")\n", " print(f\"GPU Capabilities: {core.get_property('GPU', 'OPTIMIZATION_CAPABILITIES')}\")\n", " \n", " print(\"\\nRecommendations:\")\n", " if \"GPU\" not in devices:\n", " print(\"- Install latest Intel GPU drivers\")\n", " print(\"- Update OpenVINO to latest version\")\n", " else:\n", " print(\"- Environment looks good for Intel Arc GPU acceleration\")\n", "\n", "if __name__ == \"__main__\":\n", " check_environment()" ] }, { "cell_type": "code", "execution_count": null, "id": "ff95d0b0", "metadata": {}, "outputs": [], "source": [ "import os\n", "import glob\n", "import torch\n", "import torch.nn as nn\n", "import torch.optim as optim\n", "from torch.utils.data import Dataset, DataLoader\n", "from torchvision import transforms\n", "from PIL import Image\n", "import timm\n", "from tqdm import tqdm\n", "import random\n", "import numpy as np\n", "from openvino.runtime import Core, serialize\n", "from openvino.tools.mo import convert_model\n", "\n", "# ----------------------------\n", "# CONFIGURATION (Reduced for testing)\n", "# ----------------------------\n", "DATASET_DIR = 'frames'\n", "BATCH_SIZE = 16 # Reduced from 32\n", "EPOCHS = 5 # Reduced from 10\n", "LEARNING_RATE = 3e-5\n", "NUM_CLASSES = 2\n", "IMG_SIZE = 224\n", "MODEL_SAVE_PT = './vit_model.pth'\n", "MODEL_SAVE_OV = './vit_model.xml'\n", "\n", "# Initialize OpenVINO Core (simplified)\n", "core = Core()\n", "\n", "# ----------------------------\n", "# SIMPLIFIED DATASET CLASS\n", "# ----------------------------\n", "class SimpleDataset(Dataset):\n", " def __init__(self, root_dir, transform=None, max_samples=1000):\n", " self.samples = []\n", " self.transform = transform\n", " for label, name in enumerate(['real', 'fake']):\n", " folder = os.path.join(root_dir, name)\n", " for img_path in glob.glob(os.path.join(folder, '*.jpg'))[:max_samples//2]:\n", " self.samples.append((img_path, label))\n", " random.shuffle(self.samples)\n", "\n", " def __len__(self):\n", " return len(self.samples)\n", "\n", " def __getitem__(self, idx):\n", " img_path, label = self.samples[idx]\n", " image = Image.open(img_path).convert('RGB')\n", " if self.transform:\n", " image = self.transform(image)\n", " return image, label\n", "\n", "# ----------------------------\n", "# OPTIMIZED TRANSFORMS\n", "# ----------------------------\n", "transform = transforms.Compose([\n", " transforms.Resize((IMG_SIZE, IMG_SIZE)),\n", " transforms.ToTensor(),\n", " transforms.Normalize([0.5]*3, [0.5]*3)\n", "])\n", "\n", "# ----------------------------\n", "# DEBUGGING TRAINING LOOP\n", "# ----------------------------\n", "def debug_train():\n", " # 1. Test dataset loading\n", " print(\"Testing dataset loading...\")\n", " test_dataset = SimpleDataset(DATASET_DIR, transform, max_samples=100)\n", " test_loader = DataLoader(test_dataset, batch_size=4, shuffle=False)\n", " \n", " # Try loading a single batch\n", " try:\n", " test_batch = next(iter(test_loader))\n", " print(\"Successfully loaded batch of shape:\", test_batch[0].shape)\n", " except Exception as e:\n", " print(f\"Dataset loading failed: {str(e)}\")\n", " return\n", "\n", " # 2. Test model creation\n", " print(\"\\nTesting model creation...\")\n", " try:\n", " model = timm.create_model('vit_tiny_patch16_224', pretrained=True, num_classes=NUM_CLASSES) # Smaller model\n", " print(\"Model created successfully\")\n", " except Exception as e:\n", " print(f\"Model creation failed: {str(e)}\")\n", " return\n", "\n", " # 3. Test basic forward pass\n", " print(\"\\nTesting forward pass...\")\n", " try:\n", " device = torch.device(\"cpu\") # Force CPU for debugging\n", " model = model.to(device)\n", " outputs = model(test_batch[0].to(device))\n", " print(\"Forward pass successful. Output shape:\", outputs.shape)\n", " except Exception as e:\n", " print(f\"Forward pass failed: {str(e)}\")\n", " return\n", "\n", " # 4. Test training step\n", " print(\"\\nTesting training step...\")\n", " try:\n", " optimizer = optim.AdamW(model.parameters(), lr=LEARNING_RATE)\n", " criterion = nn.CrossEntropyLoss()\n", " \n", " optimizer.zero_grad()\n", " loss = criterion(outputs, test_batch[1].to(device))\n", " loss.backward()\n", " optimizer.step()\n", " print(\"Training step completed successfully. Loss:\", loss.item())\n", " except Exception as e:\n", " print(f\"Training step failed: {str(e)}\")\n", " return\n", "\n", " print(\"\\nAll tests passed! You can now run full training.\")\n", "\n", "# ----------------------------\n", "# MAIN EXECUTION\n", "# ----------------------------\n", "if __name__ == '__main__':\n", " print(\"Running diagnostic tests...\")\n", " debug_train()\n", " \n", " # Only proceed if debugging succeeds\n", " if input(\"\\nProceed with full training? (y/n): \").lower() == 'y':\n", " from tqdm.auto import tqdm # Use the more reliable auto version\n", " \n", " # Full training setup\n", " dataset = SimpleDataset(DATASET_DIR, transform)\n", " loader = DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=0)\n", " \n", " model = timm.create_model('vit_tiny_patch16_224', pretrained=True, num_classes=NUM_CLASSES)\n", " device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", " model = model.to(device)\n", " \n", " criterion = nn.CrossEntropyLoss()\n", " optimizer = optim.AdamW(model.parameters(), lr=LEARNING_RATE)\n", " \n", " # Simple training loop with progress monitoring\n", " for epoch in range(EPOCHS):\n", " model.train()\n", " pbar = tqdm(loader, desc=f\"Epoch {epoch+1}/{EPOCHS}\")\n", " for imgs, labels in pbar:\n", " imgs, labels = imgs.to(device), labels.to(device)\n", " \n", " optimizer.zero_grad()\n", " outputs = model(imgs)\n", " loss = criterion(outputs, labels)\n", " loss.backward()\n", " optimizer.step()\n", " \n", " pbar.set_postfix(loss=loss.item())" ] }, { "cell_type": "code", "execution_count": null, "id": "57287685", "metadata": {}, "outputs": [], "source": [ "from openvino.runtime import Core\n", "core = Core()\n", "print(\"Available devices:\", core.available_devices)\n", "\n", "# Check GPU specifically\n", "if \"GPU\" in core.available_devices:\n", " print(\"GPU device name:\", core.get_property(\"GPU\", \"FULL_DEVICE_NAME\"))\n", " print(\"GPU capabilities:\", core.get_property(\"GPU\", \"OPTIMIZATION_CAPABILITIES\"))\n", "else:\n", " print(\"GPU not detected by OpenVINO\")" ] }, { "cell_type": "code", "execution_count": 1, "id": "637d217a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Dataset split complete.\n" ] } ], "source": [ "import os\n", "import shutil\n", "import random\n", "\n", "def split_data(source_dir, train_dir, val_dir, split_ratio=0.8):\n", " random.seed(42) # For reproducibility\n", " classes = ['real', 'fake']\n", "\n", " for cls in classes:\n", " src_path = os.path.join(source_dir, cls)\n", " files = os.listdir(src_path)\n", " random.shuffle(files)\n", "\n", " split = int(split_ratio * len(files))\n", " train_files = files[:split]\n", " val_files = files[split:]\n", "\n", " os.makedirs(os.path.join(train_dir, cls), exist_ok=True)\n", " os.makedirs(os.path.join(val_dir, cls), exist_ok=True)\n", "\n", " for f in train_files:\n", " shutil.copy(os.path.join(src_path, f), os.path.join(train_dir, cls, f))\n", "\n", " for f in val_files:\n", " shutil.copy(os.path.join(src_path, f), os.path.join(val_dir, cls, f))\n", "\n", "# Run it with your paths\n", "source_dir = \"frames\"\n", "train_dir = os.path.join(source_dir, 'train')\n", "val_dir = os.path.join(source_dir, 'val')\n", "\n", "split_data(source_dir, train_dir, val_dir)\n", "print(\"Dataset split complete.\")\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.11" } }, "nbformat": 4, "nbformat_minor": 5 }