{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":104308,"databundleVersionId":12660285,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":12320483,"sourceType":"datasetVersion","datasetId":7765972},{"sourceId":437496,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":356886,"modelId":378197},{"sourceId":452955,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":367443,"modelId":388342},{"sourceId":452956,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":367444,"modelId":388343},{"sourceId":452981,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":367466,"modelId":388363},{"sourceId":452987,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":367472,"modelId":388369}],"dockerImageVersionId":31040,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# D-brain [Hyeongjun Choi, Inho Jung, Hyeonsu Hwang]","metadata":{}},{"cell_type":"markdown","source":"---","metadata":{}},{"cell_type":"code","source":"# !rm -rf /kaggle/working/dataset\n# !rm -rf /kaggle/working/dataset_json","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:51:29.065592Z","iopub.execute_input":"2025-06-29T13:51:29.066140Z","iopub.status.idle":"2025-06-29T13:51:29.069678Z","shell.execute_reply.started":"2025-06-29T13:51:29.066111Z","shell.execute_reply":"2025-06-29T13:51:29.068992Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Dataset Structure\n\n- The dataset is organized as follows:\n\n```\nchallenge_datasets/\n├── red_team_1/\n│   ├── real/\n│   │   └── videos...\n│   └── fake/\n│       └── videos...\n├── red_team_2/\n│   ├── real/\n│   │   └── videos...\n│   └── fake/\n│       └── videos...\n├── red_team_3/\n│   ├── real/\n│   │   └── videos...\n│   └── fake/\n│       └── videos...\n```","metadata":{"execution":{"iopub.status.busy":"2025-06-29T13:02:56.259833Z","iopub.execute_input":"2025-06-29T13:02:56.260613Z","iopub.status.idle":"2025-06-29T13:02:56.266190Z","shell.execute_reply.started":"2025-06-29T13:02:56.260581Z","shell.execute_reply":"2025-06-29T13:02:56.265185Z"}}},{"cell_type":"markdown","source":"## Preprocessing Instruction\n\n- To perform preprocessing, we must copy the data into the working directory","metadata":{}},{"cell_type":"code","source":"import os\nimport json\nimport cv2\nimport numpy as np\nimport shutil\n\nfrom typing import List\nfrom PIL import Image","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:48:37.435029Z","iopub.execute_input":"2025-06-29T13:48:37.435341Z","iopub.status.idle":"2025-06-29T13:48:37.439284Z","shell.execute_reply.started":"2025-06-29T13:48:37.435320Z","shell.execute_reply":"2025-06-29T13:48:37.438718Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"src_path = r\"/kaggle/input/challenge-datasets\"\ndst_path = r\"/kaggle/working/dataset\"\n\nshutil.copytree(src_path, dst_path)\nprint('Copied')\n\nos.mkdir(\"/kaggle/working/dataset_json\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:48:59.292169Z","iopub.execute_input":"2025-06-29T13:48:59.292445Z","iopub.status.idle":"2025-06-29T13:49:09.466038Z","shell.execute_reply.started":"2025-06-29T13:48:59.292426Z","shell.execute_reply":"2025-06-29T13:49:09.465147Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"---","metadata":{}},{"cell_type":"markdown","source":"## Data Preprocessing","metadata":{}},{"cell_type":"code","source":"!pip install /kaggle/input/insightface/pytorch/default/1/insightface-0.7.3-cp311-cp311-linux_x86_64.whl\n!pip install --no-index --find-links=/kaggle/input/onnxruntime-gpu/pytorch/default/1 onnxruntime-gpu==1.22.0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:49:19.274215Z","iopub.execute_input":"2025-06-29T13:49:19.274739Z","iopub.status.idle":"2025-06-29T13:49:26.062200Z","shell.execute_reply.started":"2025-06-29T13:49:19.274717Z","shell.execute_reply":"2025-06-29T13:49:26.061397Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Extract Face Regions\n\n- Load each video\n- Detect and crop face regions using insightface","metadata":{}},{"cell_type":"code","source":"from insightface.app import FaceAnalysis\n\nsrc_model_dir = '/kaggle/input/challenge/pytorch/default/1/preprocessing'\napp = FaceAnalysis(name='antelopev2', root=src_model_dir, providers=['CUDAExecutionProvider'])\napp.prepare(ctx_id=0, det_thresh=0.5, det_size=(640, 640))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:49:30.880447Z","iopub.execute_input":"2025-06-29T13:49:30.880772Z","iopub.status.idle":"2025-06-29T13:50:23.555104Z","shell.execute_reply.started":"2025-06-29T13:49:30.880746Z","shell.execute_reply":"2025-06-29T13:50:23.554341Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_all_video_paths(videos_dir, extensions=('.mp4', '.avi', '.mov', '.mkv')):\n    video_paths = []\n    \n    for root, _, files in os.walk(videos_dir):\n        for file in files:\n            if file.lower().endswith(extensions):\n                video_path = os.path.join(root, file)\n                video_paths.append(video_path)\n    \n    return video_paths\n\n    \ndef extract_frames(video_path: str) -> List[np.ndarray]:\n    frames = []\n    reader = cv2.VideoCapture(video_path)\n    \n    while reader.isOpened():\n        success, frame = reader.read()\n        if not success:\n            break\n        frames.append(frame)\n    \n    reader.release()\n\n    return frames\n\n\ndef expand_bbox_to_square(bbox, img_shape, ratio=0.2):\n    x1, y1, x2, y2 = bbox\n    w = x2 - x1\n    h = y2 - y1\n    expand_w = int(w * ratio)\n    expand_h = int(h * ratio)\n\n    new_x1 = max(0, x1 - expand_w)\n    new_y1 = max(0, y1 - expand_h)\n    new_x2 = min(img_shape[1], x2 + expand_w)\n    new_y2 = min(img_shape[0], y2 + expand_h)\n\n    box_w = new_x2 - new_x1\n    box_h = new_y2 - new_y1\n    side = max(box_w, box_h)\n\n    cx = (new_x1 + new_x2) // 2\n    cy = (new_y1 + new_y2) // 2\n    half_side = side // 2\n\n    square_x1 = max(0, cx - half_side)\n    square_y1 = max(0, cy - half_side)\n    square_x2 = min(img_shape[1], square_x1 + side)\n    square_y2 = min(img_shape[0], square_y1 + side)\n\n    square_x1 = max(0, square_x2 - side)\n    square_y1 = max(0, square_y2 - side)\n\n    return [square_x1, square_y1, square_x2, square_y2]\n\n\ndef extract_faces_from_one_video(video_path, ratio=0.2, max_frames=32):\n    frames = extract_frames(video_path)\n    \n    face_cropped_frames = []\n    for frame in frames:\n        faces = app.get(frame)\n\n        if len(faces) == 0:\n            continue\n\n        else:\n            face = faces[0]\n            bbox = face.bbox.astype(int)\n            expanded_bbox = expand_bbox_to_square(bbox, frame.shape, ratio=ratio)\n            x1, y1, x2, y2 = map(int, expanded_bbox)\n            face_crop = frame[y1:y2, x1:x2]\n\n            # Convert to RGB\n            face_crop = cv2.cvtColor(face_crop, cv2.COLOR_BGR2RGB)\n            \n            face_cropped_frames.append(face_crop)\n            \n        if len(face_cropped_frames) >= max_frames:\n            break\n    \n    return face_cropped_frames","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:50:23.556387Z","iopub.execute_input":"2025-06-29T13:50:23.556660Z","iopub.status.idle":"2025-06-29T13:50:23.566878Z","shell.execute_reply.started":"2025-06-29T13:50:23.556637Z","shell.execute_reply":"2025-06-29T13:50:23.566331Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def save_cropped_faces_from_videos(videos_dir, output_dir='frames', ratio=0.2, max_frames=32, min_sequence_length=8):\n    video_paths = get_all_video_paths(videos_dir)\n    frames_root = os.path.join(videos_dir, output_dir)\n    os.makedirs(frames_root, exist_ok=True)\n\n    for video_path in video_paths:\n        video_name = os.path.splitext(os.path.basename(video_path))[0]\n        label = os.path.basename(os.path.dirname(video_path))\n\n        save_dir = os.path.join(frames_root, label, video_name)\n        os.makedirs(save_dir, exist_ok=True)\n\n        face_frames = extract_faces_from_one_video(video_path, ratio=ratio, max_frames=max_frames)\n\n        if len(face_frames) < min_sequence_length:\n            print(f\"Warning: {video_name} has only {len(face_frames)} face frames, minimum required is {min_sequence_length}\")\n\n        for i in range(0, len(face_frames) - max_frames + 1, max_frames):\n            frame_chunk = face_frames[i:i+max_frames]\n\n            for frame_idx, face_frame in enumerate(frame_chunk):\n                if isinstance(face_frame, np.ndarray):\n                    face_frame = Image.fromarray(face_frame)\n                \n                face_frame = face_frame.resize((224, 224))\n                save_path = os.path.join(save_dir, f\"{frame_idx+1:04d}.png\")\n                face_frame.save(save_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:50:23.567665Z","iopub.execute_input":"2025-06-29T13:50:23.567830Z","iopub.status.idle":"2025-06-29T13:50:23.583583Z","shell.execute_reply.started":"2025-06-29T13:50:23.567817Z","shell.execute_reply":"2025-06-29T13:50:23.582990Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"save_cropped_faces_from_videos('/kaggle/working/dataset/red_team_1')\nsave_cropped_faces_from_videos('/kaggle/working/dataset/red_team_2')\nsave_cropped_faces_from_videos('/kaggle/working/dataset/red_team_3')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:17:52.662213Z","iopub.execute_input":"2025-06-29T13:17:52.662413Z","iopub.status.idle":"2025-06-29T13:18:55.333634Z","shell.execute_reply.started":"2025-06-29T13:17:52.662397Z","shell.execute_reply":"2025-06-29T13:18:55.332728Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"---","metadata":{}},{"cell_type":"markdown","source":"### Generate Metadata\n\n- Create a JSON file containing metadata for the preprocessed face frames","metadata":{}},{"cell_type":"code","source":"def generate_dataset_file(dataset_name, dataset_root_path, output_file_path):\n    dataset_dict = {}\n    print(dataset_name)\n\n    dataset_path = os.path.join(dataset_root_path, dataset_name)\n    dataset_dict[dataset_name] = {'test': {}}\n        \n    frames_path = os.path.join(dataset_path, 'frames')\n    for label_name, label_value in [('real', 0), ('fake', 1)]:\n        label_dir = os.path.join(frames_path, label_name)\n        if not os.path.exists(label_dir):\n            continue\n        for video_dir in os.scandir(label_dir):\n            if video_dir.is_dir():\n                video_name = video_dir.name\n                frame_paths = sorted([os.path.join(video_dir.path, frame.name) \n                                    for frame in os.scandir(video_dir.path) \n                                    if frame.name.endswith('.png')])\n                \n                frame_paths = [os.path.join(dataset_name, 'frames', label_name, video_name, os.path.basename(path)) \n                                for path in frame_paths]\n                                \n                frame_paths = [path.replace('/', '\\\\') for path in frame_paths]\n                \n                dataset_dict[dataset_name]['test'][video_name] = {\n                    'frames': frame_paths,\n                    'label': label_value\n                }\n\n    output_file_path = os.path.join(output_file_path, dataset_name + '.json')\n    with open(output_file_path, 'w') as f:\n        json.dump(dataset_dict, f)\n    print(f\"{dataset_name}.json generated successfully.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:18:55.335321Z","iopub.execute_input":"2025-06-29T13:18:55.335559Z","iopub.status.idle":"2025-06-29T13:18:55.342845Z","shell.execute_reply.started":"2025-06-29T13:18:55.335535Z","shell.execute_reply":"2025-06-29T13:18:55.342196Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dataset_root_path = '/kaggle/working/dataset'\noutput_file_path = '/kaggle/working/dataset_json'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:18:55.343859Z","iopub.execute_input":"2025-06-29T13:18:55.344082Z","iopub.status.idle":"2025-06-29T13:18:55.359525Z","shell.execute_reply.started":"2025-06-29T13:18:55.344065Z","shell.execute_reply":"2025-06-29T13:18:55.358772Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"generate_dataset_file('red_team_1', dataset_root_path, output_file_path)\ngenerate_dataset_file('red_team_2', dataset_root_path, output_file_path)\ngenerate_dataset_file('red_team_3', dataset_root_path, output_file_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:18:55.360333Z","iopub.execute_input":"2025-06-29T13:18:55.360609Z","iopub.status.idle":"2025-06-29T13:18:55.377651Z","shell.execute_reply.started":"2025-06-29T13:18:55.360582Z","shell.execute_reply":"2025-06-29T13:18:55.376891Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"---","metadata":{}},{"cell_type":"markdown","source":"## Run inference","metadata":{}},{"cell_type":"code","source":"import random\nimport sys\nimport time\nimport cv2\nimport dlib\nimport yaml\nimport re\nimport logging\nimport datetime\nimport glob\nimport concurrent.futures\nimport pandas as pd\nfrom tqdm import tqdm\nfrom pathlib import Path\nfrom imutils import face_utils\nfrom skimage import transform as trans","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:18:55.378483Z","iopub.execute_input":"2025-06-29T13:18:55.378812Z","iopub.status.idle":"2025-06-29T13:18:55.387322Z","shell.execute_reply.started":"2025-06-29T13:18:55.378791Z","shell.execute_reply":"2025-06-29T13:18:55.386615Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sys.path.append(\"/kaggle/input/challenge/pytorch/default/1\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:18:55.388919Z","iopub.execute_input":"2025-06-29T13:18:55.389166Z","iopub.status.idle":"2025-06-29T13:18:55.401665Z","shell.execute_reply.started":"2025-06-29T13:18:55.389129Z","shell.execute_reply":"2025-06-29T13:18:55.401078Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.backends.cudnn as cudnn\n\nfrom training.dataset.abstract_dataset import DeepfakeAbstractBaseDataset\nfrom training.detectors import DETECTOR\nfrom training.metrics.utils import get_video_level_predictions","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:18:55.402338Z","iopub.execute_input":"2025-06-29T13:18:55.402510Z","iopub.status.idle":"2025-06-29T13:18:55.415222Z","shell.execute_reply.started":"2025-06-29T13:18:55.402496Z","shell.execute_reply":"2025-06-29T13:18:55.414417Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Load Test Set and Model\n\n- Load the preprocessed test data\n- Load the trained model for inference","metadata":{}},{"cell_type":"code","source":"# our code\ndefault_path = \"/kaggle/input/challenge/pytorch/default/1/training\"\n\n# vision tower weight\nCLIP_path = \"/kaggle/input/clipvit-l14/pytorch/default/1\"\n\n# our model weight\nDETECTOR_YAML = default_path + \"/config/detector/d_brain.yaml\"\nWEIGHTS_PATH  = \"/kaggle/input/frame_acc_ckpts/pytorch/default/1/ckpt_best.pth\"\n\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(\"Device:\", device)\n\non_2060 = \"2060\" in (torch.cuda.get_device_name(0) if torch.cuda.is_available() else \"\")\n\n\ndef init_seed(cfg):\n    if cfg.get(\"manualSeed\") is None:\n        cfg[\"manualSeed\"] = random.randint(1, 10000)\n    random.seed(cfg[\"manualSeed\"])\n    torch.manual_seed(cfg[\"manualSeed\"])\n    if cfg.get(\"cuda\", True) and torch.cuda.is_available():\n        torch.cuda.manual_seed_all(cfg[\"manualSeed\"])\n\ndef prepare_testing_data(cfg):\n    def _make_loader(name):\n        cfg_local = cfg.copy()\n        cfg_local[\"test_dataset\"] = name\n        ds = DeepfakeAbstractBaseDataset(cfg_local, mode=\"test\")\n        return torch.utils.data.DataLoader(\n            ds,\n            batch_size=cfg_local[\"test_batchSize\"],\n            shuffle=False,\n            num_workers=int(cfg_local[\"workers\"]),\n            collate_fn=ds.collate_fn,\n            drop_last=False,\n        )\n    return {name: _make_loader(name) for name in cfg[\"test_dataset\"]}\n\ndef inference(model, data_dict):\n    with torch.no_grad():\n        return model(data_dict, inference=True)\n\ndef test_one_dataset(model, loader):\n    preds, labels, feats = [], [], []\n    for batch in tqdm(loader, leave=False):\n        data, lbl = batch[\"image\"].to(device), batch[\"label\"].to(device)\n        batch[\"image\"], batch[\"label\"] = data, torch.where(lbl != 0, 1, 0)\n        if batch.get(\"mask\") is not None:\n            batch[\"mask\"] = batch[\"mask\"].to(device)\n        if batch.get(\"landmark\") is not None:\n            batch[\"landmark\"] = batch[\"landmark\"].to(device)\n        out = inference(model, batch)\n        preds.extend(out[\"prob\"].cpu().numpy())\n        feats.extend(out[\"feat\"].cpu().numpy())\n        labels.extend(batch[\"label\"].cpu().numpy())\n    return np.asarray(preds), np.asarray(labels), np.asarray(feats)\n\ndef test_epoch(model, loaders, run_tag=\"run\"):\n    model.eval()\n    all_metrics = {}\n    for name, loader in loaders.items():\n        print(f\"\\n=== Evaluating {name} ===\")\n        preds, labels, _ = test_one_dataset(model, loader)\n        metrics = get_video_level_predictions(preds, loader.dataset.data_dict[\"image\"], threshold=0.5)\n        all_metrics[name] = metrics\n    return all_metrics","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:19:14.519653Z","iopub.execute_input":"2025-06-29T13:19:14.520459Z","iopub.status.idle":"2025-06-29T13:19:14.531626Z","shell.execute_reply.started":"2025-06-29T13:19:14.520428Z","shell.execute_reply":"2025-06-29T13:19:14.530969Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"video_folder_name = ['red_team_1', 'red_team_2', 'red_team_3']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:19:20.555468Z","iopub.execute_input":"2025-06-29T13:19:20.556321Z","iopub.status.idle":"2025-06-29T13:19:20.559835Z","shell.execute_reply.started":"2025-06-29T13:19:20.556295Z","shell.execute_reply":"2025-06-29T13:19:20.559112Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load YAML configs\nwith open(DETECTOR_YAML) as f:\n    cfg = yaml.safe_load(f)\nwith open(default_path + \"/config/test_config.yaml\") as f:\n    cfg_test = yaml.safe_load(f)\ncfg.update(cfg_test)\n\n\n# Manual overrides from notebook variables\ncfg[\"test_dataset\"]  = video_folder_name\ncfg[\"weights_path\"]  = WEIGHTS_PATH\ncfg[\"workers\"]       = 0 if on_2060 else 8\ncfg[\"cuda\"]          = torch.cuda.is_available()\n\ncfg['CLIP_path'] = CLIP_path\ncfg['dataset_json_folder'] = '/kaggle/working/dataset_json'\ncfg['base_path'] = '/kaggle/working/dataset/'\n\n\n# Init seed & cudnn\ninit_seed(cfg)\nif cfg.get(\"cudnn\", True):\n    cudnn.benchmark = True\n\n\n# Dataloaders\nloaders = prepare_testing_data(cfg)\nprint(\"Loaded test datasets:\", list(loaders.keys()))\n\n\n# Model\nmodel_cls = DETECTOR[cfg[\"model_name\"]]\nmodel     = model_cls(cfg).to(device)\nprint(\"Trainable params:\", sum(p.numel() for p in model.parameters() if p.requires_grad))\n\n\n# Checkpoint\nckpt_path = cfg[\"weights_path\"]\nif ckpt_path and os.path.exists(ckpt_path):\n    ckpt = torch.load(ckpt_path, map_location=device)\n    if \"state_dict\" in ckpt:\n        ckpt = ckpt[\"state_dict\"]\n    ckpt = {k.replace(\"module.\", \"\"): v for k, v in ckpt.items()}\n    # model.load_state_dict(ckpt, strict=True)\n    model.load_state_dict(ckpt, strict=False)\n    print(\"Checkpoint loaded.\")\nelse:\n    print(\"No checkpoint found, using random weights.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:19:22.839771Z","iopub.execute_input":"2025-06-29T13:19:22.840380Z","iopub.status.idle":"2025-06-29T13:19:57.320093Z","shell.execute_reply.started":"2025-06-29T13:19:22.840359Z","shell.execute_reply":"2025-06-29T13:19:57.319398Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Perform Inference\n\n- Run predictions on the test set","metadata":{}},{"cell_type":"code","source":"run_tag = os.path.basename(os.path.dirname(os.path.dirname(os.path.dirname(ckpt_path)))) if ckpt_path else \"no_ckpt\"\nmetrics = test_epoch(model, loaders, run_tag=run_tag)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:20:01.998702Z","iopub.execute_input":"2025-06-29T13:20:01.999431Z","iopub.status.idle":"2025-06-29T13:20:17.367778Z","shell.execute_reply.started":"2025-06-29T13:20:01.999408Z","shell.execute_reply":"2025-06-29T13:20:17.366650Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"---","metadata":{}},{"cell_type":"markdown","source":"## Generate Results","metadata":{}},{"cell_type":"markdown","source":"### Compute Final Score & Create Submission File","metadata":{"execution":{"iopub.status.busy":"2025-06-21T02:48:22.519357Z","iopub.execute_input":"2025-06-21T02:48:22.519999Z","iopub.status.idle":"2025-06-21T02:48:22.524727Z","shell.execute_reply.started":"2025-06-21T02:48:22.519974Z","shell.execute_reply":"2025-06-21T02:48:22.523848Z"}}},{"cell_type":"code","source":"from sklearn.metrics import precision_score, recall_score, f1_score, accuracy_score","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:26:17.068437Z","iopub.execute_input":"2025-06-29T13:26:17.069149Z","iopub.status.idle":"2025-06-29T13:26:17.072637Z","shell.execute_reply.started":"2025-06-29T13:26:17.069123Z","shell.execute_reply":"2025-06-29T13:26:17.071827Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### RED TEAM 1","metadata":{}},{"cell_type":"code","source":"video_folder_name[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:38:28.597735Z","iopub.execute_input":"2025-06-29T13:38:28.598382Z","iopub.status.idle":"2025-06-29T13:38:28.603329Z","shell.execute_reply.started":"2025-06-29T13:38:28.598355Z","shell.execute_reply":"2025-06-29T13:38:28.602575Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_df = pd.read_csv('/kaggle/working/dataset/red_team_1/red_team_1.csv')\n\npred_df = pd.DataFrame(metrics[video_folder_name[0]])\npred_df = pred_df.rename(columns={\n    'video_id': 'ID',\n    'pred_class': 'label'\n})\n\n# 확장자 없는 파일명 생성\nlabel_df['video_key'] = label_df['ID'].apply(lambda x: os.path.splitext(x)[0])\npred_df['video_key'] = pred_df['ID'].apply(lambda x: os.path.splitext(x)[0])\n\n# video_key 기준으로 merge\nmerged_df = pd.merge(label_df, pred_df[['video_key', 'label']], on='video_key', how='left')\n\n# 예측이 없는 경우 기본값 설정\nmerged_df['label'] = merged_df['label'].fillna(1).astype(int)\n\n# 평가용 컬럼 추출\ny_pred = merged_df['label']\ny_true = merged_df['true_label']\n\n# Metric 계산\nf1 = f1_score(y_true, y_pred)\nprecision = precision_score(y_true, y_pred)\nrecall = recall_score(y_true, y_pred)\naccuracy = accuracy_score(y_true, y_pred)\n\nprint(f\"Accuracy: {accuracy:.4f}\")\nprint(f\"F1-score: {f1:.4f}\")\nprint(f\"Precision: {precision:.4f}\")\nprint(f\"Recall: {recall:.4f}\")\n\n# 최종 제출 파일: label_df 의 ID 확장자 그대로 사용\nfinal_df = merged_df[['ID', 'label']]\nfinal_df.to_csv(\"submission_1.csv\", index=False, encoding='utf-8')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:38:32.507349Z","iopub.execute_input":"2025-06-29T13:38:32.507873Z","iopub.status.idle":"2025-06-29T13:38:32.533374Z","shell.execute_reply.started":"2025-06-29T13:38:32.507851Z","shell.execute_reply":"2025-06-29T13:38:32.532545Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### RED TEAM 2","metadata":{}},{"cell_type":"code","source":"video_folder_name[1]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:38:37.460690Z","iopub.execute_input":"2025-06-29T13:38:37.461617Z","iopub.status.idle":"2025-06-29T13:38:37.466278Z","shell.execute_reply.started":"2025-06-29T13:38:37.461589Z","shell.execute_reply":"2025-06-29T13:38:37.465507Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_df = pd.read_csv('/kaggle/working/dataset/red_team_2/red_team_2.csv')\n\npred_df = pd.DataFrame(metrics[video_folder_name[1]])\npred_df = pred_df.rename(columns={\n    'video_id': 'ID',\n    'pred_class': 'label'\n})\n\n# 확장자 없는 파일명 생성\nlabel_df['video_key'] = label_df['ID'].apply(lambda x: os.path.splitext(x)[0])\npred_df['video_key'] = pred_df['ID'].apply(lambda x: os.path.splitext(x)[0])\n\n# video_key 기준으로 merge\nmerged_df = pd.merge(label_df, pred_df[['video_key', 'label']], on='video_key', how='left')\n\n# 예측이 없는 경우 기본값 설정\nmerged_df['label'] = merged_df['label'].fillna(1).astype(int)\n\n# 평가용 컬럼 추출\ny_pred = merged_df['label']\ny_true = merged_df['true_label']\n\n# Metric 계산\nf1 = f1_score(y_true, y_pred)\nprecision = precision_score(y_true, y_pred)\nrecall = recall_score(y_true, y_pred)\naccuracy = accuracy_score(y_true, y_pred)\n\nprint(f\"Accuracy: {accuracy:.4f}\")\nprint(f\"F1-score: {f1:.4f}\")\nprint(f\"Precision: {precision:.4f}\")\nprint(f\"Recall: {recall:.4f}\")\n\n# 최종 제출 파일: label_df 의 ID 확장자 그대로 사용\nfinal_df = merged_df[['ID', 'label']]\nfinal_df.to_csv(\"submission_2.csv\", index=False, encoding='utf-8')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:38:37.636551Z","iopub.execute_input":"2025-06-29T13:38:37.636820Z","iopub.status.idle":"2025-06-29T13:38:37.660144Z","shell.execute_reply.started":"2025-06-29T13:38:37.636802Z","shell.execute_reply":"2025-06-29T13:38:37.659287Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### RED TEAM 3","metadata":{}},{"cell_type":"code","source":"video_folder_name[2]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:38:42.428130Z","iopub.execute_input":"2025-06-29T13:38:42.428406Z","iopub.status.idle":"2025-06-29T13:38:42.433456Z","shell.execute_reply.started":"2025-06-29T13:38:42.428387Z","shell.execute_reply":"2025-06-29T13:38:42.432703Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"label_df = pd.read_csv('/kaggle/working/dataset/red_team_3/red_team_3.csv')\n\npred_df = pd.DataFrame(metrics[video_folder_name[2]])\npred_df = pred_df.rename(columns={\n    'video_id': 'ID',\n    'pred_class': 'label'\n})\n\n# 확장자 없는 파일명 생성\nlabel_df['video_key'] = label_df['ID'].apply(lambda x: os.path.splitext(x)[0])\npred_df['video_key'] = pred_df['ID'].apply(lambda x: os.path.splitext(x)[0])\n\n# video_key 기준으로 merge\nmerged_df = pd.merge(label_df, pred_df[['video_key', 'label']], on='video_key', how='left')\n\n# 예측이 없는 경우 기본값 설정\nmerged_df['label'] = merged_df['label'].fillna(1).astype(int)\n\n# 평가용 컬럼 추출\ny_pred = merged_df['label']\ny_true = merged_df['true_label']\n\n# Metric 계산\nf1 = f1_score(y_true, y_pred)\nprecision = precision_score(y_true, y_pred)\nrecall = recall_score(y_true, y_pred)\naccuracy = accuracy_score(y_true, y_pred)\n\nprint(f\"Accuracy: {accuracy:.4f}\")\nprint(f\"F1-score: {f1:.4f}\")\nprint(f\"Precision: {precision:.4f}\")\nprint(f\"Recall: {recall:.4f}\")\n\n# 최종 제출 파일: label_df 의 ID 확장자 그대로 사용\nfinal_df = merged_df[['ID', 'label']]\nfinal_df.to_csv(\"submission_3.csv\", index=False, encoding='utf-8')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:38:42.603768Z","iopub.execute_input":"2025-06-29T13:38:42.604100Z","iopub.status.idle":"2025-06-29T13:38:42.626164Z","shell.execute_reply.started":"2025-06-29T13:38:42.604077Z","shell.execute_reply":"2025-06-29T13:38:42.625483Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"---","metadata":{}},{"cell_type":"code","source":"# !rm -rf /kaggle/working/preprocessing_logs\n# !rm -rf /kaggle/working/dataset_json\n# !rm -rf /kaggle/working/datasets","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-29T13:37:45.559478Z","iopub.execute_input":"2025-06-29T13:37:45.559758Z","iopub.status.idle":"2025-06-29T13:37:45.563475Z","shell.execute_reply.started":"2025-06-29T13:37:45.559738Z","shell.execute_reply":"2025-06-29T13:37:45.562667Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"---","metadata":{}}]}