# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# ## Keras

import keras

keras.__version__

# ### Steps to follow:
# 1. Create the model
# 2. Compile the model
# 3. Train the model
# 4. Predict new data
# 5. Save the model for future estimates/data

# +
# Load only the resources you need, to optimize
from keras.models import Sequential
from keras.layers import Dense

import numpy as np
# -

# Load the training data
training_data = np.array([[0,0], [0,1], [1,0], [1,1]], "float32")  # single precision float: sign bit, 8 bits exponent, 23 bits mantissa

# Load the (real) results data
target_data = np.array([[0], [1], [1], [0]], "float32")

# +
# Create our model
model = Sequential()  # built layers on top of it

# Connects with n neurons/perceptrons, has x inputs, activation function
model.add(Dense(3, input_dim = 2, activation = "tanh"))

model.add(Dense(1, activation = "sigmoid"))
# -

# IMAGE
from IPython.display import Image
Image("Model.png")

# +
# Compile the model
model.compile(loss = "mean_squared_error", 
              optimizer = "adam", 
              metrics = ["binary_accuracy"])

# Loss: estimate the loss of the model so that the weights can be updated to reduce the loss on the next evaluation
# Optimizer: (backpropagation)
# Metrics: monitors and visualizes (print) the performance (accuracy) of the model

# +
# Train and optimize the model
history = model.fit(training_data, target_data, epochs = 200)  
# Collect the history of the fitting process, in order to visualize the learning of the model later

# Hypermetric: 
# - Epochs: number of learning iterations
# -

# Evaluate the training data
model.evaluate(training_data, target_data)

# Predict the results of the training data
model.predict(training_data).round()

# ## Visualization

import matplotlib.pyplot as plt

# +
# x-axis = array of epochs (length of history)
# y = history of accuracy

epochs = range(1, len(history.history["loss"]) + 1, 1)  # starting point, last point, steps

# +
# Automating the chart data
historyKeys = list(history.history.keys())

historyKeysLoss = historyKeys[0]
trained_model_Loss = history.history[historyKeysLoss]  # "loss"

historyKeysMetrics = historyKeys[1]
trained_model_Metrics = history.history[historyKeysMetrics]  # "binary_accuracy"
# -

plt.plot(epochs, trained_model_Loss, "r--", label = "Error")
plt.plot(epochs, trained_model_Metrics, "b--", label = "Accuracy")
plt.title("Evolution of the error")
plt.ylabel("error")
plt.xlabel("epochs")
plt.legend()  # show legend
plt.savefig('chart.png', figsize = (8, 6), dpi = 300, transparent = True)
plt.figure(figsize = (8, 6), dpi = 300)  # execute all

# ## Save the model

model.save("MyNetworkXOR.h5") 



StarcoderdataJupyterScriptsDedupFiltered