{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Efficientnet Single Model\n\n---\n\n## BaseModel:\n\n- Efficientnet-b0(Pretrained)\n\n## Stats:\n\n- Optimizer: Adam\n\n- lr: 0.001\n\n- Schedular: StepLR\n\n- Epochs: 15\n\n- Face Detector: MTCNN\n\n---\n\n## What I was careful about:\n\n- Adjust imbalanced data\n\n- Train data is Only 15 images from 1 Movie"},{"metadata":{},"cell_type":"markdown","source":"---\n\n## History\n\n- V3: Fixed \"ImageTransform\" Class (Resize)"},{"metadata":{},"cell_type":"markdown","source":"---\n## Library Install"},{"metadata":{"trusted":true},"cell_type":"code","source":"%%capture\n# https://www.kaggle.com/timesler/facial-recognition-model-in-pytorch\n# Install facenet-pytorch\n!pip install /kaggle/input/facenet-pytorch-vggface2/facenet_pytorch-1.0.1-py3-none-any.whl\n# Copy model checkpoints to torch cache so they are loaded automatically by the package\n!mkdir -p /tmp/.cache/torch/checkpoints/\n!cp /kaggle/input/facenet-pytorch-vggface2/20180402-114759-vggface2-logits.pth /tmp/.cache/torch/checkpoints/vggface2_DG3kwML46X.pt\n!cp /kaggle/input/facenet-pytorch-vggface2/20180402-114759-vggface2-features.pth /tmp/.cache/torch/checkpoints/vggface2_G5aNV2VSMn.pt","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","trusted":true},"cell_type":"code","source":"%matplotlib inline\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport random\nimport os\nimport gc\nimport cv2\nimport glob\nimport time\nimport copy\nfrom tqdm import tqdm_notebook as tqdm\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader, Dataset\nimport torch.nn.functional as F\nimport torchvision\nfrom torchvision import models, transforms\nfrom facenet_pytorch import MTCNN, InceptionResnetV1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import sys\npackage_path = '../input/efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master'\nsys.path.append(package_path)\n\nfrom efficientnet_pytorch import EfficientNet","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def seed_everything(seed=1234):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"seed_everything(0)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"---\n## Pretrained Weights"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Set Trained Weight Path\nweight_path = 'efficientnet_b0_epoch_15_loss_0.158.pth'\ntrained_weights_path = os.path.join('../input/deepfake-detection-model-weight', weight_path)\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\ntorch.backends.cudnn.benchmark=True","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_dir = '../input/deepfake-detection-challenge/test_videos'\nos.listdir(test_dir)[:5]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"---\n## Helper function"},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_img_from_mov(video_file, num_img, frame_window):\n    # https://note.nkmk.me/python-opencv-videocapture-file-camera/\n    cap = cv2.VideoCapture(video_file)\n    frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))\n\n    image_list = []\n    for i in range(num_img):\n        _, image = cap.read()\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        image_list.append(image)\n        cap.set(cv2.CAP_PROP_POS_FRAMES, (i + 1) * frame_window)\n        if cap.get(cv2.CAP_PROP_POS_FRAMES) >= frames:\n            break\n    cap.release()\n\n    return image_list","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class ImageTransform:\n    def __init__(self, size, mean, std):\n        self.data_transform = transforms.Compose([\n                transforms.Resize((size, size), interpolation=Image.BILINEAR),\n                transforms.ToTensor(),\n                transforms.Normalize(mean, std)\n            ])\n\n    def __call__(self, img):\n        return self.data_transform(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class DeepfakeDataset(Dataset):\n    def __init__(self, file_list, device, detector, transform, img_num=20, frame_window=10):\n        self.file_list = file_list\n        self.device = device\n        self.detector = detector\n        self.transform = transform\n        self.img_num = img_num\n        self.frame_window = frame_window\n\n    def __len__(self):\n        return len(self.file_list)\n\n    def __getitem__(self, idx):\n\n        mov_path = self.file_list[idx]\n        img_list = []\n\n        # Movie to Image\n        try:\n            all_image = get_img_from_mov(mov_path, self.img_num, self.frame_window)\n        except:\n            return [], mov_path.split('/')[-1]\n        \n        # Detect Faces\n        for image in all_image:\n            \n            try:\n                _image = image[np.newaxis, :, :, :]\n                boxes, probs = self.detector.detect(_image, landmarks=False)\n                x = int(boxes[0][0][0])\n                y = int(boxes[0][0][1])\n                z = int(boxes[0][0][2])\n                w = int(boxes[0][0][3])\n                image = image[y-15:w+15, x-15:z+15]\n                \n                # Preprocessing\n                image = Image.fromarray(image)\n                image = self.transform(image)\n                \n                img_list.append(image)\n\n            except:\n                img_list.append(None)\n            \n        # Padding None\n        img_list = [c for c in img_list if c is not None]\n        \n        return img_list, mov_path.split('/')[-1]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"---\n## Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"model = EfficientNet.from_name('efficientnet-b0')\nmodel._fc = nn.Linear(in_features=model._fc.in_features, out_features=1)\nmodel.load_state_dict(torch.load(trained_weights_path, map_location=torch.device(device)))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"---\n## Prediction"},{"metadata":{"trusted":true},"cell_type":"code","source":"test_file = [os.path.join(test_dir, path) for path in os.listdir(test_dir)]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_file[:5]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Prediction\ndef predict_dfdc(dataset, model):\n    \n    torch.cuda.empty_cache()\n    pred_list = []\n    path_list = []\n    \n    model = model.to(device)\n    model.eval()\n\n    with torch.no_grad():\n        for i in tqdm(range(len(dataset))):\n            pred = 0\n            imgs, mov_path = dataset.__getitem__(i)\n            \n            # No get Image\n            if len(imgs) == 0:\n                pred_list.append(0.5)\n                path_list.append(mov_path)\n                continue\n                \n                \n            for i in range(len(imgs)):\n                img = imgs[i]\n                \n                output = model(img.unsqueeze(0).to(device))\n                pred += torch.sigmoid(output).item() / len(imgs)\n                \n            pred_list.append(pred)\n            path_list.append(mov_path)\n            \n    torch.cuda.empty_cache()\n            \n    return path_list, pred_list","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Config\nimg_size = 120\nimg_num = 15\nframe_window = 5\nmean = (0.485, 0.456, 0.406)\nstd = (0.229, 0.224, 0.225)\n\ntransform = ImageTransform(img_size, mean, std)\n\ndetector = MTCNN(image_size=img_size, margin=14, keep_all=False, factor=0.5, \n                 select_largest=False, post_process=False, device=device).eval()\n\ndataset = DeepfakeDataset(test_file, device, detector, transform, img_num, frame_window)\n\npath_list, pred_list = predict_dfdc(dataset, model)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"---\n## Submission"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Submission\nres = pd.DataFrame({\n    'filename': path_list,\n    'label': pred_list,\n})\n\nres.sort_values(by='filename', ascending=True, inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.hist(res['label'], 20)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"res.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"res.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]}],"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.6.6"},"widgets":{"application/vnd.jupyter.widget-state+json":{"state":{"0aa9b197a8d940bda837f16c4e4f77a1":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"ProgressStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"ProgressStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","bar_color":null,"description_width":"initial"}},"12a1eeb2a3fb4cb9bc89c5473cdefcc0":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"3d3dbed6c0414f6e9e614d03621305e2":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"55b61a807f784cd1a75657b8fd8672af":{"model_module":"@jupyter-widgets/base","model_module_version":"1.2.0","model_name":"LayoutModel","state":{"_model_module":"@jupyter-widgets/base","_model_module_version":"1.2.0","_model_name":"LayoutModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"LayoutView","align_content":null,"align_items":null,"align_self":null,"border":null,"bottom":null,"display":null,"flex":null,"flex_flow":null,"grid_area":null,"grid_auto_columns":null,"grid_auto_flow":null,"grid_auto_rows":null,"grid_column":null,"grid_gap":null,"grid_row":null,"grid_template_areas":null,"grid_template_columns":null,"grid_template_rows":null,"height":null,"justify_content":null,"justify_items":null,"left":null,"margin":null,"max_height":null,"max_width":null,"min_height":null,"min_width":null,"object_fit":null,"object_position":null,"order":null,"overflow":null,"overflow_x":null,"overflow_y":null,"padding":null,"right":null,"top":null,"visibility":null,"width":null}},"6cc5e0c3a18342b2b39112289122de3b":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"IntProgressModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"IntProgressModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"ProgressView","bar_style":"success","description":"100%","description_tooltip":null,"layout":"IPY_MODEL_55b61a807f784cd1a75657b8fd8672af","max":400,"min":0,"orientation":"horizontal","style":"IPY_MODEL_0aa9b197a8d940bda837f16c4e4f77a1","value":400}},"902cf66c7ae349c7b0264d95ec39fede":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"HTMLModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HTMLModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HTMLView","description":"","description_tooltip":null,"layout":"IPY_MODEL_12a1eeb2a3fb4cb9bc89c5473cdefcc0","placeholder":"​","style":"IPY_MODEL_f10eb3086ca1493d979e0d992a85f79a","value":" 400/400 [41:25&lt;00:00,  6.21s/it]"}},"c80cee47cd1e48d8b52090249d2bfca6":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"HBoxModel","state":{"_dom_classes":[],"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"HBoxModel","_view_count":null,"_view_module":"@jupyter-widgets/controls","_view_module_version":"1.5.0","_view_name":"HBoxView","box_style":"","children":["IPY_MODEL_6cc5e0c3a18342b2b39112289122de3b","IPY_MODEL_902cf66c7ae349c7b0264d95ec39fede"],"layout":"IPY_MODEL_3d3dbed6c0414f6e9e614d03621305e2"}},"f10eb3086ca1493d979e0d992a85f79a":{"model_module":"@jupyter-widgets/controls","model_module_version":"1.5.0","model_name":"DescriptionStyleModel","state":{"_model_module":"@jupyter-widgets/controls","_model_module_version":"1.5.0","_model_name":"DescriptionStyleModel","_view_count":null,"_view_module":"@jupyter-widgets/base","_view_module_version":"1.2.0","_view_name":"StyleView","description_width":""}}},"version_major":2,"version_minor":0}}},"nbformat":4,"nbformat_minor":4}