diff --git a/neural_network/2_hidden_layers_neural_network.py b/neural_network/2_hidden_layers_neural_network.py new file mode 100644 index 000000000..b924a8593 --- /dev/null +++ b/neural_network/2_hidden_layers_neural_network.py @@ -0,0 +1,112 @@ +import numpy + +class NeuralNetwork: + + def __init__(self, input_array, output_array): + ''' + input_array : input values for training the neural network. + output_array : expected output values of the given inputs. + ''' + self.input = input_array + #Initial weights are assigned randomly where first argument is the number of nodes in previous layer + #and second argument is the number of nodes in the next layer. + + #random initial weights for the input layer + #self.input.shape[1] is used to reprsent number of nodes in input layer + #first hidden layer consists of 4 nodes + self.weights1 = numpy.random.rand(self.input.shape[1],4) + + #random initial weights for the first hidden layer + #first hidden layer has 4 nodes + #second hidden layer has 3 nodes + self.weights2 = numpy.random.rand(4,3) + + #random inital weights for the second hidden layer + #second hidden layer has 3 nodes + #output layer has 1 node + self.weights3 = numpy.random.rand(3,1) + + self.y = output_array + self.output = numpy.zeros(output_array.shape) + + def feedforward(self): + ''' + feedforward propagation using sigmoid activation function between layers + return the last layer of the neural network + ''' + #layer1 is the layer connecting the input nodes with the first hidden layer nodes + self.layer1 = sigmoid(numpy.dot(self.input, self.weights1)) + + #layer2 is the layer connecting the first hidden set of nodes with the second hidden set of nodes + self.layer2 = sigmoid(numpy.dot(self.layer1, self.weights2)) + + #layer3 is the layer connecting second hidden layer with the output node + self.layer3 = sigmoid(numpy.dot(self.layer2,self.weights3)) + + return self.layer3 + + def back_propagation(self): + ''' + backpropagating between the layers using sigmoid derivative and loss between layers + updates the weights between the layers + ''' + + updated_weights3 = numpy.dot(self.layer2.T,2*(self.y-self.output)*sigmoid_derivative(self.output)) + updated_weights2 = numpy.dot(self.layer1.T, numpy.dot(2*(self.y -self.output)*sigmoid_derivative(self.output), self.weights3.T)*sigmoid_derivative(self.layer2)) + updated_weights1 = numpy.dot(self.input.T, numpy.dot(numpy.dot(2*(self.y -self.output)*sigmoid_derivative(self.output), self.weights3.T)*sigmoid_derivative(self.layer2),self.weights2.T)*sigmoid_derivative(self.layer1)) + + self.weights1 += updated_weights1 + self.weights2 += updated_weights2 + self.weights3 += updated_weights3 + + def train(self, output, iterations): + ''' + output : required for calculating loss + performs the feeding and back propagation process for the given number of iterations + every iteration will update the weights of neural network + ''' + for iteration in range(1,iterations+1): + self.output = self.feedforward() + self.back_propagation() + print("Iteration %s "%iteration,"Loss: " + str(numpy.mean(numpy.square(output - self.feedforward())))) + + def predict(self, input): + ''' + predict output for the given input values + ''' + self.array = input + self.layer1 = sigmoid(numpy.dot(self.array, self.weights1)) + self.layer2 = sigmoid(numpy.dot(self.layer1, self.weights2)) + self.layer3 = sigmoid(numpy.dot(self.layer2,self.weights3)) + return self.layer3 + +def sigmoid(value): + ''' + applies sigmoid activation function + return normalized values + ''' + return 1/(1+numpy.exp(-value)) + +def sigmoid_derivative(value): + ''' + returns derivative of the sigmoid value + ''' + return sigmoid(value)*(1-sigmoid(value)) + + +if __name__ == "__main__": + + #input values + input = numpy.array(([0,0,0],[0,0,1],[0,1,0],[0,1,1], + [1,0,0],[1,0,1],[1,1,0],[1,1,1]),dtype=float) + + #true output for the given input values + output = numpy.array(([0],[1],[1],[0], + [1],[0],[0],[1]),dtype=float) + + #calling neural network class + Neural_Network = NeuralNetwork(input_array= input, output_array= output) + + #calling training function + Neural_Network.train(output= output, iterations= 1000) + print(Neural_Network.predict([0,1,1])) \ No newline at end of file