{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "mk43RirOWyAi",
        "outputId": "99e64090-d5cd-46d2-bf8a-02e6534a89f4"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Epoch 0 Error: 0.4993\n",
            "Epoch 1000 Error: 0.4942\n",
            "Epoch 2000 Error: 0.4416\n",
            "Epoch 3000 Error: 0.3827\n",
            "Epoch 4000 Error: 0.3410\n",
            "Epoch 5000 Error: 0.2914\n",
            "Epoch 6000 Error: 0.2521\n",
            "Epoch 7000 Error: 0.2282\n",
            "Epoch 8000 Error: 0.2130\n",
            "Epoch 9000 Error: 0.2025\n",
            "\n",
            "Final Output After Training:\n",
            "[[0.]\n",
            " [1.]\n",
            " [1.]\n",
            " [1.]]\n"
          ]
        }
      ],
      "source": [
        "import numpy as np\n",
        "\n",
        "# Sigmoid and its derivative\n",
        "def sigmoid(x):\n",
        "    return 1 / (1 + np.exp(-x))\n",
        "def sigmoid_derivative(x):\n",
        "    return x * (1 - x)\n",
        "\n",
        "# Sample training data (XOR example)\n",
        "X = np.array([[0, 0],\n",
        "              [0, 1],\n",
        "              [1, 0],\n",
        "              [1, 1]])\n",
        "\n",
        "y = np.array([[0],\n",
        "              [1],\n",
        "              [1],\n",
        "              [0]])\n",
        "\n",
        "# Set seed for reproducibility\n",
        "np.random.seed(1)\n",
        "\n",
        "# Network architecture\n",
        "input_neurons = 2\n",
        "hidden_neurons = 3\n",
        "output_neurons = 1\n",
        "\n",
        "# Random weights initialization\n",
        "weights_input_hidden = 2 * np.random.rand(input_neurons, hidden_neurons) - 1\n",
        "weights_hidden_output = 2 * np.random.rand(hidden_neurons, output_neurons) - 1\n",
        "\n",
        "# Training parameters\n",
        "epochs = 10000\n",
        "learning_rate = 0.1\n",
        "\n",
        "# Training loop\n",
        "for epoch in range(epochs):\n",
        "    # Forward pass\n",
        "    hidden_input = np.dot(X, weights_input_hidden)\n",
        "    hidden_output = sigmoid(hidden_input)\n",
        "\n",
        "    final_input = np.dot(hidden_output, weights_hidden_output)\n",
        "    predicted_output = sigmoid(final_input)\n",
        "\n",
        "    # Backward pass\n",
        "    error = y - predicted_output\n",
        "    d_output = error * sigmoid_derivative(predicted_output)\n",
        "\n",
        "    error_hidden = d_output.dot(weights_hidden_output.T)\n",
        "    d_hidden = error_hidden * sigmoid_derivative(hidden_output)\n",
        "\n",
        "    # Update weights\n",
        "    weights_hidden_output += hidden_output.T.dot(d_output) * learning_rate\n",
        "    weights_input_hidden += X.T.dot(d_hidden) * learning_rate\n",
        "\n",
        "    # Print error at intervals\n",
        "    if epoch % 1000 == 0:\n",
        "        print(f\"Epoch {epoch} Error: {np.mean(np.abs(error)):.4f}\")\n",
        "\n",
        "# Final Output\n",
        "print(\"\\nFinal Output After Training:\")\n",
        "print(predicted_output.round())\n"
      ]
    }
  ]
}