<commit_before>import numpy as np 

class FullyConnectedNN:
	"""
		General Fully connected Neural Network implementation
	"""

	def __init__(self,shape,X,y,activationfunc="sigmoid"):
		"""Initializes a neural network model

		Parameters
		----------

		shape: list
			A list of integers specifying number of nodes on each layer starting from input to output layer
		activation: string
			The activation function to be used. Currently only sigmoid is implemented
		"""
		self.X = X
		self.y = y
		self.shape = shape	# list storing the structure of the network
		self.activationfunc = activationfunc	# activation function to be used
		
		self.weights = list() # list of weights per each layer
		self.biases = list() #list of biases for each layer

		for i in range(1,len(shape)):
			# size of weight matrix for each layer => (num of units in this layer * num of units in next layer)
			self.weights.append(np.random.random_sample((shape[i-1],shape[i])))
			self.biases.append(np.zeros((1,shape[i])))
		

	def predict(self,X):
		""" Performs forward propagation
		
		Parameters
		----------

		X: ndarray
			A numpy array with values for input layer
		"""
		# store the computations
		zs = []
		# store the activations
		activations = [X]
		# initial activation is the input
		activation = X
		# get activation function
		afunc = self.activation_func()

		for weight,bias in zip(self.weights,self.biases):

			z = activation.dot(weight) + bias
			activation = afunc(z)
			zs.append(z)
			activations.append(activation)

		return (zs,activations)

	def back_propagation(self):

		delta = list()	# store the errors
		gradient = list()	#store the gradient values
		last = len(self.neurons)-1
		for k in range(0,m):
			j=1
			delta.append(self.neurons[last] - self.y[k])	
			# looping from the last layer to second layer (reverse)
			for i in range(len(self.neurons),1,-1):
				d = np.multiply(np.dot(self.neurons[i].transpose(),delta[-j]),np.multiply(self.neurons[i],(1 - self.neurons[i])))
				delta.append(i)
				j+=1


	def activation_func(self):
		""" Returns the activation function given in the constructor parameter

		Returns
		-------
		function: function
			The activation function
		"""
		def sigmoid(val):
			return float(1)/(1+np.exp(-val))
		
		if(self.activationfunc == "sigmoid"):
			return sigmoid

	def plot_data(self):
<commit_msg>Implementation of backprop in progress<commit_after>import numpy as np 

class FullyConnectedNN:
	"""
		General Fully connected Neural Network implementation
	"""

	def __init__(self,shape,X,y,activationfunc="sigmoid"):
		"""Initializes a neural network model

		Parameters
		----------

		shape: list
			A list of integers specifying number of nodes on each layer starting from input to output layer
		activation: string
			The activation function to be used. Currently only sigmoid is implemented
		"""
		self.X = X
		self.y = y
		self.shape = shape	# list storing the structure of the network
		self.activationfunc = activationfunc	# activation function to be used
		
		self.weights = list() # list of weights per each layer
		self.biases = list() #list of biases for each layer

		for i in range(1,len(shape)):
			# size of weight matrix for each layer => (num of units in this layer * num of units in next layer)
			self.weights.append(np.random.random_sample((shape[i-1],shape[i])))
			self.biases.append(np.zeros((1,shape[i])))
		

	def predict(self,X):
		""" Performs forward propagation
		
		Parameters
		----------

		X: ndarray
			A numpy array with values for input layer
		"""
		# store the computations
		zs = []
		# store the activations
		activations = [X]
		# initial activation is the input
		activation = X
		# get activation function
		afunc = self.activation_func()

		for weight,bias in zip(self.weights,self.biases):

			z = activation.dot(weight) + bias
			activation = afunc(z)
			zs.append(z)
			activations.append(activation)

		return (zs,activations)

	def train(self,alpha):
		
		weights = list() # list of weights per each layer
		biases = list() #list of biases for each layer

		for i in range(1,len(shape)):
			# size of weight matrix for each layer => (num of units in this layer * num of units in next layer)
			self.weights.append(np.random.random_sample((shape[i-1],shape[i])))
			self.biases.append(np.zeros((1,shape[i])))
		
		temp_weight = weights
		temp_bias = biases
		# iterate over all rows in the dataset
		for x,y in zip(self.X,self.y):

			zs,activations = self.predict(x)
			#last layer
			delta = activations[-1] - y
			temp_weight[-1] = np.dot(delta,activations[-1])
			temp_bias[-1] = delta.sum()
			# peroform backward pass for each layer except last
			for l in range(1,len(self.shape)):
				delta = np.dot(delta,self.weights[-l]) * (activations[-l]*(1-activations[-l]))
				temp_weight[-l] = delta.activations[-l]
				temp_bias[-l] = delta.sum()

			for weight,d in zip(weights,temp_weight):
				weight += -alpha*d
			
			for bias,d in z(weights,temp_bias):
				bias += -alpha*d
		
		return (weights,biases)


	def activation_func(self):
		""" Returns the activation function given in the constructor parameter

		Returns
		-------
		function: function
			The activation function
		"""
		def sigmoid(val):
			return float(1)/(1+np.exp(-val))
		
		if(self.activationfunc == "sigmoid"):
			return sigmoid

	def plot_data(self):

{'fraction_non_alphanumeric': 0.11943661971830986, 'fraction_numerical': 0.004882629107981221, 'mean_word_length': 3.460636515912898, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 0, '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}}
{'dir': 'git-commits-cleaned', 'id': '4634803', 'n_tokens_mistral': 1932, 'n_tokens_neox': 1646, 'n_words': 526}