commit 00b05b858f725f73c25dd0dee9de965645713717 Author: Nabil Ould Hamou Date: Tue Feb 11 19:31:55 2025 +0100 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..abf22a2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__pycache__ +.venv +.idea \ No newline at end of file diff --git a/NNLayer.py b/NNLayer.py new file mode 100644 index 0000000..a0e8747 --- /dev/null +++ b/NNLayer.py @@ -0,0 +1,69 @@ +import numpy as np + +class NNLayer: + def __init__(self, input_size, output_size, activation_fn, activation_derivative_fn): + self.input_size = input_size + self.output_size = output_size + self.activation_fn = activation_fn + self.activation_derivative_fn = activation_derivative_fn + self.weights = 2 * np.random.rand(input_size, output_size) - 0.5 + self.biases = np.random.rand(output_size).reshape(1, -1) + + def forward(self, input_data): + self.input_data = input_data + self.z = np.dot(input_data, self.weights) + self.biases + self.a = self.activation_fn(self.z) + + return self.a + + def backward(self, dA, learning_rate=0.01): + dZ = dA * self.activation_derivative_fn(self.z) + dW = np.dot(self.input_data.T, dZ) / self.input_data.shape[0] + dB = np.sum(dZ, axis=0, keepdims=True) / self.input_data.shape[0] + dInputs = np.dot(dZ, self.weights.T) + + self.weights -= learning_rate * dW + self.biases -= learning_rate * dB + + return dInputs + +def sigmoid(x): + return 1 / (1 + np.exp(-x)) + +def sigmoid_derivative(x): + return sigmoid(x) * (1 - sigmoid(x)) + +def relu(x): + return np.maximum(0, x) + +def relu_derivative(x): + return np.heaviside(x, 1) + +def softmax(x): + exp_x = np.exp(x - np.max(x, axis=1, keepdims=True)) + return exp_x / np.sum(exp_x, axis=1, keepdims=True) + +def softmax_derivative(S): + jacobian = np.diag(S) + for i in range(len(jacobian)): + for j in range(len(jacobian[i])): + if i==j: + jacobian[i][j] = S[i] * (1 - S[j]) + else: + jacobian[i][j] = -S[j] * S[i] + + return jacobian + +def cross_entropy_loss(y_pred, y_true): + epsilon = 1e-15 + y_pred = np.clip(y_pred, epsilon, 1 - epsilon) + + tmp = y_true * np.log(y_pred) + loss = -np.sum(tmp, axis=1) + + loss = np.mean(loss) + + return loss + +def cross_entropy_derivative(y_pred, y_true): + return y_pred - y_true \ No newline at end of file diff --git a/NeuralNetwork.py b/NeuralNetwork.py new file mode 100644 index 0000000..294b846 --- /dev/null +++ b/NeuralNetwork.py @@ -0,0 +1,34 @@ +import numpy as np + +import NNLayer + + +class NeuralNetwork: + def __init__(self, input_size, hidden_sizes, output_size): + self.input_size = input_size + self.hidden_sizes = hidden_sizes + self.output_size = output_size + + def hidden_activation_function(self, x): + self.hidden_activation = x + + def hidden_activation_derivative(self, x): + self.hidden_activation_derivative = x + + def output_activation_function(self, x): + self.output_activation = x + + def output_activation_derivative(self, x): + self.output_activation_derivative = x + + def create_hidden_layers(self): + self.layers = [NNLayer.NNLayer(self.input_size, self.output_size, self.hidden_activation, self.hidden_activation_derivative()) + for _ in range(len(self.hidden_sizes))] + + def forward(self, input_data): + activation = np.array([]) + + for layer in self.layers: + activation = np.append(activation, layer.forward(input_data)) + + return activation \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..cd7a7c0 --- /dev/null +++ b/main.py @@ -0,0 +1,18 @@ +import NeuralNetwork as nn +import sklearn as sk +from sklearn.preprocessing import OneHotEncoder, StandardScaler + +if __name__ == '__main__': + + iris = sk.datasets.load_iris() + + X = iris.data + y = iris.target.reshape(-1, 1) + + encoded_labes = OneHotEncoder().fit_transform(y) + + train, test = sk.model_selection.train_test_split(X, test_size=0.2) + + standardized_features = StandardScaler().fit_transform(X) + +