{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","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"}],"dockerImageVersionId":30823,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"##################################################################\n# 1) استيراد المكتبات اللازمة + التحقق من الـ GPU\n##################################################################\nimport os\nimport cv2\nimport shutil\nimport random\nimport numpy as np\nimport pandas as pd\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader, Dataset\nfrom torchvision import transforms, models\nfrom torchvision.datasets import ImageFolder\n\n# Vision Transformer من مكتبة huggingface\n!pip install transformers  # (في حال لم تكن مثبّتة)\nfrom transformers import ViTForImageClassification, ViTImageProcessor\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(\"Using device:\", device)\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-12-28T22:36:51.412788Z","iopub.execute_input":"2024-12-28T22:36:51.413086Z","iopub.status.idle":"2024-12-28T22:36:54.788208Z","shell.execute_reply.started":"2024-12-28T22:36:51.413065Z","shell.execute_reply":"2024-12-28T22:36:54.787179Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"########################################\n# 2) تحديد مسارات الفيديوهات + قراءة Metadata\n########################################\n# عدّل هذا المسار حسب بيئتك\ndataset_path = \"/kaggle/input/deepfake-detection-challenge\"\n\ntrain_videos_path = os.path.join(dataset_path, \"train_sample_videos\")\ntest_videos_path  = os.path.join(dataset_path, \"test_videos\")\n\nmetadata_json_path = os.path.join(train_videos_path, \"metadata.json\")\ntrain_sample_metadata = pd.read_json(metadata_json_path).T\n\nprint(f\"Number of train videos: {len(os.listdir(train_videos_path))}\")\nprint(f\"Number of test videos : {len(os.listdir(test_videos_path))}\")\nprint(\"Metadata sample:\")\nprint(train_sample_metadata.head())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-28T22:42:28.301753Z","iopub.execute_input":"2024-12-28T22:42:28.302084Z","iopub.status.idle":"2024-12-28T22:42:28.400544Z","shell.execute_reply.started":"2024-12-28T22:42:28.302058Z","shell.execute_reply":"2024-12-28T22:42:28.399532Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"########################################\n# 3) مسار إخراج الإطارات\n########################################\noutput_dir = \"/kaggle/working/frames\"\nos.makedirs(output_dir, exist_ok=True)\n\nreal_folder = os.path.join(output_dir, \"REAL\")\nfake_folder = os.path.join(output_dir, \"Fake\")\nos.makedirs(real_folder, exist_ok=True)\nos.makedirs(fake_folder, exist_ok=True)\n\n########################################\n# 4) دالّة استخراج الإطارات\n########################################\ndef extract_frames(video_path, output_dir, frame_rate=30):\n    cap = cv2.VideoCapture(video_path)\n    frame_idx = 0\n    while cap.isOpened():\n        ret, frame = cap.read()\n        if not ret:\n            break\n        if int(cap.get(cv2.CAP_PROP_POS_FRAMES)) % frame_rate == 0:\n            frame_name = f\"{os.path.basename(video_path)}_frame_{frame_idx}.jpg\"\n            frame_path = os.path.join(output_dir, frame_name)\n            frame_rgb  = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)\n            cv2.imwrite(frame_path, frame_rgb)\n            frame_idx += 1\n    cap.release()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-28T22:42:30.441855Z","iopub.execute_input":"2024-12-28T22:42:30.442196Z","iopub.status.idle":"2024-12-28T22:42:30.448649Z","shell.execute_reply.started":"2024-12-28T22:42:30.442167Z","shell.execute_reply":"2024-12-28T22:42:30.447900Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"########################################\n# 5) استخراج الإطارات من جميع الفيديوهات\n########################################\nprint(\"Extracting frames. This may take a while ...\")\nfor video_name, data in train_sample_metadata.iterrows():\n    label = data['label']  # REAL / FAKE\n    video_path = os.path.join(train_videos_path, video_name)\n    if label == \"REAL\":\n        extract_frames(video_path, real_folder)\n    else:\n        extract_frames(video_path, fake_folder)\n\nprint(\"Frame extraction completed.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-28T22:42:32.769489Z","iopub.execute_input":"2024-12-28T22:42:32.769783Z","iopub.status.idle":"2024-12-28T22:52:53.177524Z","shell.execute_reply.started":"2024-12-28T22:42:32.769762Z","shell.execute_reply":"2024-12-28T22:52:53.176422Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def split_data(source_dir, train_dir, val_dir, test_dir, train_ratio=0.7, val_ratio=0.1):\n    for category in [\"REAL\", \"Fake\"]:\n        category_path = os.path.join(source_dir, category)\n        if not os.path.isdir(category_path):\n            continue\n        images = [os.path.join(category_path, img) for img in os.listdir(category_path)]\n        train_imgs, test_imgs = train_test_split(images, test_size=(1 - train_ratio), random_state=42)\n        train_imgs, val_imgs  = train_test_split(train_imgs, test_size=val_ratio / train_ratio, random_state=42)\n\n        for img_set, out_dir in zip([train_imgs, val_imgs, test_imgs],\n                                    [train_dir, val_dir, test_dir]):\n            cat_out_dir = os.path.join(out_dir, category)\n            os.makedirs(cat_out_dir, exist_ok=True)\n            for img_path in img_set:\n                shutil.copy(img_path, cat_out_dir)\n\nBASE_SPLIT_DIR = \"/kaggle/working/dataset_split\"\nTRAIN_DIR = os.path.join(BASE_SPLIT_DIR, \"train\")\nVAL_DIR   = os.path.join(BASE_SPLIT_DIR, \"val\")\nTEST_DIR  = os.path.join(BASE_SPLIT_DIR, \"test\")\n\nos.makedirs(TRAIN_DIR, exist_ok=True)\nos.makedirs(VAL_DIR, exist_ok=True)\nos.makedirs(TEST_DIR, exist_ok=True)\n\nprint(\"Splitting data into train/val/test ...\")\nsplit_data(output_dir, TRAIN_DIR, VAL_DIR, TEST_DIR, train_ratio=0.7, val_ratio=0.1)\nprint(\"Data splitting completed.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-28T22:58:38.954055Z","iopub.execute_input":"2024-12-28T22:58:38.954396Z","iopub.status.idle":"2024-12-28T22:58:40.342457Z","shell.execute_reply.started":"2024-12-28T22:58:38.954354Z","shell.execute_reply":"2024-12-28T22:58:40.341703Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 7) إنشاء DataLoaders مع ImageFolder\n########################################\ndef get_dataloaders(train_dir, val_dir, test_dir, batch_size=32, num_workers=2):\n    train_transform = transforms.Compose([\n        transforms.Resize((224, 224)),\n        transforms.RandomHorizontalFlip(p=0.5),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406],\n                             [0.229, 0.224, 0.225])\n    ])\n    val_transform = transforms.Compose([\n        transforms.Resize((224, 224)),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406],\n                             [0.229, 0.224, 0.225])\n    ])\n    test_transform = val_transform\n\n    train_dataset = ImageFolder(root=train_dir, transform=train_transform)\n    val_dataset   = ImageFolder(root=val_dir,   transform=val_transform)\n    test_dataset  = ImageFolder(root=test_dir,  transform=test_transform)\n\n    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=num_workers)\n    val_loader   = DataLoader(val_dataset,   batch_size=batch_size, shuffle=False,num_workers=num_workers)\n    test_loader  = DataLoader(test_dataset,  batch_size=batch_size, shuffle=False,num_workers=num_workers)\n\n    return train_loader, val_loader, test_loader\n\nbatch_size = 16  # مثال\ntrain_loader, val_loader, test_loader = get_dataloaders(TRAIN_DIR, VAL_DIR, TEST_DIR, batch_size=batch_size)\n\nprint(f\"Train samples: {len(train_loader.dataset)}\")\nprint(f\"Val   samples: {len(val_loader.dataset)}\")\nprint(f\"Test  samples: {len(test_loader.dataset)}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-28T22:58:44.841985Z","iopub.execute_input":"2024-12-28T22:58:44.842278Z","iopub.status.idle":"2024-12-28T22:58:44.863818Z","shell.execute_reply.started":"2024-12-28T22:58:44.842255Z","shell.execute_reply":"2024-12-28T22:58:44.862914Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"########################################\n# 8) إنشاء النماذج (بمخرج 1) + FineTune\n########################################\ndef create_model(model_name, add_conv_layer=False, fine_tune_layers=0):\n    \"\"\"\n    model_name: أحد الأسماء (vgg16, resnet50, densenet121, mobilenet_v2, inception).\n    add_conv_layer: لإضافة طبقة Conv إضافية\n    fine_tune_layers: إلغاء تجميد آخر N طبقة من الـfeatures\n    \"\"\"\n    if model_name == 'vgg16':\n        model = models.vgg16(pretrained=True)\n        # تجميد\n        for param in model.parameters():\n            param.requires_grad = False\n\n        # إضافة طبقة Conv إضافية في الـfeatures إن أردنا\n        if add_conv_layer:\n            extra_conv = nn.Sequential(\n                nn.Conv2d(512, 512, kernel_size=3, padding=1),\n                nn.ReLU(inplace=True)\n            )\n            # model.features هو Sequential\n            model.features = nn.Sequential(*(list(model.features.children()) + [extra_conv]))\n\n        # إلغاء تجميد آخر fine_tune_layers من الـfeatures\n        if fine_tune_layers > 0:\n            layers_list = list(model.features.children())\n            c = 0\n            for layer in reversed(layers_list):\n                for param in layer.parameters():\n                    param.requires_grad = True\n                c += 1\n                if c >= fine_tune_layers:\n                    break\n            model.features = nn.Sequential(*layers_list)\n\n        # عدد المدخلات في آخر طبقة\n        in_features = model.classifier[-1].in_features\n        model.classifier[-1] = nn.Linear(in_features, 1)\n\n    elif model_name == 'resnet50':\n        model = models.resnet50(pretrained=True)\n        for param in model.parameters():\n            param.requires_grad = False\n\n        if add_conv_layer:\n            # نضيفها بعد layer4 مثلًا\n            model.layer4 = nn.Sequential(\n                model.layer4,\n                nn.Conv2d(2048, 2048, kernel_size=3, padding=1),\n                nn.ReLU(inplace=True)\n            )\n\n        if fine_tune_layers > 0:\n            # نفك التجميد عن layer4 كاملة مثلًا\n            for param in model.layer4.parameters():\n                param.requires_grad = True\n\n        in_features = model.fc.in_features\n        model.fc = nn.Linear(in_features, 1)\n\n    elif model_name == 'densenet121':\n        model = models.densenet121(pretrained=True)\n        for param in model.parameters():\n            param.requires_grad = False\n\n        if add_conv_layer:\n            extra_conv = nn.Sequential(\n                nn.Conv2d(1024, 1024, kernel_size=3, padding=1),\n                nn.ReLU(inplace=True)\n            )\n            model.features = nn.Sequential(model.features, extra_conv)\n\n        if fine_tune_layers > 0:\n            layers_list = list(model.features.children())\n            c = 0\n            for layer in reversed(layers_list):\n                for param in layer.parameters():\n                    param.requires_grad = True\n                c += 1\n                if c >= fine_tune_layers:\n                    break\n            model.features = nn.Sequential(*layers_list)\n\n        in_features = model.classifier.in_features\n        model.classifier = nn.Linear(in_features, 1)\n\n    elif model_name == 'mobilenet_v2':\n        model = models.mobilenet_v2(pretrained=True)\n        for param in model.parameters():\n            param.requires_grad = False\n\n        if add_conv_layer:\n            extra_conv = nn.Sequential(\n                nn.Conv2d(1280, 1280, kernel_size=3, padding=1),\n                nn.ReLU(inplace=True)\n            )\n            model.features = nn.Sequential(model.features, extra_conv)\n\n        if fine_tune_layers > 0:\n            layers_list = list(model.features.children())\n            c = 0\n            for layer in reversed(layers_list):\n                for param in layer.parameters():\n                    param.requires_grad = True\n                c += 1\n                if c >= fine_tune_layers:\n                    break\n            model.features = nn.Sequential(*layers_list)\n\n        in_features = model.classifier[-1].in_features\n        model.classifier[-1] = nn.Linear(in_features, 1)\n\n    elif model_name == 'inception':\n        model = models.inception_v3(pretrained=True)\n        for param in model.parameters():\n            param.requires_grad = False\n\n        if add_conv_layer:\n            extra_conv = nn.Sequential(\n                nn.Conv2d(2048, 2048, kernel_size=3, padding=1),\n                nn.ReLU(inplace=True)\n            )\n            # Mixed_7c آخر جزء رئيسي في inception\n            model.Mixed_7c = nn.Sequential(model.Mixed_7c, extra_conv)\n\n        if fine_tune_layers > 0:\n            # نفك التجميد عن آخر block مثلًا\n            for param in model.Mixed_7c.parameters():\n                param.requires_grad = True\n\n        # inception يحتاج مدخل (299,299) عادة، لكن سنتجاوز للفائدة فقط\n        in_features = model.fc.in_features\n        model.fc = nn.Linear(in_features, 1)\n\n    else:\n        raise ValueError(f\"Unsupported model: {model_name}\")\n\n    return model.to(device)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-28T22:58:49.169867Z","iopub.execute_input":"2024-12-28T22:58:49.170165Z","iopub.status.idle":"2024-12-28T22:58:49.184270Z","shell.execute_reply.started":"2024-12-28T22:58:49.170144Z","shell.execute_reply":"2024-12-28T22:58:49.183370Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"########################################\n# 9) دالّة إنشاء ViT (مخرج=1)\n########################################\nfrom transformers import ViTForImageClassification\n\ndef create_vit_model(add_conv_layer=False, fine_tune=False):\n    # نستخدم الإصدار الأساسي\n    vit_model = ViTForImageClassification.from_pretrained(\n        \"google/vit-base-patch16-224\",\n        num_labels=1,  # مخرج واحد\n        problem_type=\"single_label_classification\"\n    ).to(device)\n\n    for param in vit_model.parameters():\n        param.requires_grad = False\n\n    if add_conv_layer:\n        print(\"تنبيه: إضافة Conv Layer في ViT غير قياسية وقد تحتاج تعديلات عميقة في forward().\")\n\n    if fine_tune:\n        # نفك التجميد عن آخر Block في encoder\n        for param in vit_model.vit.encoder.layer[-1].parameters():\n            param.requires_grad = True\n\n    return vit_model\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-28T22:58:54.003722Z","iopub.execute_input":"2024-12-28T22:58:54.004023Z","iopub.status.idle":"2024-12-28T22:58:54.008921Z","shell.execute_reply.started":"2024-12-28T22:58:54.004003Z","shell.execute_reply":"2024-12-28T22:58:54.007996Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"########################################\n# 10) توابع التدريب والتقييم BCEWithLogitsLoss\n########################################\ndef train_one_epoch(model, dataloader, optimizer, criterion):\n    model.train()\n    total_loss = 0.0\n    total_samples = 0\n    correct = 0\n\n    for images, labels in dataloader:\n        images, labels = images.to(device), labels.to(device).float()\n\n        optimizer.zero_grad()\n        outputs = model(images).squeeze(dim=1)  # [batch]\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n\n        total_loss += loss.item() * labels.size(0)\n        total_samples += labels.size(0)\n\n        preds = (torch.sigmoid(outputs) >= 0.5).long()\n        correct += (preds == labels.long()).sum().item()\n\n    avg_loss = total_loss / total_samples\n    accuracy = correct / total_samples\n    return avg_loss, accuracy\n\n\ndef evaluate(model, dataloader, criterion):\n    model.eval()\n    total_loss = 0.0\n    total_samples = 0\n    correct = 0\n\n    with torch.no_grad():\n        for images, labels in dataloader:\n            images, labels = images.to(device), labels.to(device).float()\n            outputs = model(images).squeeze(dim=1)\n            loss = criterion(outputs, labels)\n\n            total_loss += loss.item() * labels.size(0)\n            total_samples += labels.size(0)\n\n            preds = (torch.sigmoid(outputs) >= 0.5).long()\n            correct += (preds == labels.long()).sum().item()\n\n    avg_loss = total_loss / total_samples\n    accuracy = correct / total_samples\n    return avg_loss, accuracy\n\n\ndef test_model(model, dataloader):\n    model.eval()\n    all_preds = []\n    all_labels = []\n\n    with torch.no_grad():\n        for images, labels in dataloader:\n            images, labels = images.to(device), labels.to(device).float()\n            outputs = model(images).squeeze(dim=1)\n            preds = (torch.sigmoid(outputs) >= 0.5).long()\n\n            all_preds.extend(preds.cpu().numpy())\n            all_labels.extend(labels.cpu().numpy())\n\n    acc  = accuracy_score(all_labels, all_preds)\n    prec = precision_score(all_labels, all_preds, average='macro')\n    rec  = recall_score(all_labels, all_preds, average='macro')\n    f1   = f1_score(all_labels, all_preds, average='macro')\n    cm   = confusion_matrix(all_labels, all_preds)\n    return acc, prec, rec, f1, cm\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-28T22:58:56.203245Z","iopub.execute_input":"2024-12-28T22:58:56.203572Z","iopub.status.idle":"2024-12-28T22:58:56.213317Z","shell.execute_reply.started":"2024-12-28T22:58:56.203547Z","shell.execute_reply":"2024-12-28T22:58:56.212545Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"########################################\n# 11) Simulated Annealing للـ LR\n########################################\ndef simulated_annealing_lr(model, dataloader, criterion, initial_lr=0.001, epochs=3):\n    import copy\n    original_state_dict = copy.deepcopy(model.state_dict())\n\n    best_lr = initial_lr\n    best_loss = float('inf')\n    current_lr = initial_lr\n\n    for epoch in range(epochs):\n        optimizer = optim.SGD(model.parameters(), lr=current_lr)\n        model.train()\n        total_loss = 0\n        total_samples = 0\n\n        for images, labels in dataloader:\n            images, labels = images.to(device), labels.to(device).float()\n            optimizer.zero_grad()\n            outputs = model(images).squeeze(dim=1)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            optimizer.step()\n\n            total_loss += loss.item() * labels.size(0)\n            total_samples += labels.size(0)\n\n        avg_loss = total_loss / total_samples\n        print(f\"[SimAnn] Epoch {epoch+1}/{epochs} => LR={current_lr:.6f}, Loss={avg_loss:.4f}\")\n\n        if avg_loss < best_loss:\n            best_loss = avg_loss\n            best_lr = current_lr\n\n        current_lr *= 0.9\n        # استرجاع وزن النموذج لبدء المحاولة الجديدة من نفس الوزن الأصلي\n        model.load_state_dict(copy.deepcopy(original_state_dict))\n\n    print(f\"[SimAnn] Best LR = {best_lr:.6f}, Best Loss = {best_loss:.4f}\")\n    # إعادة الحالة الأصلية\n    model.load_state_dict(original_state_dict)\n    return best_lr","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-28T22:58:59.831333Z","iopub.execute_input":"2024-12-28T22:58:59.831710Z","iopub.status.idle":"2024-12-28T22:58:59.838728Z","shell.execute_reply.started":"2024-12-28T22:58:59.831670Z","shell.execute_reply":"2024-12-28T22:58:59.837684Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"########################################\n# 12) تجربة مجموعة من النماذج\n########################################\ndef run_all_experiments(train_loader, val_loader, test_loader):\n    models_list = [\"vgg16\", \"resnet50\", \"densenet121\", \"mobilenet_v2\", \"inception\"]\n    criterion = nn.BCEWithLogitsLoss()\n\n    results = []\n\n    for model_name in models_list:\n        print(\"\\n============================\")\n        print(f\"MODEL: {model_name} (BASELINE)\")\n        print(\"============================\")\n        base_model = create_model(model_name, add_conv_layer=False, fine_tune_layers=0)\n        best_lr = simulated_annealing_lr(base_model, train_loader, criterion, initial_lr=1e-3, epochs=3)\n\n        # إعادة بناء\n        base_model = create_model(model_name, add_conv_layer=False, fine_tune_layers=0)\n        optimizer = optim.SGD(base_model.parameters(), lr=best_lr)\n\n        for epoch in range(3):\n            train_loss, train_acc = train_one_epoch(base_model, train_loader, optimizer, criterion)\n            val_loss, val_acc = evaluate(base_model, val_loader, criterion)\n            print(f\"Epoch {epoch+1}: Train Loss={train_loss:.4f}, Acc={train_acc:.4f} | Val Loss={val_loss:.4f}, Acc={val_acc:.4f}\")\n\n        acc, prec, rec, f1, cm = test_model(base_model, test_loader)\n        print(f\"[{model_name}-BASELINE] Test => Acc={acc:.4f}, Prec={prec:.4f}, Recall={rec:.4f}, F1={f1:.4f}\")\n        results.append((model_name+\"_baseline\", acc, prec, rec, f1))\n\n        print(\"\\n----------------------------\")\n        print(f\"MODEL: {model_name} (FineTune last 2 layers)\")\n        print(\"----------------------------\")\n        ft_model = create_model(model_name, add_conv_layer=False, fine_tune_layers=2)\n        best_lr_ft = simulated_annealing_lr(ft_model, train_loader, criterion, initial_lr=1e-4, epochs=3)\n        \n        ft_model = create_model(model_name, add_conv_layer=False, fine_tune_layers=2)\n        optimizer_ft = optim.SGD(ft_model.parameters(), lr=best_lr_ft)\n\n        for epoch in range(3):\n            train_loss, train_acc = train_one_epoch(ft_model, train_loader, optimizer_ft, criterion)\n            val_loss, val_acc = evaluate(ft_model, val_loader, criterion)\n            print(f\"Epoch {epoch+1}: Train Loss={train_loss:.4f}, Acc={train_acc:.4f} | Val Loss={val_loss:.4f}, Acc={val_acc:.4f}\")\n\n        acc, prec, rec, f1, cm = test_model(ft_model, test_loader)\n        print(f\"[{model_name}-FineTune2] Test => Acc={acc:.4f}, Prec={prec:.4f}, Recall={rec:.4f}, F1={f1:.4f}\")\n        results.append((model_name+\"_finetune2\", acc, prec, rec, f1))\n\n        print(\"\\n----------------------------\")\n        print(f\"MODEL: {model_name} (Add Conv Layer + FineTune last 2)\")\n        print(\"----------------------------\")\n        conv_model = create_model(model_name, add_conv_layer=True, fine_tune_layers=2)\n        best_lr_conv = simulated_annealing_lr(conv_model, train_loader, criterion, initial_lr=1e-4, epochs=3)\n        \n        conv_model = create_model(model_name, add_conv_layer=True, fine_tune_layers=2)\n        optimizer_conv = optim.SGD(conv_model.parameters(), lr=best_lr_conv)\n\n        for epoch in range(3):\n            train_loss, train_acc = train_one_epoch(conv_model, train_loader, optimizer_conv, criterion)\n            val_loss, val_acc = evaluate(conv_model, val_loader, criterion)\n            print(f\"Epoch {epoch+1}: Train Loss={train_loss:.4f}, Acc={train_acc:.4f} | Val Loss={val_loss:.4f}, Acc={val_acc:.4f}\")\n\n        acc, prec, rec, f1, cm = test_model(conv_model, test_loader)\n        print(f\"[{model_name}-AddConv] Test => Acc={acc:.4f}, Prec={prec:.4f}, Recall={rec:.4f}, F1={f1:.4f}\")\n        results.append((model_name+\"_addConv\", acc, prec, rec, f1))\n\n    print(\"\\n\\n======================\")\n    print(\"VISION TRANSFORMER (ViT)\")\n    print(\"======================\")\n    # Baseline ViT\n    vit_model = create_vit_model(add_conv_layer=False, fine_tune=False)\n    best_lr_vit = simulated_annealing_lr(vit_model, train_loader, criterion, initial_lr=1e-5, epochs=3)\n\n    vit_model = create_vit_model(add_conv_layer=False, fine_tune=False)\n    optimizer_vit = optim.SGD(vit_model.parameters(), lr=best_lr_vit)\n\n    for epoch in range(3):\n        train_loss, train_acc = train_one_epoch(vit_model, train_loader, optimizer_vit, criterion)\n        val_loss, val_acc = evaluate(vit_model, val_loader, criterion)\n        print(f\"Epoch {epoch+1}: Train Loss={train_loss:.4f}, Acc={train_acc:.4f} | Val Loss={val_loss:.4f}, Acc={val_acc:.4f}\")\n\n    acc, prec, rec, f1, cm = test_model(vit_model, test_loader)\n    print(f\"[ViT-Baseline] Test => Acc={acc:.4f}, Prec={prec:.4f}, Recall={rec:.4f}, F1={f1:.4f}\")\n    results.append((\"ViT_baseline\", acc, prec, rec, f1))\n\n    # FineTune ViT\n    print(\"\\n----------------------------\")\n    print(\"ViT (FineTune last block)\")\n    print(\"----------------------------\")\n    vit_ft_model = create_vit_model(add_conv_layer=False, fine_tune=True)\n    best_lr_vit_ft = simulated_annealing_lr(vit_ft_model, train_loader, criterion, initial_lr=1e-5, epochs=3)\n    \n    vit_ft_model = create_vit_model(add_conv_layer=False, fine_tune=True)\n    optimizer_vit_ft = optim.SGD(vit_ft_model.parameters(), lr=best_lr_vit_ft)\n\n    for epoch in range(3):\n        train_loss, train_acc = train_one_epoch(vit_ft_model, train_loader, optimizer_vit_ft, criterion)\n        val_loss, val_acc = evaluate(vit_ft_model, val_loader, criterion)\n        print(f\"Epoch {epoch+1}: Train Loss={train_loss:.4f}, Acc={train_acc:.4f} | Val Loss={val_loss:.4f}, Acc={val_acc:.4f}\")\n\n    acc, prec, rec, f1, cm = test_model(vit_ft_model, test_loader)\n    print(f\"[ViT-FineTune] Test => Acc={acc:.4f}, Prec={prec:.4f}, Recall={rec:.4f}, F1={f1:.4f}\")\n    results.append((\"ViT_finetune\", acc, prec, rec, f1))\n\n    print(\"\\n======================\")\n    print(\"FINAL RESULTS SUMMARY\")\n    print(\"======================\")\n    for r in results:\n        print(r)\n\n    return results\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-28T22:59:02.581698Z","iopub.execute_input":"2024-12-28T22:59:02.581978Z","iopub.status.idle":"2024-12-28T22:59:02.596107Z","shell.execute_reply.started":"2024-12-28T22:59:02.581958Z","shell.execute_reply":"2024-12-28T22:59:02.595275Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"########################################\n# 13) تشغيل (مثال) تجربة مجمّعة\n########################################\nif __name__ == \"__main__\":\n    print(\"\\n\\n========== STARTING EXPERIMENTS ==========\\n\")\n    # ملاحظة: إذا كانت البيانات ضخمة، ستأخذ هذه التجارب وقتًا طويلًا.\n    # جرّب على جزء صغير أو قلل عدد الإطارات أو قلل عدد الـ Epochs داخل الدوال.\n    results_summary = run_all_experiments(train_loader, val_loader, test_loader)\n    print(\"\\nAll experiments completed.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-28T22:59:05.865466Z","iopub.execute_input":"2024-12-28T22:59:05.865803Z"}},"outputs":[],"execution_count":null}]}