{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":28755,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session\n\n# Use the kagglehub client library to attach Kaggle resources like competitions, datasets, and models to your session\n# Learn more about kagglehub: https://github.com/Kaggle/kagglehub/blob/main/README.md\n\nimport kagglehub\n# kagglehub.dataset_download('<owner>/<dataset-slug>')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-08-05T14:19:06.646949Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install timm -q\nimport torch\nprint(torch.cuda.is_available())  # True আসলে Ready ✅","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ── Import ──────────────────────────────────────\nimport os, torch, timm\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom PIL import Image\nimport torch.nn.functional as F\nfrom sklearn.metrics import accuracy_score, f1_score, roc_auc_score\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(f'Device: {device}')\n\n# ── Transform ────────────────────────────────────\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.5]*3, [0.5]*3)\n])\n\n# ── Dataset Class ────────────────────────────────\nclass DeepfakeDataset(Dataset):\n    def __init__(self, real_dir, fake_dir, transform=None):\n        self.data, self.transform = [], transform\n        for f in os.listdir(real_dir):\n            if f.endswith(('.jpg','.png')):\n                self.data.append((os.path.join(real_dir, f), 0))\n        for f in os.listdir(fake_dir):\n            if f.endswith(('.jpg','.png')):\n                self.data.append((os.path.join(fake_dir, f), 1))\n    def __len__(self): return len(self.data)\n    def __getitem__(self, i):\n        p, l = self.data[i]\n        img = Image.open(p).convert('RGB')\n        return (self.transform(img) if self.transform else img), l\n\nprint('Common code ready ✅')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nprint(os.listdir('/kaggle/input/'))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# DFDC path check\ndfdc = '/kaggle/input/competitions/deepfake-detection-challenge'\nceleb = '/kaggle/input/datasets'\n\nprint(\"=== DFDC ===\")\nprint(os.listdir(dfdc))\n\nprint(\"\\n=== Celeb-DF ===\")\nprint(os.listdir(celeb))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# DFDC এর ভেতরে\nprint(\"=== DFDC train_sample_videos ===\")\nprint(os.listdir('/kaggle/input/competitions/deepfake-detection-challenge/train_sample_videos')[:5])\n\n# Celeb এর ভেতরে\nprint(\"\\n=== Celeb ভেতরে ===\")\nprint(os.listdir('/kaggle/input/datasets/pranabr0y'))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# Celeb এর একদম ভেতরে\nceleb_path = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset'\nprint(\"=== Celeb folders ===\")\nprint(os.listdir(celeb_path))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nceleb_v2 = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2'\nprint(os.listdir(celeb_v2))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\ntrain = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Train'\nprint(os.listdir(train))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import timm\nimport torch.nn as nn\n\n# EfficientNet-B4 (Mehedi-র model)\nmodel = timm.create_model('efficientnet_b4', pretrained=True)\nmodel.classifier = nn.Linear(model.classifier.in_features, 2)\nmodel = model.to(device)\nprint(\"EfficientNet-B4 ready ✅\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import timm\nimport torch\nimport torch.nn as nn\n\n# Device\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# EfficientNet-B4\nmodel = timm.create_model('efficientnet_b4', pretrained=True)\nmodel.classifier = nn.Linear(model.classifier.in_features, 2)\nmodel = model.to(device)\nprint(f\"Device: {device}\")\nprint(\"EfficientNet-B4 ready ✅\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom PIL import Image\nimport torch.optim as optim\nimport os\n\n# Transform\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.5]*3, [0.5]*3)\n])\n\n# Dataset Class\nclass DeepfakeDataset(Dataset):\n    def __init__(self, real_dir, fake_dir, transform=None):\n        self.data, self.transform = [], transform\n        for f in os.listdir(real_dir):\n            if f.endswith(('.jpg','.png')):\n                self.data.append((os.path.join(real_dir, f), 0))\n        for f in os.listdir(fake_dir):\n            if f.endswith(('.jpg','.png')):\n                self.data.append((os.path.join(fake_dir, f), 1))\n    def __len__(self): return len(self.data)\n    def __getitem__(self, i):\n        p, l = self.data[i]\n        img = Image.open(p).convert('RGB')\n        return (self.transform(img) if self.transform else img), l\n\n# Celeb-DF v2 paths\nREAL = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Train/real'\nFAKE = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Train/fake'\n\n# DataLoader\ndataset = DeepfakeDataset(REAL, FAKE, transform)\ntrain_size = int(0.8 * len(dataset))\nval_size   = len(dataset) - train_size\ntrain_ds, val_ds = torch.utils.data.random_split(\n    dataset, [train_size, val_size],\n    generator=torch.Generator().manual_seed(42)\n)\ntrain_loader = DataLoader(train_ds, batch_size=16, shuffle=True)\nval_loader   = DataLoader(val_ds,   batch_size=16, shuffle=False)\n\nprint(f\"Train: {train_size} images\")\nprint(f\"Val:   {val_size} images\")\nprint(\"DataLoader ready ✅\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.nn as nn\nimport torch.optim as optim\n\n# Loss + Optimizer\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=1e-4)\n\n# Train Function\ndef train_model(epochs=10):\n    best_acc = 0\n    for ep in range(epochs):\n        # Training\n        model.train()\n        correct, total = 0, 0\n        for imgs, labels in train_loader:\n            imgs, labels = imgs.to(device), labels.to(device)\n            optimizer.zero_grad()\n            out  = model(imgs)\n            loss = criterion(out, labels)\n            loss.backward()\n            optimizer.step()\n            correct += (out.argmax(1)==labels).sum().item()\n            total   += labels.size(0)\n        train_acc = 100*correct/total\n\n        # Validation\n        model.eval()\n        v_correct, v_total = 0, 0\n        with torch.no_grad():\n            for imgs, labels in val_loader:\n                imgs, labels = imgs.to(device), labels.to(device)\n                v_correct += (model(imgs).argmax(1)==labels).sum().item()\n                v_total   += labels.size(0)\n        val_acc = 100*v_correct/v_total\n\n        print(f\"Epoch {ep+1}/10 | Train: {train_acc:.2f}% | Val: {val_acc:.2f}%\")\n\n        # Best model save\n        if val_acc > best_acc:\n            best_acc = val_acc\n            torch.save(model.state_dict(), '/kaggle/working/best_model.pth')\n            print(f\"  ✅ Best model saved! ({best_acc:.2f}%)\")\n\n    print(f\"\\nTraining Done! Best Val Accuracy: {best_acc:.2f}%\")\n\ntrain_model(epochs=10)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nos.environ['CUDA_LAUNCH_BLOCKING'] = '1'\n\n# GPU reset করো\nimport torch\ntorch.cuda.empty_cache()\n\n# CPU দিয়ে test করো আগে\ndevice = torch.device('cpu')\nmodel = model.to(device)\nprint(f\"Device: {device}\")\n\n# ছোট batch দিয়ে test\ntest_imgs = torch.randn(2, 3, 224, 224).to(device)\nout = model(test_imgs)\nprint(f\"Model output shape: {out.shape}\")\nprint(\"Model working ✅\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nprint(torch.cuda.is_available())\nprint(torch.cuda.get_device_name(0))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, torch, timm\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom PIL import Image\n\n# Device\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(f\"Device: {device}\")\n\n# Transform\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.5]*3, [0.5]*3)\n])\n\n# Dataset Class\nclass DeepfakeDataset(Dataset):\n    def __init__(self, real_dir, fake_dir, transform=None):\n        self.data, self.transform = [], transform\n        for f in os.listdir(real_dir):\n            if f.endswith(('.jpg','.png')):\n                self.data.append((os.path.join(real_dir, f), 0))\n        for f in os.listdir(fake_dir):\n            if f.endswith(('.jpg','.png')):\n                self.data.append((os.path.join(fake_dir, f), 1))\n    def __len__(self): return len(self.data)\n    def __getitem__(self, i):\n        p, l = self.data[i]\n        img = Image.open(p).convert('RGB')\n        return (self.transform(img) if self.transform else img), l\n\n# Paths\nREAL = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Train/real'\nFAKE = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Train/fake'\n\n# DataLoader\ndataset  = DeepfakeDataset(REAL, FAKE, transform)\ntrain_size = int(0.8 * len(dataset))\nval_size   = len(dataset) - train_size\ntrain_ds, val_ds = torch.utils.data.random_split(\n    dataset, [train_size, val_size],\n    generator=torch.Generator().manual_seed(42)\n)\ntrain_loader = DataLoader(train_ds, batch_size=16, shuffle=True,  num_workers=2)\nval_loader   = DataLoader(val_ds,   batch_size=16, shuffle=False, num_workers=2)\nprint(f\"Train: {train_size} | Val: {val_size} ✅\")\n\n# Model\nmodel = timm.create_model('efficientnet_b4', pretrained=True)\nmodel.classifier = nn.Linear(model.classifier.in_features, 2)\nmodel = model.to(device)\nprint(\"EfficientNet-B4 ready ✅\")\n\n# Loss + Optimizer\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=1e-4)\n\n# Train\ndef train_model(epochs=10):\n    best_acc = 0\n    for ep in range(epochs):\n        model.train()\n        correct, total = 0, 0\n        for imgs, labels in train_loader:\n            imgs, labels = imgs.to(device), labels.to(device)\n            optimizer.zero_grad()\n            out  = model(imgs)\n            loss = criterion(out, labels)\n            loss.backward()\n            optimizer.step()\n            correct += (out.argmax(1)==labels).sum().item()\n            total   += labels.size(0)\n        train_acc = 100*correct/total\n\n        model.eval()\n        v_correct, v_total = 0, 0\n        with torch.no_grad():\n            for imgs, labels in val_loader:\n                imgs, labels = imgs.to(device), labels.to(device)\n                v_correct += (model(imgs).argmax(1)==labels).sum().item()\n                v_total   += labels.size(0)\n        val_acc = 100*v_correct/v_total\n\n        print(f\"Epoch {ep+1}/10 | Train: {train_acc:.2f}% | Val: {val_acc:.2f}%\")\n\n        if val_acc > best_acc:\n            best_acc = val_acc\n            torch.save(model.state_dict(), '/kaggle/working/best_model.pth')\n            print(f\"  ✅ Best model saved! ({best_acc:.2f}%)\")\n\n    print(f\"\\nTraining Done! Best: {best_acc:.2f}%\")\n\ntrain_model(epochs=10)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from IPython.display import FileLink\nFileLink(r'best_model.pth')","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.nn.functional as F\nfrom sklearn.metrics import accuracy_score, f1_score, roc_auc_score\n\n# Test path\nTEST_REAL = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Test/real'\nTEST_FAKE = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Test/fake'\n\n# Load best model\nmodel.load_state_dict(torch.load('/kaggle/working/best_model.pth'))\nmodel.eval()\n\n# Test DataLoader\ntest_ds     = DeepfakeDataset(TEST_REAL, TEST_FAKE, transform)\ntest_loader = DataLoader(test_ds, batch_size=16, shuffle=False)\n\n# Evaluate\nall_preds, all_labels, all_probs = [], [], []\nwith torch.no_grad():\n    for imgs, labels in test_loader:\n        imgs   = imgs.to(device)\n        out    = model(imgs)\n        probs  = F.softmax(out, dim=1)[:,1].cpu().numpy()\n        preds  = out.argmax(1).cpu().numpy()\n        all_preds.extend(preds)\n        all_labels.extend(labels.numpy())\n        all_probs.extend(probs)\n\nacc = accuracy_score(all_labels, all_preds)  * 100\nf1  = f1_score(all_labels, all_preds)        * 100\nauc = roc_auc_score(all_labels, all_probs)   * 100\n\nprint(\"====== EfficientNet-B4 Final Result ======\")\nprint(f\"Accuracy : {acc:.2f}%\")\nprint(f\"F1 Score : {f1:.2f}%\")\nprint(f\"AUC      : {auc:.2f}%\")\nprint(\"==========================================\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, torch, timm\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom PIL import Image\nfrom sklearn.metrics import accuracy_score, f1_score, roc_auc_score\n\n# Device\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# Transform\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.5]*3, [0.5]*3)\n])\n\n# Dataset Class\nclass DeepfakeDataset(Dataset):\n    def __init__(self, real_dir, fake_dir, transform=None):\n        self.data, self.transform = [], transform\n        for f in os.listdir(real_dir):\n            if f.endswith(('.jpg','.png')):\n                self.data.append((os.path.join(real_dir, f), 0))\n        for f in os.listdir(fake_dir):\n            if f.endswith(('.jpg','.png')):\n                self.data.append((os.path.join(fake_dir, f), 1))\n    def __len__(self): return len(self.data)\n    def __getitem__(self, i):\n        p, l = self.data[i]\n        img = Image.open(p).convert('RGB')\n        return (self.transform(img) if self.transform else img), l\n\n# Model load\nmodel = timm.create_model('efficientnet_b4', pretrained=False)\nmodel.classifier = nn.Linear(model.classifier.in_features, 2)\nmodel.load_state_dict(torch.load('/kaggle/working/best_model.pth'))\nmodel = model.to(device)\nmodel.eval()\nprint(\"Model loaded ✅\")\n\n# Test paths\nTEST_REAL = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Test/real'\nTEST_FAKE = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Test/fake'\n\ntest_ds     = DeepfakeDataset(TEST_REAL, TEST_FAKE, transform)\ntest_loader = DataLoader(test_ds, batch_size=16, shuffle=False)\nprint(f\"Test images: {len(test_ds)} ✅\")\n\n# Evaluate\nall_preds, all_labels, all_probs = [], [], []\nwith torch.no_grad():\n    for imgs, labels in test_loader:\n        imgs  = imgs.to(device)\n        out   = model(imgs)\n        probs = F.softmax(out, dim=1)[:,1].cpu().numpy()\n        preds = out.argmax(1).cpu().numpy()\n        all_preds.extend(preds)\n        all_labels.extend(labels.numpy())\n        all_probs.extend(probs)\n\nacc = accuracy_score(all_labels, all_preds) * 100\nf1  = f1_score(all_labels, all_preds)       * 100\nauc = roc_auc_score(all_labels, all_probs)  * 100\n\nprint(\"====== EfficientNet-B4 Final Result ======\")\nprint(f\"Accuracy : {acc:.2f}%\")\nprint(f\"F1 Score : {f1:.2f}%\")\nprint(f\"AUC      : {auc:.2f}%\")\nprint(\"==========================================\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, torch, timm\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader, Subset\nfrom torchvision import transforms\nfrom PIL import Image\nimport torch.nn.functional as F\nfrom sklearn.metrics import accuracy_score, f1_score, roc_auc_score\nimport random\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(f\"Device: {device}\")\n\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.5]*3, [0.5]*3)\n])\n\nclass DeepfakeDataset(Dataset):\n    def __init__(self, real_dir, fake_dir, transform=None, max_each=3000):\n        self.data, self.transform = [], transform\n        real_files = [f for f in os.listdir(real_dir) if f.endswith(('.jpg','.png'))]\n        fake_files = [f for f in os.listdir(fake_dir) if f.endswith(('.jpg','.png'))]\n        # শুধু ৩০০০ করে নেবো\n        random.seed(42)\n        real_files = random.sample(real_files, min(max_each, len(real_files)))\n        fake_files = random.sample(fake_files, min(max_each, len(fake_files)))\n        for f in real_files:\n            self.data.append((os.path.join(real_dir, f), 0))\n        for f in fake_files:\n            self.data.append((os.path.join(fake_dir, f), 1))\n    def __len__(self): return len(self.data)\n    def __getitem__(self, i):\n        p, l = self.data[i]\n        img = Image.open(p).convert('RGB')\n        return (self.transform(img) if self.transform else img), l\n\n# Paths\nREAL = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Train/real'\nFAKE = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Train/fake'\nTEST_REAL = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Test/real'\nTEST_FAKE = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Test/fake'\n\n# DataLoader — শুধু ৬০০০ image\ndataset    = DeepfakeDataset(REAL, FAKE, transform, max_each=3000)\ntrain_size = int(0.8 * len(dataset))\nval_size   = len(dataset) - train_size\ntrain_ds, val_ds = torch.utils.data.random_split(\n    dataset, [train_size, val_size],\n    generator=torch.Generator().manual_seed(42)\n)\ntrain_loader = DataLoader(train_ds, batch_size=32, shuffle=True,  num_workers=2)\nval_loader   = DataLoader(val_ds,   batch_size=32, shuffle=False, num_workers=2)\nprint(f\"Train: {train_size} | Val: {val_size} ✅\")\n\n# Model\nmodel = timm.create_model('efficientnet_b4', pretrained=True)\nmodel.classifier = nn.Linear(model.classifier.in_features, 2)\nmodel = model.to(device)\n\n# Train — শুধু ৫ epoch\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=1e-4)\n\nbest_acc = 0\nfor ep in range(5):\n    model.train()\n    correct, total = 0, 0\n    for imgs, labels in train_loader:\n        imgs, labels = imgs.to(device), labels.to(device)\n        optimizer.zero_grad()\n        out  = model(imgs)\n        loss = criterion(out, labels)\n        loss.backward()\n        optimizer.step()\n        correct += (out.argmax(1)==labels).sum().item()\n        total   += labels.size(0)\n    train_acc = 100*correct/total\n\n    model.eval()\n    v_correct, v_total = 0, 0\n    with torch.no_grad():\n        for imgs, labels in val_loader:\n            imgs, labels = imgs.to(device), labels.to(device)\n            v_correct += (model(imgs).argmax(1)==labels).sum().item()\n            v_total   += labels.size(0)\n    val_acc = 100*v_correct/v_total\n    print(f\"Epoch {ep+1}/5 | Train: {train_acc:.2f}% | Val: {val_acc:.2f}%\")\n    if val_acc > best_acc:\n        best_acc = val_acc\n        torch.save(model.state_dict(), '/kaggle/working/best_model.pth')\n        print(f\"  ✅ Saved! ({best_acc:.2f}%)\")\n\n# Test\ntest_ds     = DeepfakeDataset(TEST_REAL, TEST_FAKE, transform, max_each=1000)\ntest_loader = DataLoader(test_ds, batch_size=32, shuffle=False)\nmodel.load_state_dict(torch.load('/kaggle/working/best_model.pth'))\nmodel.eval()\n\nall_preds, all_labels, all_probs = [], [], []\nwith torch.no_grad():\n    for imgs, labels in test_loader:\n        out   = model(imgs.to(device))\n        probs = F.softmax(out,dim=1)[:,1].cpu().numpy()\n        preds = out.argmax(1).cpu().numpy()\n        all_preds.extend(preds)\n        all_labels.extend(labels.numpy())\n        all_probs.extend(probs)\n\nacc = accuracy_score(all_labels, all_preds) * 100\nf1  = f1_score(all_labels, all_preds)       * 100\nauc = roc_auc_score(all_labels, all_probs)  * 100\nprint(\"====== EfficientNet-B4 Result ======\")\nprint(f\"Accuracy : {acc:.2f}%\")\nprint(f\"F1 Score : {f1:.2f}%\")\nprint(f\"AUC      : {auc:.2f}%\")\nprint(\"====================================\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-08-05T14:27:35.849792Z","iopub.execute_input":"2026-08-05T14:27:35.850044Z","iopub.status.idle":"2026-08-05T14:34:58.540754Z","shell.execute_reply.started":"2026-08-05T14:27:35.850022Z","shell.execute_reply":"2026-08-05T14:34:58.539947Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, torch, timm, random\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom PIL import Image\nfrom sklearn.metrics import accuracy_score, f1_score, roc_auc_score\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(f\"Device: {device}\")\n\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.5]*3, [0.5]*3)\n])\n\nclass DeepfakeDataset(Dataset):\n    def __init__(self, real_dir, fake_dir, transform=None, max_each=5000):\n        self.data, self.transform = [], transform\n        real_files = [f for f in os.listdir(real_dir) if f.endswith(('.jpg','.png'))]\n        fake_files = [f for f in os.listdir(fake_dir) if f.endswith(('.jpg','.png'))]\n        random.seed(42)\n        real_files = random.sample(real_files, min(max_each, len(real_files)))\n        fake_files = random.sample(fake_files, min(max_each, len(fake_files)))\n        for f in real_files:\n            self.data.append((os.path.join(real_dir, f), 0))\n        for f in fake_files:\n            self.data.append((os.path.join(fake_dir, f), 1))\n    def __len__(self): return len(self.data)\n    def __getitem__(self, i):\n        p, l = self.data[i]\n        img = Image.open(p).convert('RGB')\n        return (self.transform(img) if self.transform else img), l\n\n# Paths\nREAL = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Train/real'\nFAKE = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Train/fake'\nTEST_REAL = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Test/real'\nTEST_FAKE = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Test/fake'\n\ndataset    = DeepfakeDataset(REAL, FAKE, transform, max_each=5000)\ntrain_size = int(0.8 * len(dataset))\nval_size   = len(dataset) - train_size\ntrain_ds, val_ds = torch.utils.data.random_split(\n    dataset, [train_size, val_size],\n    generator=torch.Generator().manual_seed(42)\n)\ntrain_loader = DataLoader(train_ds, batch_size=32, shuffle=True,  num_workers=2)\nval_loader   = DataLoader(val_ds,   batch_size=32, shuffle=False, num_workers=2)\nprint(f\"Train: {train_size} | Val: {val_size} ✅\")\n\n# Model — (এখানে নিজের model বসাবে)\nmodel = timm.create_model('efficientnet_b4', pretrained=True)\nmodel.classifier = nn.Linear(model.classifier.in_features, 2)\nmodel = model.to(device)\n\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=1e-4)\nscheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=3)\n\n# ── Early Stopping সহ ২০ Epoch ──────────────────\nbest_acc      = 0\nno_improve    = 0\nPATIENCE      = 5   # ৫ epoch একই result → বন্ধ হবে\n\nfor ep in range(20):\n    # Train\n    model.train()\n    correct, total = 0, 0\n    for imgs, labels in train_loader:\n        imgs, labels = imgs.to(device), labels.to(device)\n        optimizer.zero_grad()\n        out  = model(imgs)\n        loss = criterion(out, labels)\n        loss.backward()\n        optimizer.step()\n        correct += (out.argmax(1)==labels).sum().item()\n        total   += labels.size(0)\n    train_acc = 100*correct/total\n\n    # Validation\n    model.eval()\n    v_correct, v_total = 0, 0\n    with torch.no_grad():\n        for imgs, labels in val_loader:\n            imgs, labels = imgs.to(device), labels.to(device)\n            v_correct += (model(imgs).argmax(1)==labels).sum().item()\n            v_total   += labels.size(0)\n    val_acc = 100*v_correct/v_total\n    scheduler.step(val_acc)\n\n    print(f\"Epoch {ep+1:02d}/20 | Train: {train_acc:.2f}% | Val: {val_acc:.2f}%\")\n\n    if val_acc > best_acc:\n        best_acc   = val_acc\n        no_improve = 0\n        torch.save(model.state_dict(), '/kaggle/working/best_model.pth')\n        print(f\"  ✅ Best saved! ({best_acc:.2f}%)\")\n    else:\n        no_improve += 1\n        print(f\"  ⏳ No improvement ({no_improve}/{PATIENCE})\")\n        if no_improve >= PATIENCE:\n            print(f\"\\n🛑 Early Stopping! {PATIENCE} epoch ধরে উন্নতি নেই।\")\n            print(f\"   Best Val Accuracy: {best_acc:.2f}%\")\n            break\n\n# ── Test ────────────────────────────────────────\nprint(\"\\n📊 Testing শুরু...\")\ntest_ds     = DeepfakeDataset(TEST_REAL, TEST_FAKE, transform, max_each=2000)\ntest_loader = DataLoader(test_ds, batch_size=32, shuffle=False)\n\nmodel.load_state_dict(torch.load('/kaggle/working/best_model.pth'))\nmodel.eval()\n\nall_preds, all_labels, all_probs = [], [], []\nwith torch.no_grad():\n    for imgs, labels in test_loader:\n        out   = model(imgs.to(device))\n        probs = F.softmax(out,dim=1)[:,1].cpu().numpy()\n        preds = out.argmax(1).cpu().numpy()\n        all_preds.extend(preds)\n        all_labels.extend(labels.numpy())\n        all_probs.extend(probs)\n\nacc = accuracy_score(all_labels, all_preds) * 100\nf1  = f1_score(all_labels, all_preds)       * 100\nauc = roc_auc_score(all_labels, all_probs)  * 100\nprint(\"====== FINAL RESULT ======\")\nprint(f\"Accuracy : {acc:.2f}%\")\nprint(f\"F1 Score : {f1:.2f}%\")\nprint(f\"AUC      : {auc:.2f}%\")\nprint(\"==========================\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-08-08T07:31:26.035792Z","iopub.execute_input":"2026-08-08T07:31:26.036094Z","iopub.status.idle":"2026-08-08T07:31:48.744065Z","shell.execute_reply.started":"2026-08-08T07:31:26.036071Z","shell.execute_reply":"2026-08-08T07:31:48.742848Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os, torch, timm, random\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom PIL import Image\nfrom sklearn.metrics import accuracy_score, f1_score, roc_auc_score\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(f\"Device: {device}\")\n\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.5]*3, [0.5]*3)\n])\n\nclass DeepfakeDataset(Dataset):\n    def __init__(self, real_dir, fake_dir, transform=None, max_each=5000):\n        self.data, self.transform = [], transform\n        real_files = [f for f in os.listdir(real_dir) if f.endswith(('.jpg','.png'))]\n        fake_files = [f for f in os.listdir(fake_dir) if f.endswith(('.jpg','.png'))]\n        random.seed(42)\n        real_files = random.sample(real_files, min(max_each, len(real_files)))\n        fake_files = random.sample(fake_files, min(max_each, len(fake_files)))\n        for f in real_files:\n            self.data.append((os.path.join(real_dir, f), 0))\n        for f in fake_files:\n            self.data.append((os.path.join(fake_dir, f), 1))\n    def __len__(self): return len(self.data)\n    def __getitem__(self, i):\n        p, l = self.data[i]\n        img = Image.open(p).convert('RGB')\n        return (self.transform(img) if self.transform else img), l\n\nREAL = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Train/real'\nFAKE = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Train/fake'\nTEST_REAL = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Test/real'\nTEST_FAKE = '/kaggle/input/datasets/pranabr0y/celebdf-v2image-dataset/Celeb_V2/Test/fake'\n\ndataset    = DeepfakeDataset(REAL, FAKE, transform, max_each=5000)\ntrain_size = int(0.8 * len(dataset))\nval_size   = len(dataset) - train_size\ntrain_ds, val_ds = torch.utils.data.random_split(\n    dataset, [train_size, val_size],\n    generator=torch.Generator().manual_seed(42)\n)\ntrain_loader = DataLoader(train_ds, batch_size=32, shuffle=True,  num_workers=2)\nval_loader   = DataLoader(val_ds,   batch_size=32, shuffle=False, num_workers=2)\nprint(f\"Train: {train_size} | Val: {val_size} ✅\")\n\nmodel = timm.create_model('efficientnet_b4', pretrained=True)\nmodel.classifier = nn.Linear(model.classifier.in_features, 2)\nmodel = model.to(device)\n\ncriterion = nn.CrossEntropyLoss()\noptimizer  = optim.Adam(model.parameters(), lr=1e-4)\nscheduler  = optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=3)\n\nbest_acc   = 0\nno_improve = 0\nPATIENCE   = 5\n\nfor ep in range(20):\n    model.train()\n    correct, total = 0, 0\n    for imgs, labels in train_loader:\n        imgs, labels = imgs.to(device), labels.to(device)\n        optimizer.zero_grad()\n        out  = model(imgs)\n        loss = criterion(out, labels)\n        loss.backward()\n        optimizer.step()\n        correct += (out.argmax(1)==labels).sum().item()\n        total   += labels.size(0)\n    train_acc = 100*correct/total\n\n    model.eval()\n    v_correct, v_total = 0, 0\n    with torch.no_grad():\n        for imgs, labels in val_loader:\n            imgs, labels = imgs.to(device), labels.to(device)\n            v_correct += (model(imgs).argmax(1)==labels).sum().item()\n            v_total   += labels.size(0)\n    val_acc = 100*v_correct/v_total\n    scheduler.step(val_acc)\n\n    print(f\"Epoch {ep+1:02d}/20 | Train: {train_acc:.2f}% | Val: {val_acc:.2f}%\")\n\n    if val_acc > best_acc:\n        best_acc   = val_acc\n        no_improve = 0\n        torch.save(model.state_dict(), '/kaggle/working/best_model.pth')\n        print(f\"  ✅ Best saved! ({best_acc:.2f}%)\")\n    else:\n        no_improve += 1\n        print(f\"  ⏳ No improve ({no_improve}/{PATIENCE})\")\n        if no_improve >= PATIENCE:\n            print(f\"🛑 Early Stop! Best: {best_acc:.2f}%\")\n            break\n\n# Test\nprint(\"\\n📊 Testing...\")\ntest_ds     = DeepfakeDataset(TEST_REAL, TEST_FAKE, transform, max_each=2000)\ntest_loader = DataLoader(test_ds, batch_size=32, shuffle=False)\nmodel.load_state_dict(torch.load('/kaggle/working/best_model.pth'))\nmodel.eval()\n\nall_preds, all_labels, all_probs = [], [], []\nwith torch.no_grad():\n    for imgs, labels in test_loader:\n        out   = model(imgs.to(device))\n        probs = F.softmax(out,dim=1)[:,1].cpu().numpy()\n        preds = out.argmax(1).cpu().numpy()\n        all_preds.extend(preds)\n        all_labels.extend(labels.numpy())\n        all_probs.extend(probs)\n\nacc = accuracy_score(all_labels, all_preds) * 100\nf1  = f1_score(all_labels, all_preds)       * 100\nauc = roc_auc_score(all_labels, all_probs)  * 100\nprint(\"====== EfficientNet-B4 FINAL RESULT ======\")\nprint(f\"Accuracy : {acc:.2f}%\")\nprint(f\"F1 Score : {f1:.2f}%\")\nprint(f\"AUC      : {auc:.2f}%\")\nprint(\"==========================================\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-08-08T07:38:15.474164Z","iopub.execute_input":"2026-08-08T07:38:15.474894Z","iopub.status.idle":"2026-08-08T08:20:39.916543Z","shell.execute_reply.started":"2026-08-08T07:38:15.474860Z","shell.execute_reply":"2026-08-08T08:20:39.915580Z"}},"outputs":[],"execution_count":null}]}