-
-
Notifications
You must be signed in to change notification settings - Fork 46.8k
Adding 2-hidden layer neural network with back propagation using sigmoid activation function #4037
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
fa4e2ac
1219f8c
97556ab
a783a4d
07fd20e
3f17bfc
ff55363
0454f72
0034458
4536f59
c5f71eb
527109d
1033bd1
481d7b7
1285ca3
3e2e723
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
import numpy | ||
|
||
|
||
class NeuralNetwork: | ||
raman77768 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def __init__(self, input_array: numpy.array, output_array: numpy.array) -> None: | ||
""" | ||
input_array : input values for training the neural network. | ||
output_array : expected output values of the given inputs. | ||
""" | ||
self.input = input_array | ||
raman77768 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# 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 represent number of nodes in input layer | ||
# first hidden layer consists of 4 nodes | ||
self.weights1 = numpy.random.rand(self.input.shape[1], 4) | ||
raman77768 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# 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 initial 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 | ||
raman77768 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self.output = numpy.zeros(output_array.shape) | ||
|
||
def feedforward(self) -> None: | ||
dhruvmanila marked this conversation as resolved.
Show resolved
Hide resolved
raman77768 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
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)) | ||
raman77768 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# 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) -> None: | ||
dhruvmanila marked this conversation as resolved.
Show resolved
Hide resolved
dhruvmanila marked this conversation as resolved.
Show resolved
Hide resolved
dhruvmanila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
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: numpy.array, iterations: int) -> None: | ||
dhruvmanila marked this conversation as resolved.
Show resolved
Hide resolved
dhruvmanila marked this conversation as resolved.
Show resolved
Hide resolved
dhruvmanila marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
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: list) -> int: | ||
dhruvmanila marked this conversation as resolved.
Show resolved
Hide resolved
dhruvmanila marked this conversation as resolved.
Show resolved
Hide resolved
dhruvmanila marked this conversation as resolved.
Show resolved
Hide resolved
dhruvmanila marked this conversation as resolved.
Show resolved
Hide resolved
raman77768 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
predict's output for the given input values | ||
""" | ||
self.array = numpy.array((input), dtype=float) | ||
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)) | ||
if self.layer3 >= 0.5: | ||
return 1 | ||
else: | ||
return 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does the output values represent? Please mention this in the function contract (function docstring). 1 and 0 represent Truthy and Falsy values, so if you're going for that then you should probably return a boolean value. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I mean by the above comment is to mention what does 0 and 1 represent. If the user uses the function and gets 0 and 1, how does he/she know what to do with that? Also, can you tell me why should we not return the value itself which is between 0 and 1 instead? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The output is given in binary classification, '0' and '1' are the two classes provided in this training data.Our model provides a value in-between 0-1 so i have set a threshold value which assigns the value to one of the classes |
||
|
||
|
||
def sigmoid(value: float) -> float: | ||
""" | ||
applies sigmoid activation function | ||
return normalized values | ||
|
||
>>> sigmoid(2) | ||
0.8807970779778823 | ||
|
||
>>> sigmoid(0) | ||
0.5 | ||
""" | ||
return 1 / (1 + numpy.exp(-value)) | ||
|
||
|
||
def sigmoid_derivative(value: float) -> float: | ||
""" | ||
returns derivative of the sigmoid value | ||
|
||
>>> sigmoid_derivative(0.7) | ||
0.22171287329310904 | ||
""" | ||
return sigmoid(value) * (1 - sigmoid(value)) | ||
|
||
|
||
def example() -> int: | ||
dhruvmanila marked this conversation as resolved.
Show resolved
Hide resolved
raman77768 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
used for example | ||
""" | ||
# 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) | ||
raman77768 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# calling training function | ||
Neural_Network.train(output=output, iterations=1500) | ||
return Neural_Network.predict([1, 1, 1]) | ||
|
||
|
||
if __name__ == "__main__": | ||
example() |
Uh oh!
There was an error while loading. Please reload this page.