
# !pip install numpy pandas matplotlib seaborn scikit-learn scipy
import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    return x * (1 - x)

X = np.array([[0,0],
              [0,1],
              [1,0],
              [1,1]])

y = np.array([[0],
              [1],
              [1],
              [0]])

np.random.seed(42)
input_dim = 2
hidden_dim = 4
output_dim = 1

W1 = np.random.uniform(-1, 1, (input_dim, hidden_dim))
b1 = np.zeros((1, hidden_dim))
W2 = np.random.uniform(-1, 1, (hidden_dim, output_dim))
b2 = np.zeros((1, output_dim))

epochs = 10000
learning_rate = 0.1

for epoch in range(epochs):

    z1 = np.dot(X, W1) + b1
    a1 = sigmoid(z1)
    z2 = np.dot(a1, W2) + b2
    a2 = sigmoid(z2)

    error = y - a2

    d2 = error * sigmoid_derivative(a2)
    d1 = np.dot(d2, W2.T) * sigmoid_derivative(a1)

    W2 += np.dot(a1.T, d2) * learning_rate
    b2 += np.sum(d2, axis=0, keepdims=True) * learning_rate
    W1 += np.dot(X.T, d1) * learning_rate
    b1 += np.sum(d1, axis=0, keepdims=True) * learning_rate

    if epoch % 2000 == 0:
        loss = np.mean(np.square(error))
        print(f"Epoch {epoch}, Loss: {loss:.4f}")

print("\nPredictions after training:")
print(a2.round(3))
