{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.6.6","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"},{"sourceId":9422294,"sourceType":"datasetVersion","datasetId":5723118}],"dockerImageVersionId":29844,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-09-17T20:01:19.452607Z","iopub.execute_input":"2024-09-17T20:01:19.452905Z","iopub.status.idle":"2024-09-17T20:01:20.114098Z","shell.execute_reply.started":"2024-09-17T20:01:19.452863Z","shell.execute_reply":"2024-09-17T20:01:20.113366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.models import Sequential, load_model\nfrom tensorflow.keras.layers import Conv2D, MaxPool2D, Dropout, Dense, Flatten, BatchNormalization, Activation, \\\n    Dropout, MaxPooling2D, Concatenate, GlobalMaxPooling2D, GlobalAveragePooling2D, \\\n    Lambda, Multiply, LSTM, Bidirectional, PReLU, MaxPooling1D\nfrom tensorflow.keras.applications.nasnet import NASNetMobile, NASNetLarge, preprocess_input\nfrom tensorflow.keras.optimizers import Adam, RMSprop\nfrom tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau\nfrom tensorflow.keras.optimizers import Adagrad\nfrom sklearn.model_selection import train_test_split\n#from sklearn.metrics import accuracy_score\nfrom tensorflow.keras.preprocessing.image import load_img, array_to_img, ImageDataGenerator\nfrom PIL import Image\n#from sklearn.preprocessing import OneHotEncoder\nfrom tensorflow.keras import Input, Model\nfrom imgaug import augmenters as iaa\nimport imgaug as ia\nfrom glob import glob\nfrom random import shuffle\nimport matplotlib.pyplot as plt\nimport cv2\nimport os\n","metadata":{"execution":{"iopub.status.busy":"2024-09-17T20:01:20.116393Z","iopub.execute_input":"2024-09-17T20:01:20.116626Z","iopub.status.idle":"2024-09-17T20:01:20.126902Z","shell.execute_reply.started":"2024-09-17T20:01:20.116587Z","shell.execute_reply":"2024-09-17T20:01:20.125813Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Getting files from server\ntrain_dir = os.path.join(\"/kaggle/input/dfdc-train-part-46/dfdc_train_part_46\")\ntest_dir = os.path.join(\"/kaggle/input/deepfake-detection-challenge/test_videos\")\n\ntrain_len = len(os.listdir(train_dir))  # Total test files\ntest_len = len(os.listdir(test_dir))  # Total test files\n\nprint('total training deepfake videos:', len(os.listdir(train_dir)))\nprint('total testing deepfake videos:', len(os.listdir(test_dir)))\n\nlabeled_files_train = glob(train_dir+'/*.mp4')\nlabeled_files_test = glob(test_dir+'/*.mp4')\n","metadata":{"execution":{"iopub.status.busy":"2024-09-17T20:01:20.128800Z","iopub.execute_input":"2024-09-17T20:01:20.129161Z","iopub.status.idle":"2024-09-17T20:01:20.261920Z","shell.execute_reply.started":"2024-09-17T20:01:20.129101Z","shell.execute_reply":"2024-09-17T20:01:20.261211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#removing files with less than 150 videos\nimport json\nimport copy\n\n# Change the path accordingly\n#video_files = glob('../content/Real videos/*.mp4')\n#video_files1 = glob('../content/dfdc_train_part_8/*.mp4')\n#video_files += video_files1\n\nframe_count = []\n\nfor video_file in labeled_files_train:\n    cap = cv2.VideoCapture(video_file)\n\n    if int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) < 150:\n        labeled_files_train.remove(video_file)\n        continue\n\n    frame_count.append(int(cap.get(cv2.CAP_PROP_FRAME_COUNT)))\n\nprint(\"frames\", frame_count)\nprint(\"Total number of videos:\", len(frame_count))\nprint('Average frame per video:', np.mean(frame_count))\n\nlabeled_files_train = sorted(labeled_files_train)\n\nprint(len(labeled_files_train))\n","metadata":{"execution":{"iopub.status.busy":"2024-09-17T20:01:20.263274Z","iopub.execute_input":"2024-09-17T20:01:20.263547Z","iopub.status.idle":"2024-09-17T20:01:50.578647Z","shell.execute_reply.started":"2024-09-17T20:01:20.263483Z","shell.execute_reply":"2024-09-17T20:01:50.577739Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Function to extract frame from videos\ndef frame_extract(path):\n    vidobj = cv2.VideoCapture(path)\n    success = True\n\n    while success:\n        success, image = vidobj.read()\n\n        if success:\n            yield image\n","metadata":{"execution":{"iopub.status.busy":"2024-09-17T20:01:50.581680Z","iopub.execute_input":"2024-09-17T20:01:50.582031Z","iopub.status.idle":"2024-09-17T20:01:50.587528Z","shell.execute_reply.started":"2024-09-17T20:01:50.581967Z","shell.execute_reply":"2024-09-17T20:01:50.586526Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport json\nimport pandas as pd\n\n# Load the metadata from the JSON file\nmetadata_path = '/kaggle/input/dfdc-train-part-46/dfdc_train_part_46/metadata.json'\n\nwith open(metadata_path, 'r') as f:\n    metadata = json.load(f)\n\n# Convert metadata to a DataFrame\nlabel_data = pd.DataFrame({\n    'video': list(metadata.keys()),   # Video filenames\n    'labels': [1 if metadata[k]['label'] == 'FAKE' else 0 for k in metadata]  # 1 for FAKE, 0 for REAL\n})\n\n# Preview the label_data\nprint(label_data.head())\n","metadata":{"execution":{"iopub.status.busy":"2024-09-17T20:01:50.589157Z","iopub.execute_input":"2024-09-17T20:01:50.589480Z","iopub.status.idle":"2024-09-17T20:01:50.609024Z","shell.execute_reply.started":"2024-09-17T20:01:50.589422Z","shell.execute_reply":"2024-09-17T20:01:50.608385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create id_label_map safely depending on structure of label_data\nif isinstance(label_data['video'], list):\n    id_label_map = {os.path.splitext(k)[0]: v for k, v in zip(label_data['video'], label_data['labels'])}\nelse:  # Assuming label_data is a DataFrame\n    id_label_map = {os.path.splitext(k)[0]: v for k, v in zip(label_data['video'].values, label_data['labels'].values)}\n\n# Function to break dataset into batches\ndef chunker(seq, size):\n    return (seq[pos:pos + size] for pos in range(0, len(seq), size))\n\n# Function to resize frames and normalize them for training\ndef train_transform(frame):\n    x = cv2.resize(frame, (224, 224))\n    normalized_array = np.zeros((x.shape))\n    normalized_array = cv2.normalize(x, normalized_array, 0, 255, cv2.NORM_MINMAX)\n    return normalized_array / 255\n\n# Generator for getting a numpy array of image frames and labels\ndef data_gen(label_data, id_label_map, batch_size=32, seq_len=60):\n    while True:\n        shuffle(label_data)\n        for batch in chunker(label_data, batch_size):\n            X = []\n            Y = []\n            for x in batch:\n                # Remove the file extension before accessing the map\n                label = id_label_map[os.path.splitext(os.path.basename(x))[0]]\n                frames = []\n                frame_labels = []\n                for i, frame in enumerate(frame_extract(x)):\n                    frames.append(train_transform(frame))\n                    frame_labels.append(label)\n                    if len(frames) == seq_len:\n                        break\n                frames = np.stack(frames)\n                frames = frames[:seq_len]\n                frame_labels = np.stack(frame_labels)\n                frame_labels = frame_labels[:seq_len]\n                X.append(frames)\n                Y.append(label)\n                print(np.asarray(X).shape)\n            X = np.asarray(X)\n            Y = np.asarray(Y)\n            batch_size, seq_length, c, h, w = X.shape\n            X = np.reshape(X, (batch_size, seq_length, c, h, w))\n            yield X, Y\n","metadata":{"execution":{"iopub.status.busy":"2024-09-17T20:01:50.610263Z","iopub.execute_input":"2024-09-17T20:01:50.610522Z","iopub.status.idle":"2024-09-17T20:01:50.634725Z","shell.execute_reply.started":"2024-09-17T20:01:50.610458Z","shell.execute_reply":"2024-09-17T20:01:50.634021Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.layers import LeakyReLU\nfrom tensorflow.keras.layers import TimeDistributed\nfrom tensorflow.keras.applications.resnet50 import ResNet50\nseq_len=10\ninputs = Input((seq_len, 224, 224, 3))\nresnet = ResNet50(include_top=False, input_shape=(224, 224, 3), weights='imagenet')\nfor layer in resnet.layers:\n    layer.trainable = False\n# x = resnet.layers[-1].output\noutput = GlobalAveragePooling2D()(resnet.output)\n# output=resnet.layers[-1].output\ncnn = Model(inputs=resnet.input, outputs=output)\nencoded_frames = TimeDistributed(cnn)(inputs)\nlstm = LSTM(2048)(encoded_frames)\nout_leaky = LeakyReLU()(lstm)\nout_drop = Dropout(0.4)(out_leaky)\nout_dense = Dense(2048, input_dim=inputs, activation=\"relu\")(out_drop)\nout_1 = Dense(1, activation=\"sigmoid\")(out_dense)\nmodel = Model(inputs=[inputs], outputs=out_1)\nmodel.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy', tf.keras.metrics.AUC()])\nmodel.summary()\n","metadata":{"execution":{"iopub.status.busy":"2024-09-17T20:01:50.635924Z","iopub.execute_input":"2024-09-17T20:01:50.636209Z","iopub.status.idle":"2024-09-17T20:02:03.199796Z","shell.execute_reply.started":"2024-09-17T20:01:50.636153Z","shell.execute_reply":"2024-09-17T20:02:03.198785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint\n\n# Define the EarlyStopping callback to stop training when the model stops improving\nearly_stopping = EarlyStopping(\n    monitor='val_loss',  # Monitors the validation loss\n    patience=5,          # Number of epochs with no improvement after which training will be stopped\n    mode='min',          # Stops when the monitored quantity has stopped decreasing\n    verbose=1            # Prints a message when early stopping occurs\n)","metadata":{"execution":{"iopub.status.busy":"2024-09-17T20:14:17.157118Z","iopub.execute_input":"2024-09-17T20:14:17.157443Z","iopub.status.idle":"2024-09-17T20:14:17.162447Z","shell.execute_reply.started":"2024-09-17T20:14:17.157400Z","shell.execute_reply":"2024-09-17T20:14:17.161711Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Validate videos and handle corrupted videos\ndef validate_video(vid_path, train_transforms):\n    frames = []\n    for i, frame in enumerate(frame_extract(vid_path)):\n        frames.append(train_transforms(frame))\n        if len(frames) == 10:  # seq_len = 10\n            break\n    frames = np.stack(frames)\n    frames = frames[:10]  # Ensure frame count is 10\n    return frames\n\ncount = 0\ncorrupt_list = []\n\nlabel_data = np.array(labeled_files_train)  # Assuming label_data refers to training files\nfor i in range(len(label_data)):\n    video_path = label_data[i]\n    try:\n        validate_video(video_path, train_transform)\n        count += 1\n        print(\"Number of videos processed:\", count, \"Remaining:\", len(label_data) - count)\n    except:\n        corrupt_list.append(video_path)\n        print(\"Corrupted video:\", count, \"video_path:\", video_path)\n        continue\n\nprint(len(label_data) - count)\nlabel_data = label_data[~label_data['video_path'].isin(corrupt_list)]\n\n# Split the dataset into train and validation sets\ntrain, valid = train_test_split(label_data, test_size=0.2, random_state=0)\ntrain.reset_index(drop=True ,inplace = True)\nvalid.reset_index(drop=True ,inplace = True)\n\n# Training Parameters\nbatch_size = 10\nseq_len = 10  # Sequence length for video frames\ntrain_steps = int(np.ceil(len(train) / (batch_size)))\nval_steps = int(np.ceil(len(valid) / (batch_size)))\n\n# Model Checkpoint\ncheckpoint_path = \"best_model.h5\"\ncheckpoint = ModelCheckpoint(checkpoint_path, monitor='val_accuracy', verbose=1, save_best_only=True, mode='max')\nhistory = 0\n\n# Training the Model\nwith tf.device('/GPU:0'):\n    history = model.fit(data_gen(train.loc[:,\"video_path\"], id_label_map, batch_size, seq_len), \n                        steps_per_epoch=train_steps, \n                        validation_data=data_gen(valid, id_label_map, batch_size, seq_len), \n                        validation_steps=val_steps, \n                        epochs=20, \n                        callbacks=[checkpoint,early_stopping])","metadata":{"execution":{"iopub.status.busy":"2024-09-17T20:16:19.871615Z","iopub.execute_input":"2024-09-17T20:16:19.871953Z","iopub.status.idle":"2024-09-17T20:20:27.265619Z","shell.execute_reply.started":"2024-09-17T20:16:19.871902Z","shell.execute_reply":"2024-09-17T20:20:27.264127Z"},"trusted":true},"execution_count":null,"outputs":[]}]}