{"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":"none","dataSources":[{"sourceId":16880,"databundleVersionId":858837,"sourceType":"competition"}],"dockerImageVersionId":29844,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport numpy as np\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.models import Sequential, Model\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, GlobalAveragePooling2D\nfrom tensorflow.keras.applications import Xception, InceptionV3, MobileNet\nfrom tensorflow.keras.optimizers import Adam, RMSprop\nfrom tensorflow.keras.callbacks import EarlyStopping\nfrom sklearn.ensemble import VotingClassifier\nfrom sklearn.metrics import classification_report, confusion_matrix, accuracy_score, precision_score, recall_score, f1_score\nimport random\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array, array_to_img\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom collections import Counter\n\n# Define the data paths - UPDATED FOLDER NAME\ntrain_data_dir = '/kaggle/input/deepfake-detection-challenge/train_sample_videos'\ntest_data_dir = '/kaggle/input/deepfake-detection-challenge/test_videos'\n\n# Image preprocessing settings\nimg_width, img_height = 256, 256\nbatch_size = 64\n\ndef visualize_sample_images(data_dir, num_samples=5):\n    \"\"\"Visualize sample images from each class in the dataset\"\"\"\n    classes = os.listdir(data_dir)\n    for class_name in classes:\n        class_dir = os.path.join(data_dir, class_name)\n        images = os.listdir(class_dir)\n        sample_images = random.sample(images, min(num_samples, len(images)))\n        \n        plt.figure(figsize=(10, 5))\n        for i, image_name in enumerate(sample_images):\n            image_path = os.path.join(class_dir, image_name)\n            image = load_img(image_path)\n            plt.subplot(1, len(sample_images), i+1)\n            plt.imshow(image)\n            plt.title(class_name)\n            plt.axis('off')\n        plt.show()\n\n# Visualize sample images from all sets\nprint(\"Training Set Sample Images:\")\nvisualize_sample_images(train_data_dir)\nprint(\"Validation Set Sample Images:\")\nvisualize_sample_images(valid_data_dir)\nprint(\"Test Set Sample Images:\")\nvisualize_sample_images(test_data_dir)\n\ndef plot_class_distribution(data_dir, title):\n    \"\"\"Plot the distribution of classes in the dataset\"\"\"\n    classes = os.listdir(data_dir)\n    num_samples_per_class = [len(os.listdir(os.path.join(data_dir, class_name))) for class_name in classes]\n    \n    plt.figure(figsize=(8, 5))\n    plt.bar(classes, num_samples_per_class)\n    plt.xlabel('Class')\n    plt.ylabel('Number of Samples')\n    plt.title(title)\n    plt.xticks(rotation=45)\n    plt.tight_layout()\n    plt.show()\n\n# Plot class distribution for all sets\nplot_class_distribution(train_data_dir, 'Training Set Class Distribution')\nplot_class_distribution(valid_data_dir, 'Validation Set Class Distribution')\nplot_class_distribution(test_data_dir, 'Test Set Class Distribution')\n\n# Data generators with augmentation for training and validation\ntrain_datagen = ImageDataGenerator(\n    rescale=1./255,\n    shear_range=0.2,\n    zoom_range=0.2,\n    horizontal_flip=True,\n    rotation_range=20\n)\n\nvalid_datagen = ImageDataGenerator(rescale=1./255)\ntest_datagen = ImageDataGenerator(rescale=1./255)\n\ntrain_generator = train_datagen.flow_from_directory(\n    train_data_dir,\n    target_size=(img_width, img_height),\n    batch_size=batch_size,\n    class_mode='binary'\n)\n\nvalidation_generator = valid_datagen.flow_from_directory(\n    valid_data_dir,\n    target_size=(img_width, img_height),\n    batch_size=batch_size,\n    class_mode='binary'\n)\n\ntest_generator = test_datagen.flow_from_directory(\n    test_data_dir,\n    target_size=(img_width, img_height),\n    batch_size=batch_size,\n    class_mode='binary',\n    shuffle=False\n)\n\ndef visualize_augmented_images(data_generator, num_samples=5):\n    \"\"\"Visualize augmented images from the data generator\"\"\"\n    plt.figure(figsize=(12, 6))\n    batch_x, batch_y = next(data_generator)\n    \n    for i in range(min(num_samples, len(batch_x))):\n        plt.subplot(1, num_samples, i + 1)\n        plt.imshow(batch_x[i])\n        plt.axis('off')\n        plt.title(f'Label: {int(batch_y[i])}')\n    plt.show()\n\n# Visualize augmented images from the training generator\nprint(\"Augmented Training Images:\")\nvisualize_augmented_images(train_generator)\n\ndef visualize_original_and_augmented(image_path, data_generator, num_augmented=5):\n    \"\"\"Show original image alongside its augmented versions\"\"\"\n    original_image = load_img(image_path)\n    image_array = img_to_array(original_image)\n    image_array = np.expand_dims(image_array, axis=0)\n    \n    aug_iter = data_generator.flow(image_array, batch_size=1)\n    \n    plt.figure(figsize=(15, 3))\n    plt.subplot(1, num_augmented + 1, 1)\n    plt.imshow(original_image)\n    plt.title(\"Original\")\n    plt.axis('off')\n    \n    for i in range(num_augmented):\n        augmented_image = next(aug_iter)[0]\n        plt.subplot(1, num_augmented + 1, i + 2)\n        plt.imshow(array_to_img(augmented_image))\n        plt.title(f\"Aug {i+1}\")\n        plt.axis('off')\n    \n    plt.tight_layout()\n    plt.show()\n\ndef get_random_image_paths(root_dir, num_samples=10, extensions=('.jpg', '.png', '.jpeg')):\n    \"\"\"Get random image paths from the directory\"\"\"\n    image_paths = []\n    for dirpath, dirnames, filenames in os.walk(root_dir):\n        for file in filenames:\n            if file.lower().endswith(extensions):\n                image_paths.append(os.path.join(dirpath, file))\n    \n    return random.sample(image_paths, min(num_samples, len(image_paths)))\n\n# Get random sample paths and visualize augmentations - UPDATED PATH\nsample_paths = get_random_image_paths('/kaggle/input/faceforensic1600-videospreprocess', num_samples=3)\nprint(\"Original vs Augmented Images:\")\nfor image_path in sample_paths:\n    visualize_original_and_augmented(image_path, train_datagen, num_augmented=5)\n\n# Calculate steps per epoch\ntrain_steps_per_epoch = train_generator.samples // batch_size\nvalid_steps_per_epoch = validation_generator.samples // batch_size\n\nprint(f\"Training steps per epoch: {train_steps_per_epoch}\")\nprint(f\"Validation steps per epoch: {valid_steps_per_epoch}\")\n\n# 1. CNN Model\ndef create_cnn_model():\n    \"\"\"Create a simple CNN model\"\"\"\n    model = Sequential([\n        Conv2D(32, (3,3), activation='relu', input_shape=(img_height, img_width, 3)),\n        MaxPooling2D(2, 2),\n        Conv2D(64, (3,3), activation='relu'),\n        MaxPooling2D(2, 2),\n        Conv2D(128, (3,3), activation='relu'),\n        MaxPooling2D(2, 2),\n        Flatten(),\n        Dense(512, activation='relu'),\n        Dropout(0.5),\n        Dense(1, activation='sigmoid')\n    ])\n    return model\n\nmodel_cnn = create_cnn_model()\nmodel_cnn.compile(\n    loss='binary_crossentropy',\n    optimizer=RMSprop(learning_rate=0.001),\n    metrics=['accuracy']\n)\n\nprint(\"CNN Model Summary:\")\nmodel_cnn.summary()\n\n# Train CNN model\nearly_stopping = EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True)\n\nprint(\"Training CNN Model...\")\nhistory_cnn = model_cnn.fit(\n    train_generator,\n    steps_per_epoch=train_steps_per_epoch,\n    epochs=20,\n    validation_data=validation_generator,\n    validation_steps=valid_steps_per_epoch,\n    verbose=1,\n    callbacks=[early_stopping]\n)\n\n# Plot CNN training history\nplt.figure(figsize=(12, 6))\nplt.subplot(1, 2, 1)\nplt.plot(history_cnn.history['accuracy'])\nplt.plot(history_cnn.history['val_accuracy'])\nplt.title('CNN Model Accuracy')\nplt.ylabel('Accuracy')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper left')\n\nplt.subplot(1, 2, 2)\nplt.plot(history_cnn.history['loss'])\nplt.plot(history_cnn.history['val_loss'])\nplt.title('CNN Model Loss')\nplt.ylabel('Loss')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper left')\nplt.show()\n\n# 2. Xception Model\ndef create_xception_model():\n    \"\"\"Create Xception-based model\"\"\"\n    base_model = Xception(weights='imagenet', include_top=False, input_shape=(img_height, img_width, 3))\n    x = base_model.output\n    x = GlobalAveragePooling2D()(x)\n    x = Dense(128, activation='relu')(x)\n    x = Dropout(0.5)(x)\n    predictions = Dense(1, activation='sigmoid')(x)\n    model = Model(inputs=base_model.input, outputs=predictions)\n    return model\n\nxception_model = create_xception_model()\nxception_model.compile(\n    optimizer=Adam(learning_rate=0.0001),\n    loss='binary_crossentropy',\n    metrics=['accuracy']\n)\n\nprint(\"Training Xception Model...\")\nhistory_xception = xception_model.fit(\n    train_generator,\n    steps_per_epoch=train_steps_per_epoch,\n    epochs=10,\n    validation_data=validation_generator,\n    validation_steps=valid_steps_per_epoch,\n    callbacks=[early_stopping]\n)\n\n# Plot Xception training history\nplt.figure(figsize=(12, 6))\nplt.subplot(1, 2, 1)\nplt.plot(history_xception.history['accuracy'])\nplt.plot(history_xception.history['val_accuracy'])\nplt.title('Xception Model Accuracy')\nplt.ylabel('Accuracy')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper left')\n\nplt.subplot(1, 2, 2)\nplt.plot(history_xception.history['loss'])\nplt.plot(history_xception.history['val_loss'])\nplt.title('Xception Model Loss')\nplt.ylabel('Loss')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper left')\nplt.show()\n\n# 3. InceptionV3 Model\ndef create_inception_model():\n    \"\"\"Create InceptionV3-based model\"\"\"\n    base_model = InceptionV3(weights='imagenet', include_top=False, input_shape=(img_height, img_width, 3))\n    x = base_model.output\n    x = GlobalAveragePooling2D()(x)\n    x = Dense(128, activation='relu')(x)\n    x = Dropout(0.5)(x)\n    predictions = Dense(1, activation='sigmoid')(x)\n    model = Model(inputs=base_model.input, outputs=predictions)\n    return model\n\ninception_model = create_inception_model()\ninception_model.compile(\n    optimizer=Adam(learning_rate=0.0001),\n    loss='binary_crossentropy',\n    metrics=['accuracy']\n)\n\nprint(\"Training InceptionV3 Model...\")\nhistory_inception = inception_model.fit(\n    train_generator,\n    steps_per_epoch=train_steps_per_epoch,\n    epochs=10,\n    validation_data=validation_generator,\n    validation_steps=valid_steps_per_epoch,\n    callbacks=[early_stopping]\n)\n\n# Plot InceptionV3 training history\nplt.figure(figsize=(12, 6))\nplt.subplot(1, 2, 1)\nplt.plot(history_inception.history['accuracy'])\nplt.plot(history_inception.history['val_accuracy'])\nplt.title('InceptionV3 Model Accuracy')\nplt.ylabel('Accuracy')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper left')\n\nplt.subplot(1, 2, 2)\nplt.plot(history_inception.history['loss'])\nplt.plot(history_inception.history['val_loss'])\nplt.title('InceptionV3 Model Loss')\nplt.ylabel('Loss')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper left')\nplt.show()\n\n# 4. MobileNet Model\ndef create_mobilenet_model():\n    \"\"\"Create MobileNet-based model\"\"\"\n    base_model = MobileNet(weights='imagenet', include_top=False, input_shape=(img_height, img_width, 3))\n    x = base_model.output\n    x = GlobalAveragePooling2D()(x)\n    x = Dense(128, activation='relu')(x)\n    x = Dropout(0.5)(x)\n    predictions = Dense(1, activation='sigmoid')(x)\n    model = Model(inputs=base_model.input, outputs=predictions)\n    return model\n\nmobilenet_model = create_mobilenet_model()\nmobilenet_model.compile(\n    optimizer=Adam(learning_rate=0.0001),\n    loss='binary_crossentropy',\n    metrics=['accuracy']\n)\n\nprint(\"Training MobileNet Model...\")\nhistory_mobilenet = mobilenet_model.fit(\n    train_generator,\n    steps_per_epoch=train_steps_per_epoch,\n    epochs=10,\n    validation_data=validation_generator,\n    validation_steps=valid_steps_per_epoch,\n    callbacks=[early_stopping]\n)\n\n# Plot MobileNet training history\nplt.figure(figsize=(12, 6))\nplt.subplot(1, 2, 1)\nplt.plot(history_mobilenet.history['accuracy'])\nplt.plot(history_mobilenet.history['val_accuracy'])\nplt.title('MobileNet Model Accuracy')\nplt.ylabel('Accuracy')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper left')\n\nplt.subplot(1, 2, 2)\nplt.plot(history_mobilenet.history['loss'])\nplt.plot(history_mobilenet.history['val_loss'])\nplt.title('MobileNet Model Loss')\nplt.ylabel('Loss')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'], loc='upper left')\nplt.show()\n\n# Evaluation Function\ndef evaluate_model(model, model_name, test_gen):\n    \"\"\"Evaluate a single model and display results\"\"\"\n    print(f\"\\nEvaluating {model_name} Model...\")\n    \n    # Get predictions\n    y_pred = model.predict(test_gen, steps=len(test_gen), verbose=1)\n    y_pred_binary = np.round(y_pred)\n    \n    # Get true labels\n    y_true = test_gen.classes\n    \n    # Calculate accuracy\n    accuracy = accuracy_score(y_true, y_pred_binary)\n    print(f\"{model_name} Accuracy: {accuracy:.4f}\")\n    \n    # Classification report\n    print(f\"\\n{model_name} Classification Report:\")\n    print(classification_report(y_true, y_pred_binary, target_names=['fake', 'real']))\n    \n    # Confusion matrix\n    conf_matrix = confusion_matrix(y_true, y_pred_binary)\n    plt.figure(figsize=(7, 5))\n    sns.heatmap(conf_matrix, annot=True, cmap='Blues', fmt='g', \n                xticklabels=['fake', 'real'], yticklabels=['fake', 'real'])\n    plt.title(f'{model_name} Confusion Matrix')\n    plt.xlabel('Predicted labels')\n    plt.ylabel('True labels')\n    plt.show()\n    \n    return y_pred_binary, accuracy\n\n# Evaluate all models\nprint(\"=\"*50)\nprint(\"MODEL EVALUATION\")\nprint(\"=\"*50)\n\n# Reset test generator\ntest_generator.reset()\ncnn_pred, cnn_acc = evaluate_model(model_cnn, \"CNN\", test_generator)\n\ntest_generator.reset()\nxception_pred, xception_acc = evaluate_model(xception_model, \"Xception\", test_generator)\n\ntest_generator.reset()\ninception_pred, inception_acc = evaluate_model(inception_model, \"InceptionV3\", test_generator)\n\ntest_generator.reset()\nmobilenet_pred, mobilenet_acc = evaluate_model(mobilenet_model, \"MobileNet\", test_generator)\n\n# Ensemble Method\ndef ensemble_predict(models, test_gen, threshold=0.5):\n    \"\"\"Create ensemble predictions using majority voting\"\"\"\n    test_gen.reset()\n    predictions = []\n    \n    for i, model in enumerate(models):\n        print(f\"Getting predictions from model {i+1}/{len(models)}...\")\n        pred = (model.predict(test_gen, verbose=0) > threshold).astype('int32').flatten()\n        predictions.append(pred)\n        test_gen.reset()  # Reset for next model\n    \n    predictions = np.array(predictions)\n    # Majority voting\n    ensemble_predictions = np.apply_along_axis(\n        lambda x: Counter(x).most_common(1)[0][0], \n        axis=0, \n        arr=predictions\n    )\n    return ensemble_predictions\n\n# Create ensemble\nprint(\"\\n\" + \"=\"*50)\nprint(\"ENSEMBLE MODEL EVALUATION\")\nprint(\"=\"*50)\n\nmodels_list = [xception_model, inception_model, mobilenet_model]\nmodel_names = [\"Xception\", \"InceptionV3\", \"MobileNet\"]\n\nensemble_pred = ensemble_predict(models_list, test_generator)\ny_true = test_generator.classes\n\n# Ensemble evaluation\nensemble_acc = accuracy_score(y_true, ensemble_pred)\nprint(f\"Ensemble Accuracy: {ensemble_acc:.4f}\")\n\nprint(\"\\nEnsemble Classification Report:\")\nprint(classification_report(y_true, ensemble_pred, target_names=['fake', 'real']))\n\n# Ensemble confusion matrix\nconf_matrix_ensemble = confusion_matrix(y_true, ensemble_pred)\nplt.figure(figsize=(7, 5))\nsns.heatmap(conf_matrix_ensemble, annot=True, cmap='Blues', fmt='g', \n            xticklabels=['fake', 'real'], yticklabels=['fake', 'real'])\nplt.title('Ensemble Confusion Matrix')\nplt.xlabel('Predicted labels')\nplt.ylabel('True labels')\nplt.show()\n\n# Summary of all model performances\nprint(\"\\n\" + \"=\"*50)\nprint(\"SUMMARY OF MODEL PERFORMANCES\")\nprint(\"=\"*50)\nprint(f\"CNN Accuracy:        {cnn_acc:.4f}\")\nprint(f\"Xception Accuracy:   {xception_acc:.4f}\")\nprint(f\"InceptionV3 Accuracy: {inception_acc:.4f}\")\nprint(f\"MobileNet Accuracy:  {mobilenet_acc:.4f}\")\nprint(f\"Ensemble Accuracy:   {ensemble_acc:.4f}\")\n\n# Find best performing model\naccuracies = [cnn_acc, xception_acc, inception_acc, mobilenet_acc, ensemble_acc]\nmodel_names_all = [\"CNN\", \"Xception\", \"InceptionV3\", \"MobileNet\", \"Ensemble\"]\nbest_model_idx = np.argmax(accuracies)\nprint(f\"\\nBest performing model: {model_names_all[best_model_idx]} with accuracy: {accuracies[best_model_idx]:.4f}\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-07-30T06:13:04.277046Z","iopub.execute_input":"2025-07-30T06:13:04.277521Z","iopub.status.idle":"2025-07-30T06:13:04.427261Z","shell.execute_reply.started":"2025-07-30T06:13:04.277448Z","shell.execute_reply":"2025-07-30T06:13:04.425397Z"}},"outputs":[],"execution_count":null}]}