From 456bea39288c05ae52dee63f1f2a4b4363ac2946 Mon Sep 17 00:00:00 2001 From: Sanam Bhanu Prakash <50152146+SanamBhanuPrakash@users.noreply.github.com> Date: Sun, 5 Jul 2026 07:52:41 +0000 Subject: [PATCH 1/4] orgate --- .vscode/settings.json | 1 - main.py | 47 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 main.py diff --git a/.vscode/settings.json b/.vscode/settings.json index e879633..9e1e7d7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -17,7 +17,6 @@ "files.autoSave": "afterDelay", "screencastMode.onlyKeyboardShortcuts": true, "terminal.integrated.fontSize": 18, - "workbench.activityBar.visible": true, "workbench.colorTheme": "Visual Studio Dark", "workbench.fontAliasing": "antialiased", "workbench.statusBar.visible": true, diff --git a/main.py b/main.py new file mode 100644 index 0000000..3ed2ce2 --- /dev/null +++ b/main.py @@ -0,0 +1,47 @@ +import numpy as np + +class Perceptron: + def __init__(self, inputs, bias=1.0): + # Initialize weights randomly between -1 and 1 + self.weights = (np.random.rand(inputs + 1) * 2) - 1 + self.bias = bias + + def run(self, x): + # Append the bias to the input list + x_with_bias = np.append(x, self.bias) + # Calculate weighted sum + x_sum = np.dot(x_with_bias, self.weights) + # Apply sigmoid activation function + return self.sigmoid(x_sum) + + def set_weights(self, w_init): + # Manually set weights for specific logic gates + self.weights = np.array(w_init) + + def sigmoid(self, x): + # Activation function to squash output between 0 and 1 + return 1 / (1 + np.exp(-x)) + +# --- TESTING AND GATE --- +neuron = Perceptron(inputs=2) +neuron.set_weights([10, 10, -15]) # AND Gate weights + +print("Gate (AND):") +print(f"0 0 = {neuron.run([0, 0]):.10f}") +print(f"0 1 = {neuron.run([0, 1]):.10f}") +print(f"1 0 = {neuron.run([1, 0]):.10f}") +print(f"1 1 = {neuron.run([1, 1]):.10f}") + +print("-" * 20) + +# --- TESTING OR GATE --- +neuron = Perceptron(inputs=2) +neuron.set_weights([15, 15, -10]) # OR Gate weights + +print("Gate (OR):") +print(f"0 0 = {neuron.run([0, 0]):.10f}") +print(f"0 1 = {neuron.run([0, 1]):.10f}") +print(f"1 0 = {neuron.run([1, 0]):.10f}") +print(f"1 1 = {neuron.run([1, 1]):.10f}") + + From df77f1d2cff1a9fab043952fc1a62b2c6fe9c416 Mon Sep 17 00:00:00 2001 From: Sanam Bhanu Prakash <50152146+SanamBhanuPrakash@users.noreply.github.com> Date: Sun, 5 Jul 2026 07:54:10 +0000 Subject: [PATCH 2/4] Xor gate --- main.py | 65 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/main.py b/main.py index 3ed2ce2..eb317f0 100644 --- a/main.py +++ b/main.py @@ -2,46 +2,63 @@ class Perceptron: def __init__(self, inputs, bias=1.0): - # Initialize weights randomly between -1 and 1 self.weights = (np.random.rand(inputs + 1) * 2) - 1 self.bias = bias def run(self, x): - # Append the bias to the input list x_with_bias = np.append(x, self.bias) - # Calculate weighted sum x_sum = np.dot(x_with_bias, self.weights) - # Apply sigmoid activation function return self.sigmoid(x_sum) def set_weights(self, w_init): - # Manually set weights for specific logic gates self.weights = np.array(w_init) def sigmoid(self, x): - # Activation function to squash output between 0 and 1 return 1 / (1 + np.exp(-x)) -# --- TESTING AND GATE --- -neuron = Perceptron(inputs=2) -neuron.set_weights([10, 10, -15]) # AND Gate weights - -print("Gate (AND):") -print(f"0 0 = {neuron.run([0, 0]):.10f}") -print(f"0 1 = {neuron.run([0, 1]):.10f}") -print(f"1 0 = {neuron.run([1, 0]):.10f}") -print(f"1 1 = {neuron.run([1, 1]):.10f}") +class MultiLayerPerceptron: + def __init__(self, layers, bias=1.0): + self.layers = np.array(layers, dtype=object) + self.bias = bias + self.network = [] + self.values = [] + + for i in range(len(self.layers)): + self.values.append([0.0 for j in range(self.layers[i])]) + if i > 0: # Only create neurons for layers after the input layer + layer = [Perceptron(inputs=self.layers[i-1], bias=self.bias) for j in range(self.layers[i])] + self.network.append(layer) + + self.network = np.array([np.array(x) for x in self.network], dtype=object) + self.values = np.array([np.array(x) for x in self.values], dtype=object) -print("-" * 20) + def set_weights(self, w_init): + # Loops through the layers and neurons to assign weights + for i in range(len(w_init)): + for j in range(len(w_init[i])): + self.network[i][j].set_weights(w_init[i][j]) -# --- TESTING OR GATE --- -neuron = Perceptron(inputs=2) -neuron.set_weights([15, 15, -10]) # OR Gate weights + def printWeights(self): + for i in range(1, len(self.network) + 1): + for j in range(len(self.network[i-1])): + print("Layer", i, "Neuron", j, self.network[i-1][j].weights) + print() -print("Gate (OR):") -print(f"0 0 = {neuron.run([0, 0]):.10f}") -print(f"0 1 = {neuron.run([0, 1]):.10f}") -print(f"1 0 = {neuron.run([1, 0]):.10f}") -print(f"1 1 = {neuron.run([1, 1]):.10f}") + def run(self, x): + self.values[0] = x + for i in range(1, len(self.network) + 1): + for j in range(self.layers[i]): + self.values[i][j] = self.network[i-1][j].run(self.values[i-1]) + return self.values[-1] +# --- XOR TEST CODE --- +mlp = MultiLayerPerceptron(layers=[2, 2, 1]) +# These weights are specifically tuned for XOR logic +mlp.set_weights([[[-10, -10, 15], [15, 15, -10]], [[10, 10, -15]]]) +mlp.printWeights() +print("MLP (XOR Gate):") +print(f"0 0 = {mlp.run([0, 0])[0]:.10f}") +print(f"0 1 = {mlp.run([0, 1])[0]:.10f}") +print(f"1 0 = {mlp.run([1, 0])[0]:.10f}") +print(f"1 1 = {mlp.run([1, 1])[0]:.10f}") \ No newline at end of file From 21c6d3eb71ecb70b4fa6e3c72db9cb8d162c3148 Mon Sep 17 00:00:00 2001 From: Sanam Bhanu Prakash <50152146+SanamBhanuPrakash@users.noreply.github.com> Date: Mon, 6 Jul 2026 18:24:55 +0000 Subject: [PATCH 3/4] Backpropagation Algorithm Implementation for a Multi-Layer Perceptron --- main.py | 68 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/main.py b/main.py index eb317f0..965b5aa 100644 --- a/main.py +++ b/main.py @@ -17,32 +17,24 @@ def sigmoid(self, x): return 1 / (1 + np.exp(-x)) class MultiLayerPerceptron: - def __init__(self, layers, bias=1.0): + def __init__(self, layers, bias=1.0, eta=0.5): self.layers = np.array(layers, dtype=object) self.bias = bias + self.eta = eta self.network = [] self.values = [] - + self.d = [] + for i in range(len(self.layers)): self.values.append([0.0 for j in range(self.layers[i])]) - if i > 0: # Only create neurons for layers after the input layer + self.d.append([0.0 for j in range(self.layers[i])]) + if i > 0: layer = [Perceptron(inputs=self.layers[i-1], bias=self.bias) for j in range(self.layers[i])] self.network.append(layer) self.network = np.array([np.array(x) for x in self.network], dtype=object) self.values = np.array([np.array(x) for x in self.values], dtype=object) - - def set_weights(self, w_init): - # Loops through the layers and neurons to assign weights - for i in range(len(w_init)): - for j in range(len(w_init[i])): - self.network[i][j].set_weights(w_init[i][j]) - - def printWeights(self): - for i in range(1, len(self.network) + 1): - for j in range(len(self.network[i-1])): - print("Layer", i, "Neuron", j, self.network[i-1][j].weights) - print() + self.d = np.array([np.array(x) for x in self.d], dtype=object) def run(self, x): self.values[0] = x @@ -51,14 +43,42 @@ def run(self, x): self.values[i][j] = self.network[i-1][j].run(self.values[i-1]) return self.values[-1] -# --- XOR TEST CODE --- + def bp(self, x, y): + outputs = self.run(x) + error = (y - outputs) + + # Calculate output layer error terms (deltas) + self.d[-1] = outputs * (1 - outputs) * error + + # Calculate error terms for hidden layers + for i in reversed(range(1, len(self.network))): + for h in range(len(self.network[i-1])): + fwd_error = 0.0 + for k in range(self.layers[i+1]): + fwd_error += self.network[i][k].weights[h] * self.d[i+1][k] + self.d[i][h] = self.values[i][h] * (1 - self.values[i][h]) * fwd_error + + # Update weights + for i in range(1, len(self.network) + 1): + for j in range(self.layers[i]): + for k in range(self.layers[i-1] + 1): + if k == self.layers[i-1]: + delta = self.eta * self.d[i][j] * self.bias + else: + delta = self.eta * self.d[i][j] * self.values[i-1][k] + self.network[i-1][j].weights[k] += delta + return sum(error**2) + +# Training mlp = MultiLayerPerceptron(layers=[2, 2, 1]) -# These weights are specifically tuned for XOR logic -mlp.set_weights([[[-10, -10, 15], [15, 15, -10]], [[10, 10, -15]]]) +print("Training Neural Network as an XOR Gate...\n") +for i in range(5000): + mse = (mlp.bp([0,0],[0]) + mlp.bp([0,1],[1]) + mlp.bp([1,0],[1]) + mlp.bp([1,1],[0])) / 4 + if i % 500 == 0: + print(f"MSE: {mse:.6f}") -mlp.printWeights() -print("MLP (XOR Gate):") -print(f"0 0 = {mlp.run([0, 0])[0]:.10f}") -print(f"0 1 = {mlp.run([0, 1])[0]:.10f}") -print(f"1 0 = {mlp.run([1, 0])[0]:.10f}") -print(f"1 1 = {mlp.run([1, 1])[0]:.10f}") \ No newline at end of file +print("\nFinal XOR Results:") +print(f"0 0 = {mlp.run([0,0])[0]:.4f}") +print(f"0 1 = {mlp.run([0,1])[0]:.4f}") +print(f"1 0 = {mlp.run([1,0])[0]:.4f}") +print(f"1 1 = {mlp.run([1,1])[0]:.4f}") \ No newline at end of file From 7b3f88b11c25e25afcdcfa9a4b179d23c539f65c Mon Sep 17 00:00:00 2001 From: Sanam Bhanu Prakash <50152146+SanamBhanuPrakash@users.noreply.github.com> Date: Wed, 8 Jul 2026 16:45:37 +0000 Subject: [PATCH 4/4] Organize neural network implementations into separate project directories --- AND-Gate/main.py | 35 +++++ main.py => Backpropagation/main.py | 0 Multi-Layer-Perceptron/main.py | 136 +++++++++++++++++++ OR-Gate/main.py | 47 +++++++ Seven-Segment-Display-Recognition/main.py | 152 ++++++++++++++++++++++ XOR-Gate/main.py | 64 +++++++++ 6 files changed, 434 insertions(+) create mode 100644 AND-Gate/main.py rename main.py => Backpropagation/main.py (100%) create mode 100644 Multi-Layer-Perceptron/main.py create mode 100644 OR-Gate/main.py create mode 100644 Seven-Segment-Display-Recognition/main.py create mode 100644 XOR-Gate/main.py diff --git a/AND-Gate/main.py b/AND-Gate/main.py new file mode 100644 index 0000000..70aeacb --- /dev/null +++ b/AND-Gate/main.py @@ -0,0 +1,35 @@ +import numpy as np + +class Perceptron: + def __init__(self, inputs, bias=1.0): + # Initialize weights randomly between -1 and 1 + self.weights = (np.random.rand(inputs + 1) * 2) - 1 + self.bias = bias + + def run(self, x): + # Append the bias to the input list + x_with_bias = np.append(x, self.bias) + # Calculate weighted sum + x_sum = np.dot(x_with_bias, self.weights) + # Apply sigmoid activation function + return self.sigmoid(x_sum) + + def set_weights(self, w_init): + # Manually set weights for specific logic gates + self.weights = np.array(w_init) + + def sigmoid(self, x): + # Activation function to squash output between 0 and 1 + return 1 / (1 + np.exp(-x)) + +# --- TESTING AND GATE --- +neuron = Perceptron(inputs=2) +neuron.set_weights([10, 10, -15]) # AND Gate weights + +print("Gate (AND):") +print(f"0 0 = {neuron.run([0, 0]):.10f}") +print(f"0 1 = {neuron.run([0, 1]):.10f}") +print(f"1 0 = {neuron.run([1, 0]):.10f}") +print(f"1 1 = {neuron.run([1, 1]):.10f}") + +print("-" * 20) diff --git a/main.py b/Backpropagation/main.py similarity index 100% rename from main.py rename to Backpropagation/main.py diff --git a/Multi-Layer-Perceptron/main.py b/Multi-Layer-Perceptron/main.py new file mode 100644 index 0000000..0f94315 --- /dev/null +++ b/Multi-Layer-Perceptron/main.py @@ -0,0 +1,136 @@ +import numpy as np + + +class Perceptron: + def __init__(self, inputs, bias=1.0): + # Initialize random weights (including one weight for the bias) + self.weights = (np.random.rand(inputs + 1) * 2) - 1 + self.bias = bias + + def run(self, x): + # Add the bias input + x_with_bias = np.append(x, self.bias) + + # Calculate weighted sum + x_sum = np.dot(x_with_bias, self.weights) + + # Apply sigmoid activation + return self.sigmoid(x_sum) + + def set_weights(self, w_init): + self.weights = np.array(w_init) + + def sigmoid(self, x): + return 1 / (1 + np.exp(-x)) + + +class MultiLayerPerceptron: + def __init__(self, layers, bias=1.0): + self.layers = np.array(layers, dtype=object) + self.bias = bias + + # Stores all neurons in the network + self.network = [] + + # Stores the output value of every neuron + self.values = [] + + # Build the network + for i in range(len(self.layers)): + # Allocate memory for each layer's outputs + self.values.append([0.0 for _ in range(self.layers[i])]) + + # Skip the input layer (it contains no neurons) + if i > 0: + layer = [ + Perceptron(inputs=self.layers[i - 1], bias=self.bias) + for _ in range(self.layers[i]) + ] + self.network.append(layer) + + self.network = np.array( + [np.array(layer) for layer in self.network], + dtype=object + ) + + self.values = np.array( + [np.array(layer) for layer in self.values], + dtype=object + ) + + def set_weights(self, weights): + """ + Assign manually configured weights to every neuron. + + Network Structure: + Input(2) -> Hidden(2) -> Output(1) + + Hidden Layer + Neuron 1 : [-10, -10, 15] + Neuron 2 : [15, 15, -10] + + Output Layer + Neuron 1 : [10, 10, -15] + """ + + for layer_index in range(len(weights)): + for neuron_index in range(len(weights[layer_index])): + self.network[layer_index][neuron_index].set_weights( + weights[layer_index][neuron_index] + ) + + def print_weights(self): + print("Neural Network Weights\n") + + for layer in range(1, len(self.network) + 1): + for neuron in range(len(self.network[layer - 1])): + print( + f"Layer {layer} " + f"Neuron {neuron} : " + f"{self.network[layer - 1][neuron].weights}" + ) + + print() + + def run(self, x): + # Input layer values + self.values[0] = x + + # Forward propagation + for layer in range(1, len(self.network) + 1): + for neuron in range(self.layers[layer]): + self.values[layer][neuron] = ( + self.network[layer - 1][neuron].run( + self.values[layer - 1] + ) + ) + + return self.values[-1] + + +# ---------------------------------------------------- +# XOR Demonstration +# ---------------------------------------------------- + +# Create a 2-2-1 Multi-Layer Perceptron +mlp = MultiLayerPerceptron(layers=[2, 2, 1]) + +# Manually assign weights that solve XOR +mlp.set_weights([ + [ + [-10, -10, 15], + [15, 15, -10] + ], + [ + [10, 10, -15] + ] +]) + +mlp.print_weights() + +print("Multi-Layer Perceptron (XOR Gate)\n") + +print(f"0 XOR 0 = {mlp.run([0, 0])[0]:.10f}") +print(f"0 XOR 1 = {mlp.run([0, 1])[0]:.10f}") +print(f"1 XOR 0 = {mlp.run([1, 0])[0]:.10f}") +print(f"1 XOR 1 = {mlp.run([1, 1])[0]:.10f}") \ No newline at end of file diff --git a/OR-Gate/main.py b/OR-Gate/main.py new file mode 100644 index 0000000..3ed2ce2 --- /dev/null +++ b/OR-Gate/main.py @@ -0,0 +1,47 @@ +import numpy as np + +class Perceptron: + def __init__(self, inputs, bias=1.0): + # Initialize weights randomly between -1 and 1 + self.weights = (np.random.rand(inputs + 1) * 2) - 1 + self.bias = bias + + def run(self, x): + # Append the bias to the input list + x_with_bias = np.append(x, self.bias) + # Calculate weighted sum + x_sum = np.dot(x_with_bias, self.weights) + # Apply sigmoid activation function + return self.sigmoid(x_sum) + + def set_weights(self, w_init): + # Manually set weights for specific logic gates + self.weights = np.array(w_init) + + def sigmoid(self, x): + # Activation function to squash output between 0 and 1 + return 1 / (1 + np.exp(-x)) + +# --- TESTING AND GATE --- +neuron = Perceptron(inputs=2) +neuron.set_weights([10, 10, -15]) # AND Gate weights + +print("Gate (AND):") +print(f"0 0 = {neuron.run([0, 0]):.10f}") +print(f"0 1 = {neuron.run([0, 1]):.10f}") +print(f"1 0 = {neuron.run([1, 0]):.10f}") +print(f"1 1 = {neuron.run([1, 1]):.10f}") + +print("-" * 20) + +# --- TESTING OR GATE --- +neuron = Perceptron(inputs=2) +neuron.set_weights([15, 15, -10]) # OR Gate weights + +print("Gate (OR):") +print(f"0 0 = {neuron.run([0, 0]):.10f}") +print(f"0 1 = {neuron.run([0, 1]):.10f}") +print(f"1 0 = {neuron.run([1, 0]):.10f}") +print(f"1 1 = {neuron.run([1, 1]):.10f}") + + diff --git a/Seven-Segment-Display-Recognition/main.py b/Seven-Segment-Display-Recognition/main.py new file mode 100644 index 0000000..1a724de --- /dev/null +++ b/Seven-Segment-Display-Recognition/main.py @@ -0,0 +1,152 @@ +import numpy as np + +class Perceptron: + def __init__(self, inputs, bias=1.0): + self.weights = (np.random.rand(inputs + 1) * 2) - 1 + self.bias = bias + + def run(self, x): + x_with_bias = np.append(x, self.bias) + x_sum = np.dot(x_with_bias, self.weights) + return self.sigmoid(x_sum) + + def set_weights(self, w_init): + self.weights = np.array(w_init) + + def sigmoid(self, x): + return 1 / (1 + np.exp(-x)) + +class MultiLayerPerceptron: + def __init__(self, layers, bias=1.0, eta=0.5): + self.layers = np.array(layers, dtype=object) + self.bias = bias + self.eta = eta + self.network = [] + self.values = [] + self.d = [] + + for i in range(len(self.layers)): + self.values.append([0.0 for j in range(self.layers[i])]) + self.d.append([0.0 for j in range(self.layers[i])]) + if i > 0: + layer = [Perceptron(inputs=self.layers[i-1], bias=self.bias) for j in range(self.layers[i])] + self.network.append(layer) + + self.network = np.array([np.array(x) for x in self.network], dtype=object) + self.values = np.array([np.array(x) for x in self.values], dtype=object) + self.d = np.array([np.array(x) for x in self.d], dtype=object) + + def run(self, x): + self.values[0] = x + for i in range(1, len(self.network) + 1): + for j in range(self.layers[i]): + self.values[i][j] = self.network[i-1][j].run(self.values[i-1]) + return self.values[-1] + + def bp(self, x, y): + outputs = self.run(x) + error = (y - outputs) + + # Output layer deltas + self.d[-1] = outputs * (1 - outputs) * error + + # Hidden layer deltas + for i in reversed(range(1, len(self.network))): + for h in range(len(self.network[i-1])): + fwd_error = 0.0 + for k in range(self.layers[i+1]): + fwd_error += self.network[i][k].weights[h] * self.d[i+1][k] + self.d[i][h] = self.values[i][h] * (1 - self.values[i][h]) * fwd_error + + # Update weights + for i in range(1, len(self.network) + 1): + for j in range(self.layers[i]): + for k in range(self.layers[i-1] + 1): + if k == self.layers[i-1]: + delta = self.eta * self.d[i][j] * self.bias + else: + delta = self.eta * self.d[i][j] * self.values[i-1][k] + self.network[i-1][j].weights[k] += delta + return sum(error**2) + +# --- TRAINING THE 7-SEGMENT DISPLAY --- + +epochs = int(input("How many epochs? ")) +print("Training networks, please wait...") + +# Create the 3 different architectures +mlp1 = MultiLayerPerceptron(layers=[7,7,1]) +mlp2 = MultiLayerPerceptron(layers=[7,7,10]) +mlp3 = MultiLayerPerceptron(layers=[7,7,7]) + +# Dataset for the 7 to 1 network +for i in range(epochs): + mse = 0.0 + mse += mlp1.bp([1,1,1,1,1,1,0],[0.05]) + mse += mlp1.bp([0,1,1,0,0,0,0],[0.15]) + mse += mlp1.bp([1,1,0,1,1,0,1],[0.25]) + mse += mlp1.bp([1,1,1,1,0,0,1],[0.35]) + mse += mlp1.bp([0,1,1,0,0,1,1],[0.45]) + mse += mlp1.bp([1,0,1,1,0,1,1],[0.55]) + mse += mlp1.bp([1,0,1,1,1,1,1],[0.65]) + mse += mlp1.bp([1,1,1,0,0,0,0],[0.75]) + mse += mlp1.bp([1,1,1,1,1,1,1],[0.85]) + mse += mlp1.bp([1,1,1,1,0,1,1],[0.95]) + mse = mse/10.0 + +# Dataset for the 7 to 10 network +for i in range(epochs): + mse = 0.0 + mse += mlp2.bp([1,1,1,1,1,1,0], [1,0,0,0,0,0,0,0,0,0]) + mse += mlp2.bp([0,1,1,0,0,0,0], [0,1,0,0,0,0,0,0,0,0]) + mse += mlp2.bp([1,1,0,1,1,0,1], [0,0,1,0,0,0,0,0,0,0]) + mse += mlp2.bp([1,1,1,1,0,0,1], [0,0,0,1,0,0,0,0,0,0]) + mse += mlp2.bp([0,1,1,0,0,1,1], [0,0,0,0,1,0,0,0,0,0]) + mse += mlp2.bp([1,0,1,1,0,1,1], [0,0,0,0,0,1,0,0,0,0]) + mse += mlp2.bp([1,0,1,1,1,1,1], [0,0,0,0,0,0,1,0,0,0]) + mse += mlp2.bp([1,1,1,0,0,0,0], [0,0,0,0,0,0,0,1,0,0]) + mse += mlp2.bp([1,1,1,1,1,1,1], [0,0,0,0,0,0,0,0,1,0]) + mse += mlp2.bp([1,1,1,1,0,1,1], [0,0,0,0,0,0,0,0,0,1]) + mse = mse/10.0 + +# Dataset for the 7 to 7 network +for i in range(epochs): + mse = 0.0 + mse += mlp3.bp([1,1,1,1,1,1,0], [1,1,1,1,1,1,0]) + mse += mlp3.bp([0,1,1,0,0,0,0], [0,1,1,0,0,0,0]) + mse += mlp3.bp([1,1,0,1,1,0,1], [1,1,0,1,1,0,1]) + mse += mlp3.bp([1,1,1,1,0,0,1], [1,1,1,1,0,0,1]) + mse += mlp3.bp([0,1,1,0,0,1,1], [0,1,1,0,0,1,1]) + mse += mlp3.bp([1,0,1,1,0,1,1], [1,0,1,1,0,1,1]) + mse += mlp3.bp([1,0,1,1,1,1,1], [1,0,1,1,1,1,1]) + mse += mlp3.bp([1,1,1,0,0,0,0], [1,1,1,0,0,0,0]) + mse += mlp3.bp([1,1,1,1,1,1,1], [1,1,1,1,1,1,1]) + mse += mlp3.bp([1,1,1,1,0,1,1], [1,1,1,1,0,1,1]) + mse = mse/10.0 + +print("Done Training!\n") + +# --- INTERACTIVE TESTING --- +pattern = [1.2] +while (pattern[0] >= 0.0): + try: + # Ask user for a pattern (e.g. 0 1 1 0 0 0 0 for '1') + user_input = input("Input pattern 'a b c d e f g' (or -1 to quit): ") + pattern = list(map(float, user_input.strip().split())) + + if pattern[0] < 0.0: + print("Exiting...") + break + + print() + # mlp1 returns a single probability in an array, so we grab [0] and multiply by 10 + print("The number recognized by the 7 to 1 network is:", int(mlp1.run(pattern)[0] * 10)) + + # mlp2 returns 10 probabilities. np.argmax finds the index of the highest one. + print("The number recognized by the 7 to 10 network is:", np.argmax(mlp2.run(pattern))) + + # mlp3 returns 7 probabilities. We add 0.5 and cast to int to round them to 0 or 1. + print("The pattern recognized by the 7 to 7 network is:", [int(x) for x in (mlp3.run(pattern) + 0.5)], "\n") + + except Exception as e: + print("Invalid input. Please enter 7 numbers separated by spaces (e.g. '1 1 1 1 1 1 0').") \ No newline at end of file diff --git a/XOR-Gate/main.py b/XOR-Gate/main.py new file mode 100644 index 0000000..eb317f0 --- /dev/null +++ b/XOR-Gate/main.py @@ -0,0 +1,64 @@ +import numpy as np + +class Perceptron: + def __init__(self, inputs, bias=1.0): + self.weights = (np.random.rand(inputs + 1) * 2) - 1 + self.bias = bias + + def run(self, x): + x_with_bias = np.append(x, self.bias) + x_sum = np.dot(x_with_bias, self.weights) + return self.sigmoid(x_sum) + + def set_weights(self, w_init): + self.weights = np.array(w_init) + + def sigmoid(self, x): + return 1 / (1 + np.exp(-x)) + +class MultiLayerPerceptron: + def __init__(self, layers, bias=1.0): + self.layers = np.array(layers, dtype=object) + self.bias = bias + self.network = [] + self.values = [] + + for i in range(len(self.layers)): + self.values.append([0.0 for j in range(self.layers[i])]) + if i > 0: # Only create neurons for layers after the input layer + layer = [Perceptron(inputs=self.layers[i-1], bias=self.bias) for j in range(self.layers[i])] + self.network.append(layer) + + self.network = np.array([np.array(x) for x in self.network], dtype=object) + self.values = np.array([np.array(x) for x in self.values], dtype=object) + + def set_weights(self, w_init): + # Loops through the layers and neurons to assign weights + for i in range(len(w_init)): + for j in range(len(w_init[i])): + self.network[i][j].set_weights(w_init[i][j]) + + def printWeights(self): + for i in range(1, len(self.network) + 1): + for j in range(len(self.network[i-1])): + print("Layer", i, "Neuron", j, self.network[i-1][j].weights) + print() + + def run(self, x): + self.values[0] = x + for i in range(1, len(self.network) + 1): + for j in range(self.layers[i]): + self.values[i][j] = self.network[i-1][j].run(self.values[i-1]) + return self.values[-1] + +# --- XOR TEST CODE --- +mlp = MultiLayerPerceptron(layers=[2, 2, 1]) +# These weights are specifically tuned for XOR logic +mlp.set_weights([[[-10, -10, 15], [15, 15, -10]], [[10, 10, -15]]]) + +mlp.printWeights() +print("MLP (XOR Gate):") +print(f"0 0 = {mlp.run([0, 0])[0]:.10f}") +print(f"0 1 = {mlp.run([0, 1])[0]:.10f}") +print(f"1 0 = {mlp.run([1, 0])[0]:.10f}") +print(f"1 1 = {mlp.run([1, 1])[0]:.10f}") \ No newline at end of file