{"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":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}