<jupyter_start><jupyter_text>References: Article:https://towardsdatascience.com/how-to-build-your-own-neural-network-from-scratch-in-python-68998a08e4f6Code:https://gist.githubusercontent.com/jamesloyys/9f3308921bf7852e95ab9e34cd2ee0a0/raw/3d9a8dc8c0b4a9796c2f569cb6c04b0e37c0424b/neural_network_full.py Doubts and Solutions:Numpy Array Basics:https://jakevdp.github.io/PythonDataScienceHandbook/02.02-the-basics-of-numpy-arrays.htmlWeights matrix dimensions:https://datascience.stackexchange.com/questions/23462/dimension-of-weight-matrix-in-neural-networkSigmoid Formula:https://math.stackexchange.com/a/1225116<jupyter_code>import numpy as np

def sigmoid(x):
    return 1.0/(1+ np.exp(-x))

def sigmoid_derivative(x):
    return x * (1.0 - x)

class NeuralNetwork:
    def __init__(self, x, y):
        self.input      = x
        self.weights1   = np.random.rand(self.input.shape[1],4) 
        #Regarding weights matrix dimension
        #Matrix multiplication works so that if you multiply two matrices together, C=AB, 
        #where A is an i×j matrix and B is a j×k matrix, then C will be a i×k matrix. 
        #Note that A's column count must equal B's row count (j).
        self.weights2   = np.random.rand(4,1)                 
        self.y          = y
        self.output     = np.zeros(self.y.shape)

    def feedforward(self):
        self.layer1 = sigmoid(np.dot(self.input, self.weights1))
        self.output = sigmoid(np.dot(self.layer1, self.weights2))

    def backprop(self):
        # application of the chain rule to find derivative of the loss function with respect to weights2 and weights1
        d_weights2 = np.dot(self.layer1.T, (2*(self.y - self.output) * sigmoid_derivative(self.output)))
        d_weights1 = np.dot(self.input.T,  (np.dot(2*(self.y - self.output) * sigmoid_derivative(self.output), self.weights2.T) * sigmoid_derivative(self.layer1)))

        # update the weights with the derivative (slope) of the loss function
        self.weights1 += d_weights1
        self.weights2 += d_weights2


if __name__ == "__main__":
    X = np.array([[0,0,1], # 1
                  [0,1,1], # 3
                  [1,0,1], # 5
                  [1,1,1]]) # 7
    y = np.array([[0],[1],[1],[0]])
    nn = NeuralNetwork(X,y)

    for i in range(30000):
        nn.feedforward()
        nn.backprop()

    print(nn.output)<jupyter_output>[[0.00139528]
 [0.99454182]
 [0.9945022 ]
 [0.00680752]]
{'fraction_non_alphanumeric': 0.12932454695222406, 'fraction_numerical': 0.06466227347611203, 'mean_word_length': 2.956026058631922, 'pattern_counts': {'":': 1, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '433805', 'license': 'MIT', 'n_tokens_mistral': 961, 'n_tokens_neox': 872, 'n_words': 167, 'path': 'Simple Neural Network in python.ipynb', 'repo_name': 'naushadS/Machine-Learning', 'size': '2428'}