"""
Lecture 11 - Building Neural Networks in Python: Keras/TensorFlow equivalent

The exact same architecture and dataset as lecture-11-numpy-nn.py, built
with tf.keras instead of hand-derived NumPy. Every call below corresponds
to a specific piece of math derived earlier in the course:
  Dense(2, activation='relu')  -> X W1 + b1, then ReLU        (Lectures 4-5)
  Dense(1, activation='sigmoid') -> A W2 + b2, then sigmoid   (Lectures 4-5)
  loss='binary_crossentropy'   -> L = -[y log Q + (1-y) log(1-Q)]  (Lecture 6)
  optimizer='adam'             -> adaptive moment estimation   (Lecture 9)
  model.fit(...)               -> forward pass + autodiff backprop
                                   + gradient descent, repeated (Lectures 7-8)

Requires: pip install tensorflow
Run: python lecture-11-keras-nn.py
"""
import numpy as np
import tensorflow as tf

# Same AND-gate toy dataset as the NumPy version
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=float)
y = np.array([[0], [0], [0], [1]], dtype=float)

model = tf.keras.Sequential([
    tf.keras.layers.Dense(2, activation='relu', input_shape=(2,)),
    tf.keras.layers.Dense(1, activation='sigmoid'),
])

model.compile(
    optimizer='adam',
    loss='binary_crossentropy',
    metrics=['accuracy'],
)

if __name__ == "__main__":
    history = model.fit(X, y, epochs=500, verbose=0)

    print("Final loss:", round(history.history['loss'][-1], 4))
    print("Predictions:", model.predict(X, verbose=0).ravel().round(4))
    print("True labels:", y.ravel())
