{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": [],
      "gpuType": "T4"
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {
        "id": "WsKxn6vY7caN"
      },
      "outputs": [],
      "source": [
        "!pip install torch torchvision tensorflow matplotlib pillow -q"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# TensorFlow\n",
        "import tensorflow as tf\n",
        "from tensorflow import keras\n",
        "\n",
        "# PyTorch\n",
        "import torch\n",
        "import torch.nn as nn\n",
        "import torch.optim as optim\n",
        "import torchvision\n",
        "import torchvision.transforms as transforms\n",
        "\n",
        "# Common\n",
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "from PIL import Image"
      ],
      "metadata": {
        "id": "ir0MVy4k7n7o"
      },
      "execution_count": 8,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# TensorFlow dataset\n",
        "(X_train, y_train), (X_test, y_test) = keras.datasets.mnist.load_data()\n",
        "\n",
        "print(\"Train shape:\", X_train.shape)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "YGJAlyYv7rl7",
        "outputId": "1c82c6df-6bf1-4371-d2b0-b8fcd280ec8f"
      },
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Train shape: (60000, 28, 28)\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Normalize\n",
        "X_train = X_train / 255.0\n",
        "X_test = X_test / 255.0\n",
        "\n",
        "# Reshape for CNN\n",
        "X_train_tf = X_train.reshape(-1,28,28,1)\n",
        "X_test_tf = X_test.reshape(-1,28,28,1)"
      ],
      "metadata": {
        "id": "TPQeUR8S7r_J"
      },
      "execution_count": 10,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "model_tf = keras.Sequential([\n",
        "    keras.layers.Conv2D(32,(3,3),activation='relu',input_shape=(28,28,1)),\n",
        "    keras.layers.MaxPooling2D((2,2)),\n",
        "\n",
        "    keras.layers.Conv2D(64,(3,3),activation='relu'),\n",
        "    keras.layers.MaxPooling2D((2,2)),\n",
        "\n",
        "    keras.layers.Flatten(),\n",
        "    keras.layers.Dense(64,activation='relu'),\n",
        "    keras.layers.Dense(10,activation='softmax')\n",
        "])\n",
        "\n",
        "model_tf.compile(\n",
        "    optimizer='adam',\n",
        "    loss='sparse_categorical_crossentropy',\n",
        "    metrics=['accuracy']\n",
        ")\n",
        "\n",
        "model_tf.summary()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 353
        },
        "id": "ACDxgFdL7ti7",
        "outputId": "438de7ac-5d82-4fd6-a314-a9b79d54e2b5"
      },
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1mModel: \"sequential_1\"\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"sequential_1\"</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
              "┃\u001b[1m \u001b[0m\u001b[1mLayer (type)                   \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape          \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m      Param #\u001b[0m\u001b[1m \u001b[0m┃\n",
              "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
              "│ conv2d_2 (\u001b[38;5;33mConv2D\u001b[0m)               │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m26\u001b[0m, \u001b[38;5;34m26\u001b[0m, \u001b[38;5;34m32\u001b[0m)     │           \u001b[38;5;34m320\u001b[0m │\n",
              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
              "│ max_pooling2d_2 (\u001b[38;5;33mMaxPooling2D\u001b[0m)  │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m13\u001b[0m, \u001b[38;5;34m13\u001b[0m, \u001b[38;5;34m32\u001b[0m)     │             \u001b[38;5;34m0\u001b[0m │\n",
              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
              "│ conv2d_3 (\u001b[38;5;33mConv2D\u001b[0m)               │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m11\u001b[0m, \u001b[38;5;34m11\u001b[0m, \u001b[38;5;34m64\u001b[0m)     │        \u001b[38;5;34m18,496\u001b[0m │\n",
              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
              "│ max_pooling2d_3 (\u001b[38;5;33mMaxPooling2D\u001b[0m)  │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m5\u001b[0m, \u001b[38;5;34m5\u001b[0m, \u001b[38;5;34m64\u001b[0m)       │             \u001b[38;5;34m0\u001b[0m │\n",
              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
              "│ flatten_1 (\u001b[38;5;33mFlatten\u001b[0m)             │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1600\u001b[0m)           │             \u001b[38;5;34m0\u001b[0m │\n",
              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
              "│ dense_2 (\u001b[38;5;33mDense\u001b[0m)                 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m64\u001b[0m)             │       \u001b[38;5;34m102,464\u001b[0m │\n",
              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
              "│ dense_3 (\u001b[38;5;33mDense\u001b[0m)                 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m10\u001b[0m)             │           \u001b[38;5;34m650\u001b[0m │\n",
              "└─────────────────────────────────┴────────────────────────┴───────────────┘\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
              "┃<span style=\"font-weight: bold\"> Layer (type)                    </span>┃<span style=\"font-weight: bold\"> Output Shape           </span>┃<span style=\"font-weight: bold\">       Param # </span>┃\n",
              "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
              "│ conv2d_2 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Conv2D</span>)               │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">26</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">26</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">32</span>)     │           <span style=\"color: #00af00; text-decoration-color: #00af00\">320</span> │\n",
              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
              "│ max_pooling2d_2 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">MaxPooling2D</span>)  │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">13</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">13</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">32</span>)     │             <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
              "│ conv2d_3 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Conv2D</span>)               │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">11</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">11</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">64</span>)     │        <span style=\"color: #00af00; text-decoration-color: #00af00\">18,496</span> │\n",
              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
              "│ max_pooling2d_3 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">MaxPooling2D</span>)  │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">5</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">5</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">64</span>)       │             <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
              "│ flatten_1 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Flatten</span>)             │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">1600</span>)           │             <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
              "│ dense_2 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>)                 │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">64</span>)             │       <span style=\"color: #00af00; text-decoration-color: #00af00\">102,464</span> │\n",
              "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
              "│ dense_3 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>)                 │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">10</span>)             │           <span style=\"color: #00af00; text-decoration-color: #00af00\">650</span> │\n",
              "└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m121,930\u001b[0m (476.29 KB)\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">121,930</span> (476.29 KB)\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m121,930\u001b[0m (476.29 KB)\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">121,930</span> (476.29 KB)\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> (0.00 B)\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "history_tf = model_tf.fit(\n",
        "    X_train_tf, y_train,\n",
        "    epochs=5,\n",
        "    batch_size=64,\n",
        "    validation_split=0.1\n",
        ")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "NmWrj3rv7uhp",
        "outputId": "8ee72301-2590-43c0-8ec5-90610f8c7eea"
      },
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Epoch 1/5\n",
            "\u001b[1m844/844\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m13s\u001b[0m 10ms/step - accuracy: 0.9377 - loss: 0.2037 - val_accuracy: 0.9820 - val_loss: 0.0599\n",
            "Epoch 2/5\n",
            "\u001b[1m844/844\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 3ms/step - accuracy: 0.9812 - loss: 0.0595 - val_accuracy: 0.9863 - val_loss: 0.0481\n",
            "Epoch 3/5\n",
            "\u001b[1m844/844\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 4ms/step - accuracy: 0.9867 - loss: 0.0413 - val_accuracy: 0.9895 - val_loss: 0.0392\n",
            "Epoch 4/5\n",
            "\u001b[1m844/844\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 4ms/step - accuracy: 0.9899 - loss: 0.0315 - val_accuracy: 0.9902 - val_loss: 0.0363\n",
            "Epoch 5/5\n",
            "\u001b[1m844/844\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 4ms/step - accuracy: 0.9921 - loss: 0.0248 - val_accuracy: 0.9868 - val_loss: 0.0435\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "loss, acc = model_tf.evaluate(X_test_tf, y_test)\n",
        "print(\"TensorFlow Test Accuracy:\", acc)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "AlcPYWH77vbe",
        "outputId": "51187734-5b1a-4ab1-b462-061c86271dec"
      },
      "execution_count": 13,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "\u001b[1m313/313\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 6ms/step - accuracy: 0.9887 - loss: 0.0354\n",
            "TensorFlow Test Accuracy: 0.9886999726295471\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "transform = transforms.Compose([\n",
        "    transforms.ToTensor()\n",
        "])\n",
        "\n",
        "train_dataset = torchvision.datasets.MNIST(\n",
        "    root='./data', train=True, download=True, transform=transform\n",
        ")\n",
        "\n",
        "test_dataset = torchvision.datasets.MNIST(\n",
        "    root='./data', train=False, download=True, transform=transform\n",
        ")\n",
        "\n",
        "train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)\n",
        "test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=64)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "smA8ZoA77wZ1",
        "outputId": "ebea3334-21f2-4589-9dc7-536c2bfcda93"
      },
      "execution_count": 14,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 9.91M/9.91M [00:00<00:00, 18.0MB/s]\n",
            "100%|██████████| 28.9k/28.9k [00:00<00:00, 493kB/s]\n",
            "100%|██████████| 1.65M/1.65M [00:00<00:00, 4.68MB/s]\n",
            "100%|██████████| 4.54k/4.54k [00:00<00:00, 11.2MB/s]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "class CNN(nn.Module):\n",
        "    def __init__(self):\n",
        "        super(CNN, self).__init__()\n",
        "        self.conv1 = nn.Conv2d(1,32,3)\n",
        "        self.conv2 = nn.Conv2d(32,64,3)\n",
        "        self.pool = nn.MaxPool2d(2,2)\n",
        "\n",
        "        self.fc1 = nn.Linear(64*5*5,64)\n",
        "        self.fc2 = nn.Linear(64,10)\n",
        "\n",
        "    def forward(self,x):\n",
        "        x = self.pool(torch.relu(self.conv1(x)))\n",
        "        x = self.pool(torch.relu(self.conv2(x)))\n",
        "        x = x.view(-1,64*5*5)\n",
        "        x = torch.relu(self.fc1(x))\n",
        "        x = self.fc2(x)\n",
        "        return x\n",
        "\n",
        "model_pt = CNN()\n",
        "criterion = nn.CrossEntropyLoss()\n",
        "optimizer = optim.Adam(model_pt.parameters(), lr=0.001)"
      ],
      "metadata": {
        "id": "a1zcLbgB7xki"
      },
      "execution_count": 15,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "for epoch in range(5):\n",
        "    for images, labels in train_loader:\n",
        "        outputs = model_pt(images)\n",
        "        loss = criterion(outputs, labels)\n",
        "\n",
        "        optimizer.zero_grad()\n",
        "        loss.backward()\n",
        "        optimizer.step()\n",
        "\n",
        "    print(f\"Epoch {epoch+1} done\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "MPVOQcwz7ylW",
        "outputId": "22f79b52-7b12-4fdf-e2fe-5c4bf9b878b9"
      },
      "execution_count": 16,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Epoch 1 done\n",
            "Epoch 2 done\n",
            "Epoch 3 done\n",
            "Epoch 4 done\n",
            "Epoch 5 done\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "correct = 0\n",
        "total = 0\n",
        "\n",
        "with torch.no_grad():\n",
        "    for images, labels in test_loader:\n",
        "        outputs = model_pt(images)\n",
        "        _, predicted = torch.max(outputs.data,1)\n",
        "        total += labels.size(0)\n",
        "        correct += (predicted == labels).sum().item()\n",
        "\n",
        "print(\"PyTorch Test Accuracy:\", correct/total)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "xAdxIIkc7zwE",
        "outputId": "06307438-ab37-4b84-aadd-3a12f4c42358"
      },
      "execution_count": 17,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "PyTorch Test Accuracy: 0.9909\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from PIL import Image, ImageOps\n",
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "import torch\n",
        "\n",
        "img_path = \"test.jpg\"\n",
        "\n",
        "img = Image.open(img_path).convert('L')\n",
        "img = ImageOps.invert(img)\n",
        "img = img.resize((28,28))\n",
        "img_array = np.array(img)\n",
        "\n",
        "img_array = img_array / 255.0\n",
        "\n",
        "plt.imshow(img_array, cmap='gray')\n",
        "plt.title(\"Processed Image\")\n",
        "plt.axis('off')\n",
        "plt.show()\n",
        "\n",
        "img_tf = img_array.reshape(1,28,28,1)\n",
        "pred_tf = model_tf.predict(img_tf)\n",
        "print(\"TensorFlow Prediction:\", np.argmax(pred_tf))\n",
        "\n",
        "img_pt = torch.tensor(img_array).float().unsqueeze(0).unsqueeze(0)\n",
        "output = model_pt(img_pt)\n",
        "_, pred_pt = torch.max(output,1)\n",
        "print(\"PyTorch Prediction:\", pred_pt.item())"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 480
        },
        "id": "vqE1BpGL716S",
        "outputId": "0790bd3a-91dd-4c38-a058-442ca9ae427e"
      },
      "execution_count": 24,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 640x480 with 1 Axes>"
            ],
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAGbCAYAAAAr/4yjAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAFdtJREFUeJzt3HmMVfX5+PHnwsAwrCIyLIKAg2hdURvB7YsogiJYrMZKTRWsLdatNFSDNVpQlOCGRitJTZRGba2YulAXlIppsdJotVq1RkRxqwpWGFEEC3N+f1ieb6fg7zsHi6PyeiUkzrnnufdzh/G+59xzOZWiKIoAgIho0dwLAOCLQxQASKIAQBIFAJIoAJBEAYAkCgAkUQAgiQIASRSgpL59+8a4ceOaexmwRYjCVmj27NlRqVTyT5s2bWLAgAFx5plnxjvvvNPcy/vKqFQqceaZZzb3MqCUquZeAM3noosuin79+sWaNWti4cKFMWvWrLjvvvvi2WefjbZt2zb38oBmIApbsSOPPDK+/vWvR0TEqaeeGl26dImrrroq7r777hg7duwmZz788MNo167d57lM4HPk7SPSoYceGhERr7zySkREjBs3Ltq3bx9LliyJkSNHRocOHeLEE0+MiE/iMGnSpOjdu3dUV1fHzjvvHFdccUVs6qK7t9xyS+y3337Rtm3b6Ny5c/zP//xPPPjgg432uf/+++Pggw+Odu3aRYcOHeKoo46K5557rtE+b7/9dowfPz569eoV1dXV0aNHj/jGN74RS5cuzX2eeOKJGDFiRGy33XZRU1MT/fr1i1NOOaXR/TQ0NMTVV18du+22W7Rp0ya6desWEyZMiBUrVjTaryiKmDZtWvTq1Svatm0bQ4cO3WhNZTzyyCNRqVTi9ttvj6lTp8b2228fHTp0iOOOOy7q6+tj7dq1MXHixKitrY327dvH+PHjY+3atY3u46abbopDDz00amtro7q6OnbdddeYNWvWRo/V0NAQU6ZMiZ49e+ban3/++U2eD1m5cmVMnDgx/y779+8fM2bMiIaGhs1+rnx5OVIgLVmyJCIiunTpktvWrVsXI0aMiIMOOiiuuOKKaNu2bRRFEUcffXQsWLAgvvvd78bAgQNj3rx5cc4558Sbb74ZM2fOzPmpU6fGlClT4oADDoiLLrooWrduHX/605/i4YcfjuHDh0dExM033xwnn3xyjBgxImbMmBGrV6+OWbNmxUEHHRRPPfVU9O3bNyIijj322HjuuefirLPOir59+8ayZcvioYceitdeey2/Hj58eHTt2jUmT54c22yzTSxdujR+85vfNHqeEyZMiNmzZ8f48ePj7LPPjldeeSWuu+66eOqpp+LRRx+NVq1aRUTEhRdeGNOmTYuRI0fGyJEj48knn4zhw4fHxx9//Jm+z9OnT4+ampqYPHlyvPTSS3HttddGq1atokWLFrFixYqYMmVKLFq0KGbPnh39+vWLCy+8MGdnzZoVu+22Wxx99NFRVVUVc+fOjdNPPz0aGhrijDPOyP3OO++8uOyyy2L06NExYsSIePrpp2PEiBGxZs2aRmtZvXp1DBkyJN58882YMGFC7LDDDvHHP/4xzjvvvHjrrbfi6quv/kzPlS+hgq3OTTfdVEREMX/+/GL58uXF66+/Xtx2221Fly5dipqamuKNN94oiqIoTj755CIiismTJzeav+uuu4qIKKZNm9Zo+3HHHVdUKpXipZdeKoqiKBYvXly0aNGiOOaYY4r169c32rehoaEoiqJYtWpVsc022xTf+973Gt3+9ttvF506dcrtK1asKCKiuPzyyz/1ed15551FRBSPP/74p+7zhz/8oYiI4tZbb220/YEHHmi0fdmyZUXr1q2Lo446KtdaFEXxk5/8pIiI4uSTT/7Ux9ggIoozzjgjv16wYEEREcXuu+9efPzxx7l97NixRaVSKY488shG8/vvv3/Rp0+fRttWr1690eOMGDGi2HHHHfPrt99+u6iqqirGjBnTaL8pU6ZstPaLL764aNeuXfHiiy822nfy5MlFy5Yti9dee+3/fJ58tXj7aCs2bNiw6Nq1a/Tu3TtOOOGEaN++fdx5552x/fbbN9rvBz/4QaOv77vvvmjZsmWcffbZjbZPmjQpiqKI+++/PyIi7rrrrmhoaIgLL7wwWrRo/KNWqVQiIuKhhx6KlStXxtixY+Pdd9/NPy1btoxBgwbFggULIiKipqYmWrduHY888shGb/NssM0220RExG9/+9v45z//ucl95syZE506dYrDDz+80ePtu+++0b59+3y8+fPnx8cffxxnnXVWrjUiYuLEiZ/27Wyyk046KY9GIiIGDRoURVFs9DbXoEGD4vXXX49169bltpqamvzv+vr6ePfdd2PIkCHx8ssvR319fURE/O53v4t169bF6aef3uj+zjrrrI3WMmfOnDj44IOjc+fOjb4fw4YNi/Xr18fvf//7z/x8+XLx9tFW7Gc/+1kMGDAgqqqqolu3brHzzjtv9OJdVVUVvXr1arTt1VdfjZ49e0aHDh0abf/a176Wt0d88nZUixYtYtddd/3UNSxevDgi/vd8xn/q2LFjRERUV1fHjBkzYtKkSdGtW7cYPHhwjBo1Kk466aTo3r17REQMGTIkjj322Jg6dWrMnDkzDjnkkBgzZkx8+9vfjurq6ny8+vr6qK2t3eTjLVu2rNFz2GmnnRrd3rVr1+jcufOnPp+m2GGHHRp93alTp4iI6N2790bbGxoaor6+Pt/Se/TRR+OnP/1pPPbYY7F69epG+9fX10enTp1y7f379290+7bbbrvR2hcvXhzPPPNMdO3adZNr3fD9YOshClux/fbbLz999Gmqq6s3CsV/04aTmTfffHO+uP+7qqr//RGdOHFijB49Ou66666YN29eXHDBBTF9+vR4+OGHY++9945KpRJ33HFHLFq0KObOnRvz5s2LU045Ja688spYtGhRtG/fPhoaGqK2tjZuvfXWTa7n014c/5tatmxZanvxr5P3S5YsicMOOyx22WWXuOqqq6J3797RunXruO+++2LmzJmbdWK4oaEhDj/88Dj33HM3efuAAQNK3ydfbqJAaX369In58+fHqlWrGh0tvPDCC3l7RERdXV00NDTE888/HwMHDtzkfdXV1UVERG1tbQwbNuz/fOy6urqYNGlSTJo0KRYvXhwDBw6MK6+8Mm655ZbcZ/DgwTF48OC45JJL4pe//GWceOKJcdttt8Wpp54adXV1MX/+/DjwwAMbvRWzqecY8clv0jvuuGNuX758+ae+fbWlzZ07N9auXRv33HNPo6ONDW95bbBh7S+99FL069cvt//jH//YaO11dXXxwQcfNOl7z9bBOQVKGzlyZKxfvz6uu+66RttnzpwZlUoljjzyyIiIGDNmTLRo0SIuuuiijX6L3fDb74gRI6Jjx45x6aWXbvI8wPLlyyPik0/J/OcnZ+rq6qJDhw75sc0VK1Zs9JHYDTHasM/xxx8f69evj4svvnijx1q3bl2sXLkyIj4539KqVau49tprG91nc34aZ8ORxL+vp76+Pm666aZG+x122GFRVVW10UdV//PvK+KT78djjz0W8+bN2+i2lStXNjqfwdbBkQKljR49OoYOHRrnn39+LF26NPbaa6948MEH4+67746JEyfmb//9+/eP888/Py6++OI4+OCD45vf/GZUV1fH448/Hj179ozp06dHx44dY9asWfGd73wn9tlnnzjhhBOia9eu8dprr8W9994bBx54YFx33XXx4osvxmGHHRbHH3987LrrrlFVVRV33nlnvPPOO3HCCSdERMQvfvGLuP766+OYY46Jurq6WLVqVdxwww3RsWPHGDlyZER8ct5hwoQJMX369PjLX/4Sw4cPj1atWsXixYtjzpw5cc0118Rxxx0XXbt2jR//+Mcxffr0GDVqVIwcOTKeeuqpuP/++2O77bZrlu/78OHDo3Xr1jF69OiYMGFCfPDBB3HDDTdEbW1tvPXWW7lft27d4oc//GFceeWVcfTRR8cRRxwRTz/9dK7930+cn3POOXHPPffEqFGjYty4cbHvvvvGhx9+GH/961/jjjvuiKVLlzbb86WZNOMnn2gmGz6S+v/76GZRfPKR1Hbt2m3ytlWrVhU/+tGPip49exatWrUqdtppp+Lyyy9v9PHNDW688cZi7733Lqqrq4vOnTsXQ4YMKR566KFG+yxYsKAYMWJE0alTp6JNmzZFXV1dMW7cuOKJJ54oiqIo3n333eKMM84odtlll6Jdu3ZFp06dikGDBhW333573seTTz5ZjB07tthhhx2K6urqora2thg1alTex7/7+c9/Xuy7775FTU1N0aFDh2KPPfYozj333OLvf/977rN+/fpi6tSpRY8ePYqamprikEMOKZ599tmiT58+n+kjqXPmzGm036f9ffz0pz8tIqJYvnx5brvnnnuKPffcs2jTpk3Rt2/fYsaMGcWNN95YRETxyiuv5H7r1q0rLrjggqJ79+5FTU1NceihhxZ/+9vfii5duhSnnXZao8dZtWpVcd555xX9+/cvWrduXWy33XbFAQccUFxxxRWNPjrL1qFSFJv4J6jAV87KlSujc+fOMW3atDj//PObezl8QTmnAF9BH3300UbbNpwPOeSQQz7fxfCl4pwCfAX9+te/jtmzZ8fIkSOjffv2sXDhwvjVr34Vw4cPjwMPPLC5l8cXmCjAV9Cee+4ZVVVVcdlll8X777+fJ5+nTZvW3EvjC845BQCScwoAJFEAIDX5nMK//4MXAL58mnK2wJECAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAKmquRcAW0KlUik9s+2225ae6dq1a+mZdu3alZ6JiKiqKv+/6+Z8H1asWFF65sUXXyw9UxRF6Rm2PEcKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABILoj3FdOmTZvSM7W1tZ/LzO677156JiJi8ODBpWf22GOP0jP9+vUrPdOlS5fSM61bty4983las2ZN6Zm5c+eWnjnttNNKz0REvPfee5s1R9M4UgAgiQIASRQASKIAQBIFAJIoAJBEAYAkCgAkUQAgiQIASRQASKIAQKoURVE0acdKZUuvhf+Ca665pvTM+PHjS8906NCh9MwXXX19femZ5cuXl55ZvXp16ZmIiHXr1m3WXFmbc7HDXr16lZ6ZOHFi6ZmIzfsZ5xNNebl3pABAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKAKSq5l4A/10vv/xy6ZmGhobSMwsXLiw9s2jRotIzEREvvPBC6Znnnnuu9Mwbb7xReua9994rPbO5Vztt4gWNP/NjTZ48ufTMpZdeWnqmpqam9AxbniMFAJIoAJBEAYAkCgAkUQAgiQIASRQASKIAQBIFAJIoAJBEAYAkCgCkStHEq2xVKpUtvRaaSZ8+fUrPLFu2rPTMRx99VHqGz2bHHXcsPbM5Fzts2bJl6Zn999+/9EzE5l30kU805eXekQIASRQASKIAQBIFAJIoAJBEAYAkCgAkUQAgiQIASRQASKIAQBIFAFJVcy+A5vfqq6829xJogs25KOXUqVNLz/To0aP0zPe///3SMy5s98XkSAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAKlSFEXRpB0342JcwH/PfvvtV3rm0UcfLT3zwAMPlJ4ZM2ZM6Zn169eXnuGzacrLvSMFAJIoAJBEAYAkCgAkUQAgiQIASRQASKIAQBIFAJIoAJBEAYAkCgAkUQAgVTX3AoCmGT9+fOmZFi3K/953ySWXlJ5xxdOvDkcKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIlaIoiibtWKls6bXAVqF79+6bNffss8+WnnnmmWdKzwwbNqz0TENDQ+kZPn9Nebl3pABAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgFTV3AuArc23vvWtzZrr0qVL6Znrr7++9IyL223dHCkAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACBViqIomrRjpbKl1wJfOu3bty898+c//3mzHmvNmjWlZ/bff//SM6tXry49w5dDU17uHSkAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACBVNfcC4MvsiCOOKD0zYMCAzXqscePGlZ5xcTvKcqQAQBIFAJIoAJBEAYAkCgAkUQAgiQIASRQASKIAQBIFAJIoAJBEAYAkCgCkSlEURZN2rFS29FqgWW3Oz/jdd99dembgwIGlZyIi9thjj9Iz9fX1m/VYfDU15eXekQIASRQASKIAQBIFAJIoAJBEAYAkCgAkUQAgiQIASRQASKIAQBIFAFJVcy8Avih69OhRembo0KGlZ2bNmlV6JsLF7fh8OFIAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEByQTz4l7322qv0TLt27UrP3HvvvaVn4PPiSAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAMkF8eBfunfvXnpm7dq1pWeWLFlSegY+L44UAEiiAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQXBAP/uXNN98sPVNdXV16pm/fvqVnIiLeeOONzZqDMhwpAJBEAYAkCgAkUQAgiQIASRQASKIAQBIFAJIoAJBEAYAkCgAkUQAgiQIAqVIURdGkHSuVLb0WaFYdOnQoPbNw4cLSM++//37pmYiIoUOHlp5Zt27dZj0WX01Nebl3pABAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgFTV3AuAL4pVq1aVnjnxxBNLz+yzzz6lZyIiGhoaNmsOynCkAEASBQCSKACQRAGAJAoAJFEAIIkCAEkUAEiiAEASBQCSKACQRAGAVCmKomjSjpXKll4LAFtQU17uHSkAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBAEgUAkigAkEQBgCQKACRRACBVNXXHoii25DoA+AJwpABAEgUAkigAkEQBgCQKACRRACCJAgBJFABIogBA+n/zdEv44hKYqQAAAABJRU5ErkJggg==\n"
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 57ms/step\n",
            "TensorFlow Prediction: 7\n",
            "PyTorch Prediction: 7\n"
          ]
        }
      ]
    }
  ]
}