# ---
# 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
# ---

# +
# What is Neural Network?
# It is a computational system inspired by the Structure, Processing Method and Learning Ability similar to our biological brain

# +


# Characteristics of Artificial Neural Networks
# A large number of very simple processing neuron-like processing elements

# A large number of weighted connections between the elements

# Distributed representation of knowledge over the connections

# Knowledge is acquired by network through a learning process

# +
# number of layers and number of neurons are problem dependent. we dont know how many do we need for the specific 
# problem. but we can use some references people have used before
# -

# # Forward and backward propagation
# - NN takes several input, processes it through multiple neurons from multiple hidden layers and returns the result using an output layer. This result estimation process is technically known as “Forward Propagation“
#
# - Next, we compare the result with actual output. The task is to make the output to neural network as close to actual (desired) output. This defines our cost function.
#
# - We try to obtain the weight of neurons such that the NN total error (our cost function) being minimized. This process is known as “Backward Propagation“

# +
# we want to obtain best weight and biases. 
# Each perceptron has its weight and bias
# -

# # Activity: Implementing NN using Numpy
# - Assume, we want to build and train (obtain the weights) of a MLP such that for the given input: `X=np.array([[1,0,1,0],[1,0,1,1],[0,1,0,1]])`
#
#
# - gives us this desire output: `y=np.array([[1],[1],[0]])`
#
#
# - Also, assume we have only one hidden layer with three neurons and activation function for each perceptron is sigmoid

# +
import numpy as np
X = np.array([[1,0,1,0],[1,0,1,1],[0,1,0,1]])

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


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

#Derivative of Sigmoid Function
def derivatives_sigmoid(x):
    return x * (1 - x)



# -

print(sigmoid(X))

# +
# variables
epoch=5000 #Setting training iterations
lr = 0.1 # setting learning rate
inputlayer_neurons = X.shape[1] # number of features 
hiddenlayer_neurons = 3 # hidden layer number of neurons
output_neurons = 1

# wieghts abd bias 
wh = np.random.uniform(size=(inputlayer_neurons, hiddenlayer_neurons))
bh = np.random.uniform(size=(1, hiddenlayer_neurons))
wout=np.random.uniform(size=(hiddenlayer_neurons,output_neurons))
bout=np.random.uniform(size=(1,output_neurons))

for i in range(epoch):
    #Forward Propogation
    # take a dot product of inputs and weight
    hidden_layer_input1=np.dot(X,wh)
    # 
    hidden_layer_input=hidden_layer_input1 + bh
    hiddenlayer_activations = sigmoid(hidden_layer_input)
    output_layer_input1=np.dot(hiddenlayer_activations,wout)
    output_layer_input= output_layer_input1+ bout
    output = sigmoid(output_layer_input)
    
    #Backpropagation
    D = y-output
    slope_output_layer = derivatives_sigmoid(output)
    slope_hidden_layer = derivatives_sigmoid(hiddenlayer_activations)
    d_output = D * slope_output_layer
    Error_at_hidden_layer = d_output.dot(wout.T)
    d_hiddenlayer = Error_at_hidden_layer * slope_hidden_layer
    wout += hiddenlayer_activations.T.dot(d_output) *lr
    bout += np.sum(d_output, axis=0,keepdims=True) *lr
    wh += X.T.dot(d_hiddenlayer) *lr
    bh += np.sum(d_hiddenlayer, axis=0,keepdims=True) *lr
    
print(output)

# +
# good guess at the initial steps for weights it reduces the computing time

StarcoderdataJupyterScriptsDedupFiltered