From bbfe2d6645ae311707b0869bfa2244fa3cff228c Mon Sep 17 00:00:00 2001 From: felipe Date: Tue, 24 Sep 2024 18:36:11 -0300 Subject: [PATCH] updated README and added documentation for #1 Single Layer Perceptrons modified: README.md modified: perceptrons.ipynb --- README.md | 38 ++++++++++++++++++++++++++++++++++++-- perceptrons.ipynb | 2 +- step_function_plot.png | Bin 0 -> 18326 bytes 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 step_function_plot.png diff --git a/README.md b/README.md index 26929c9..218829b 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,40 @@ This project implements artificial neural networks (ANN) using perceptrons as per the ANN university subject. -1. Single Layer +0. [Sum Function](#0-sum-function) +1. [Single Layer](#1-single-layer-perceptron) 2. Single Layer and Training -3. Multi Layer \ No newline at end of file +3. Multi Layer + +## 0. Sum Function + The sum_function is designed to compute the sum of the products of corresponding elements from two lists: inputs and weights. This is a common operation in neural networks, particularly in the calculation of the net input to a neuron. + +```python +def sum_function(inputs, weights) -> float: + ''' + Sum of the product of the inputs by the weights + + @return float: The Net Input / Pre-Activation result + ''' + + ... +``` + +## 1. Single Layer Perceptron + In this section, we implement a simple step function, which is often used in academic settings to illustrate the basic principles of neural networks and perceptrons. + +```python +def step_function(net_input) -> int: + ''' + 1, if net_input >= 1 + 0, if net_input < 1 + + @return int: The Activation result + ''' + + ... +``` +> The following chart is made using both the `Sum` and `Step` functions + +![Step Function Plot](step_function_plot.png) + diff --git a/perceptrons.ipynb b/perceptrons.ipynb index 551e357..ada233f 100644 --- a/perceptrons.ipynb +++ b/perceptrons.ipynb @@ -1 +1 @@ -{"cells":[{"cell_type":"markdown","metadata":{},"source":["# Perceptron Networks\n","1. Single Layer\n","2. Single Layer and Training\n","3. Multi Layer\n","\n","## 1. Single Layer perceptron"]},{"cell_type":"code","execution_count":2,"metadata":{"execution":{"iopub.execute_input":"2024-09-23T22:05:27.183684Z","iopub.status.busy":"2024-09-23T22:05:27.181778Z","iopub.status.idle":"2024-09-23T22:05:27.191100Z","shell.execute_reply":"2024-09-23T22:05:27.189735Z","shell.execute_reply.started":"2024-09-23T22:05:27.183607Z"},"trusted":true},"outputs":[],"source":["import numpy as np"]},{"cell_type":"code","execution_count":3,"metadata":{"execution":{"iopub.execute_input":"2024-09-23T22:05:27.194942Z","iopub.status.busy":"2024-09-23T22:05:27.194269Z","iopub.status.idle":"2024-09-23T22:05:27.202310Z","shell.execute_reply":"2024-09-23T22:05:27.201067Z","shell.execute_reply.started":"2024-09-23T22:05:27.194868Z"},"trusted":true},"outputs":[],"source":["def sum_function(inputs, weights):\n"," return inputs.dot(weights)\n"," \n","def step_function(raw_output):\n"," return int(raw_output >= 1)"]},{"cell_type":"code","execution_count":4,"metadata":{"execution":{"iopub.execute_input":"2024-09-23T22:05:27.204206Z","iopub.status.busy":"2024-09-23T22:05:27.203839Z","iopub.status.idle":"2024-09-23T22:05:27.214666Z","shell.execute_reply":"2024-09-23T22:05:27.213260Z","shell.execute_reply.started":"2024-09-23T22:05:27.204165Z"},"trusted":true},"outputs":[],"source":["inputs = np.array([-1, 7, 5])\n","weights = np.array([.8, .1, 0])"]},{"cell_type":"code","execution_count":5,"metadata":{"execution":{"iopub.execute_input":"2024-09-23T22:05:27.217168Z","iopub.status.busy":"2024-09-23T22:05:27.216617Z","iopub.status.idle":"2024-09-23T22:05:27.227334Z","shell.execute_reply":"2024-09-23T22:05:27.226101Z","shell.execute_reply.started":"2024-09-23T22:05:27.217088Z"},"trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["Summation: -0.09999999999999998\n","Step Func: 0\n"]}],"source":["s = sum_function(inputs, weights)\n","r = step_function(s)\n","\n","print(f'Summation: {s}\\nStep Func: {r}')"]},{"cell_type":"markdown","metadata":{},"source":["## 2. Single layer with Training\n","> Now a ANN to predict logic gate (AND, NAND, OR, NOR) outputs based on two inputs"]},{"cell_type":"code","execution_count":6,"metadata":{"execution":{"iopub.execute_input":"2024-09-23T22:05:27.230633Z","iopub.status.busy":"2024-09-23T22:05:27.230175Z","iopub.status.idle":"2024-09-23T22:05:27.240407Z","shell.execute_reply":"2024-09-23T22:05:27.239036Z","shell.execute_reply.started":"2024-09-23T22:05:27.230590Z"},"trusted":true},"outputs":[],"source":["inputs = np.array([\n"," [0,0], # 0\n"," [0,1], # 1\n"," [1,0], # 2\n"," [1,1], # 3\n","])\n","\n","outputs = {\n"," 'AND': np.array([0,0,0,1]),\n"," 'NAND': np.array([1,1,1,0]),\n"," 'OR': np.array([0,1,1,1]),\n"," 'NOR': np.array([1,0,0,0]),\n","}\n","\n","LEARN_RATE = 0.1"]},{"cell_type":"code","execution_count":7,"metadata":{"execution":{"iopub.execute_input":"2024-09-23T22:06:51.503104Z","iopub.status.busy":"2024-09-23T22:06:51.502560Z","iopub.status.idle":"2024-09-23T22:06:51.518048Z","shell.execute_reply":"2024-09-23T22:06:51.516346Z","shell.execute_reply.started":"2024-09-23T22:06:51.503057Z"},"trusted":true},"outputs":[],"source":["def get_output(inputs, weights):\n"," s = sum_function(inputs, weights)\n"," return step_function(s)\n","\n","def train(gate):\n"," total_error = 1\n"," weights = np.array([0.0, 0.0]) # manually set\n"," GATE = outputs[gate]\n"," epoch = 0\n"," \n"," while(total_error != 0): # STOP CONDITION\n"," total_error = 0\n"," epoch += 1\n"," \n"," print(f'WEIGHTS: {weights}')\n"," for i in range(len(GATE)): # ERROR UPDATE\n"," current_output = get_output(np.asarray(inputs[i]), weights)\n"," current_error = abs(GATE[i] - current_output)\n"," total_error += current_error\n"," \n","\n"," print(f'IN{[i]}: ________ {inputs[i]}')\n"," for j in range(len(weights)): # LEARNING PHASE\n"," tmp_weight = weights[j]\n"," weights[j] = weights[j] + (LEARN_RATE * inputs[i][j] * current_error)\n","\n"," print(f'\\tOUT[{j}]: {current_output}', end='')\n"," \n"," if weights[j] != tmp_weight:\n"," print(f', Weight[{j}] updated: {weights[j]}')\n"," else:\n"," print()\n"," \n"," print(f'\\tcurrent_error: {current_error}')\n"," \n"," print(f'\\n --- END OF EPOCH {epoch} Total error {total_error}', '----------------------------', '\\n')\n"," print(f'>>> Training complete!')\n"," print(f'Final weights: W0={weights[0]} and W1={weights[1]}')"]},{"cell_type":"code","execution_count":8,"metadata":{"collapsed":true,"execution":{"iopub.execute_input":"2024-09-23T22:06:54.010218Z","iopub.status.busy":"2024-09-23T22:06:54.009791Z","iopub.status.idle":"2024-09-23T22:06:54.024485Z","shell.execute_reply":"2024-09-23T22:06:54.023164Z","shell.execute_reply.started":"2024-09-23T22:06:54.010177Z"},"jupyter":{"outputs_hidden":true},"trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["WEIGHTS: [0. 0.]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.1\n","\tOUT[1]: 0, Weight[1] updated: 0.1\n","\tcurrent_error: 1\n","\n"," --- END OF EPOCH 1 Total error 1 ---------------------------- \n","\n","WEIGHTS: [0.1 0.1]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.2\n","\tOUT[1]: 0, Weight[1] updated: 0.2\n","\tcurrent_error: 1\n","\n"," --- END OF EPOCH 2 Total error 1 ---------------------------- \n","\n","WEIGHTS: [0.2 0.2]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.30000000000000004\n","\tOUT[1]: 0, Weight[1] updated: 0.30000000000000004\n","\tcurrent_error: 1\n","\n"," --- END OF EPOCH 3 Total error 1 ---------------------------- \n","\n","WEIGHTS: [0.3 0.3]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.4\n","\tOUT[1]: 0, Weight[1] updated: 0.4\n","\tcurrent_error: 1\n","\n"," --- END OF EPOCH 4 Total error 1 ---------------------------- \n","\n","WEIGHTS: [0.4 0.4]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.5\n","\tOUT[1]: 0, Weight[1] updated: 0.5\n","\tcurrent_error: 1\n","\n"," --- END OF EPOCH 5 Total error 1 ---------------------------- \n","\n","WEIGHTS: [0.5 0.5]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 6 Total error 0 ---------------------------- \n","\n",">>> Training complete!\n","Final weights: W0=0.5 and W1=0.5\n"]}],"source":["train('AND')"]},{"cell_type":"code","execution_count":9,"metadata":{"collapsed":true,"execution":{"iopub.execute_input":"2024-09-23T22:07:15.312100Z","iopub.status.busy":"2024-09-23T22:07:15.311614Z","iopub.status.idle":"2024-09-23T22:07:15.330061Z","shell.execute_reply":"2024-09-23T22:07:15.328726Z","shell.execute_reply.started":"2024-09-23T22:07:15.312052Z"},"jupyter":{"outputs_hidden":true},"trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["WEIGHTS: [0. 0.]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.1\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.1\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.2\n","\tOUT[1]: 0, Weight[1] updated: 0.2\n","\tcurrent_error: 1\n","\n"," --- END OF EPOCH 1 Total error 3 ---------------------------- \n","\n","WEIGHTS: [0.2 0.2]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.30000000000000004\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.30000000000000004\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.4\n","\tOUT[1]: 0, Weight[1] updated: 0.4\n","\tcurrent_error: 1\n","\n"," --- END OF EPOCH 2 Total error 3 ---------------------------- \n","\n","WEIGHTS: [0.4 0.4]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.5\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.5\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 3 Total error 2 ---------------------------- \n","\n","WEIGHTS: [0.5 0.5]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.6\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.6\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 4 Total error 2 ---------------------------- \n","\n","WEIGHTS: [0.6 0.6]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.7\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.7\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 5 Total error 2 ---------------------------- \n","\n","WEIGHTS: [0.7 0.7]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.7999999999999999\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.7999999999999999\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 6 Total error 2 ---------------------------- \n","\n","WEIGHTS: [0.8 0.8]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.8999999999999999\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.8999999999999999\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 7 Total error 2 ---------------------------- \n","\n","WEIGHTS: [0.9 0.9]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.9999999999999999\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.9999999999999999\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 8 Total error 2 ---------------------------- \n","\n","WEIGHTS: [1. 1.]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 1.0999999999999999\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 1.0999999999999999\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 9 Total error 2 ---------------------------- \n","\n","WEIGHTS: [1.1 1.1]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 10 Total error 0 ---------------------------- \n","\n",">>> Training complete!\n","Final weights: W0=1.0999999999999999 and W1=1.0999999999999999\n"]}],"source":["train('OR')"]},{"cell_type":"code","execution_count":12,"metadata":{},"outputs":[],"source":["# WONT STOP BECAUSE OF STOP CONDITION\n","# train('NAND') - Keeps increasing weights\n","# train('NOR') - Never updates weights"]},{"cell_type":"markdown","metadata":{},"source":["## 3. Multi-layer perceptron"]},{"cell_type":"code","execution_count":13,"metadata":{},"outputs":[],"source":["# TODO"]}],"metadata":{"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":30761,"isGpuEnabled":false,"isInternetEnabled":true,"language":"python","sourceType":"notebook"},"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.4"}},"nbformat":4,"nbformat_minor":4} +{"cells":[{"cell_type":"markdown","metadata":{},"source":["# Perceptron Networks\n","0. [Sum Function](#0-sum-function)\n","1. Single Layer\n","2. Single Layer and Training\n","3. Multi Layer\n","\n","## 0. Sum Function\n"," This Summation function will be used for the three models of perceptron used in this notebook."]},{"cell_type":"code","execution_count":50,"metadata":{"execution":{"iopub.execute_input":"2024-09-23T22:05:27.183684Z","iopub.status.busy":"2024-09-23T22:05:27.181778Z","iopub.status.idle":"2024-09-23T22:05:27.191100Z","shell.execute_reply":"2024-09-23T22:05:27.189735Z","shell.execute_reply.started":"2024-09-23T22:05:27.183607Z"},"trusted":true},"outputs":[],"source":["# Setup\n","\n","## Libraries\n","import matplotlib.pyplot as plt\n","import seaborn as sns\n","import pandas as pd\n","import numpy as np\n","rd = np.random"]},{"cell_type":"code","execution_count":7,"metadata":{"execution":{"iopub.execute_input":"2024-09-23T22:05:27.194942Z","iopub.status.busy":"2024-09-23T22:05:27.194269Z","iopub.status.idle":"2024-09-23T22:05:27.202310Z","shell.execute_reply":"2024-09-23T22:05:27.201067Z","shell.execute_reply.started":"2024-09-23T22:05:27.194868Z"},"trusted":true},"outputs":[],"source":["# Define Summation Function\n","def sum_function(inputs, weights) -> float:\n"," '''\n"," Sum of the product of the inputs by the weights\n"," + w[i] * x[i]\n"," + w[i+1] * x[i+1] \n"," + ... + w[n] * x[n]\n","\n"," @return float: The Net Input / Pre-Activation result\n"," '''\n"," net_input: float = inputs.dot(weights)\n"," return net_input"]},{"cell_type":"markdown","metadata":{},"source":["\n","## 1. Single Layer perceptron"]},{"cell_type":"code","execution_count":9,"metadata":{},"outputs":[],"source":["# Define the Step Function\n","def step_function(net_input) -> int:\n"," '''\n"," 1, if net_input >= 1\n"," 0, if net_input < 1\n"," \n"," @return int: The Activation result\n"," '''\n"," activation: int = int(net_input >= 1)\n"," return activation"]},{"cell_type":"code","execution_count":10,"metadata":{"execution":{"iopub.execute_input":"2024-09-23T22:05:27.204206Z","iopub.status.busy":"2024-09-23T22:05:27.203839Z","iopub.status.idle":"2024-09-23T22:05:27.214666Z","shell.execute_reply":"2024-09-23T22:05:27.213260Z","shell.execute_reply.started":"2024-09-23T22:05:27.204165Z"},"trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["Summation: -0.09999999999999998\n","Step Func: 0\n"]}],"source":["# Setup the case scenario #1\n","inputs = np.array([-1, 7, 5])\n","weights = np.array([.8, .1, 0])\n","\n","# Run the Perceptron\n","net_input: float = sum_function(inputs, weights)\n","activation: int = step_function(net_input)\n","\n","print(f'Summation: {net_input}\\nStep Func: {activation}')"]},{"cell_type":"code","execution_count":77,"metadata":{},"outputs":[{"data":{"image/png":"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mjVrlg4cONAU9QAA4ML23ZCURLiBezwON5MmTdLatWvVq1cv9e/fX7///e9VUFDQFLUBAOCcb9MmxKpWVo+/ttACefxXMmXKFH388cf67LPPdPPNN2vRokVKSEjQ8OHD9dprrzVFjQCAFozJxPBUgyPwj3/8Y82ePVsHDhzQBx98oKKiImVkZHizNgAAVMIycHioQXtL1dixY4dWrlyp3Nxc2Ww23XHHHd6qCwAASfTcwHMeh5sDBw7oL3/5i15//XUdPnxYN910k5577jndeuutatu2bVPUCABowQg38JTH4aZnz57q37+/Jk2apLvuuktxcXFNURcAAJK+Xy3F1gtwl8fhZv/+/erevXtT1AIAQC303MBTHk8oJtgAAJoTdyeGp9zquWnfvr0OHDigmJgYtWvXThaLpd5jazbVBADAG0rOVEki3MB9boWbBQsWKCIiwvnzxcINAADexI7g8JRb4SY9Pd358/jx45uqFgAAaik9c35fqejWISZXAn/h8Zwbq9WqkydP1mr/5ptvZLVavVIUAAA1bEwohoc8DjeGYdTZXllZqZAQUjUAwLtYLQVPub0U/MUXX5QkWSwWLV261OWGfXa7XVu2bFHPnj29XyEAoMU6Z3fodOX5YSnCDdzldrhZsGCBpPM9N4sXL3YZggoJCVFiYqIWL17s/QoBAC1WzZCUJEWGNWrHILQgbv+lHD58WJI0dOhQvfnmm2rXrl2TFQUAgPT9kFTb0GAFWxu81zNaGI9j8KZNm5qiDgAAamG+DRrC4xh822236bnnnqvVPm/ePHYFBwB4FeEGDeFxuNmyZYtuvvnmWu0jRozQli1bvFIUAAAS4QYN43G4OX36dJ1Lvlu1aiWbzeaVogAAkAg3aBiPw80111yj3NzcWu2rVq3SVVdd5ZWiAACQ2DQTDePxhOKnn35at956qw4dOqSbbrpJkpSXl6eVK1dq9erVXi8QANBy1fTcRLcm3MB9HoebUaNGac2aNZozZ45Wr16t8PBw9e3bV++//77at2/fFDUCAFooNs1EQzTojkgjR47UyJEjJUk2m02vv/66Hn/8ce3cuVN2u92rBQIAWi7m3KAhGnxHpC1btig9PV2dOnXSCy+8oJtuukkfffSRN2sDALRwJYQbNIBH4aagoEBz585V9+7ddccddygyMlKVlZVas2aN5s6dq/79+zeo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ZaR+7NixKioq0syZM1VQUKCkpCStX7++1iTjluIPf/iDJOnGG290aX/11Vc1fvz45i8IjcKcGwAAEFBaziAzAABoEQg3AAAgoBBuAABAQCHcAACAgEK4AQAAAYVwAwAAAgrhBgAABBTCDQAACCiEGwBeN378eFksFs2dO9elfc2aNS4beLojMTFROTk5XjvO28aPH++y+SQA8xFuADSJsLAwPffcc/r222/NLgVAC0O4AdAkUlNTFR8fr+zs7Iset3XrVg0ZMkTh4eFKSEjQI488ovLycknn9/n58ssvNWXKFFksFo96fSwWi5YuXaoxY8aodevW6t69u9555x3n85s3b5bFYtHatWvVp08fhYWF6brrrtPevXudx8yaNUtJSUkur5uTk6PExETn8ytWrNDbb7/trG/z5s1u1wigaRBuADQJq9WqOXPmaOHChfrqq6/qPObQoUP6+c9/rttuu0179uxRbm6utm7dqsmTJ0uS3nzzTV1++eV65plndOLECZ04ccKjGmbPnq0777xTe/bs0c0336x7771Xp06dcjnm//2//6cXXnhBH3/8sTp06KBRo0bp3Llzbr3+448/rjvvvFM///nPnfUNGjTIoxoBeB/hBkCTGTNmjJKSkpSVlVXn89nZ2br33nv12GOPqXv37ho0aJBefPFFvfbaazp79qzat28vq9WqiIgIxcfHKz4+3qP3Hz9+vO6++25169ZNc+bM0enTp7Vjxw6XY7KysjRs2DBdc801WrFihQoLC/XWW2+59fpt27ZVeHi4QkNDnfWFhIR4VCMA7yPcAGhSzz33nFasWKHPPvus1nO7d+/W8uXL1bZtW+cjLS1NDodDhw8fbvR79+nTx/lzmzZtFBkZqZMnT7ocM3DgQOfP7du3V48ePeqsFYD/CDa7AACB7ac//anS0tI0ffp0jR8/3uW506dP68EHH9QjjzxS67wrrrii0e/dqlUrl98tFoscDofb5wcFBckwDJc2d4esAJiHcAOgyc2dO1dJSUnq0aOHS/tPfvIT/fe//1W3bt3qPTckJER2u73Javvoo4+cQerbb7/VgQMH1KtXL0lShw4dVFBQIMMwnJOZd+3a1az1AfAcw1IAmtw111yje++9Vy+++KJL+9SpU7Vt2zZNnjxZu3bt0ueff663337bOaFYOn//mi1btuj48eMqLi72em3PPPOM8vLytHfvXo0fP14xMTHO+9bceOONKioq0rx583To0CEtWrRI7777rsv5iYmJ2rNnj/bv36/i4mJ6dgAfQLgB0CyeeeaZWkNCffr00b/+9S8dOHBAQ4YM0bXXXquZM2eqU6dOLucdOXJEV155pTp06OD1uubOnatHH31UycnJKigo0N///nfnpOBevXrp5Zdf1qJFi9S3b1/t2LFDjz/+uMv5EydOVI8ePdSvXz916NBBH374oddrBOAZi/HDAWUAaAE2b96soUOH6ttvv1V0dLTZ5QDwInpuAABAQCHcAACAgMKwFAAACCj03AAAgIBCuAEAAAGFcAMAAAIK4QYAAAQUwg0AAAgohBsAABBQCDcAACCgEG4AAEBAIdwAAICA8v8BpVd+u5+rBIQAAAAASUVORK5CYII=","text/plain":["
"]},"metadata":{},"output_type":"display_data"}],"source":["# Net Input VS. Activation \n","inputs = []\n","weights = []\n","net_input = []\n","activation = []\n","\n","for i in range(10):\n"," seed1, seed2 = 42 + i, 73 + i\n"," rd.seed(seed1)\n"," inputs.append(rd.randint(-10, 10, 3))\n"," rd.seed(seed2)\n"," weights.append(np.round(rd.rand(3), 4))\n","\n"," # Run the Perceptron\n"," net_input.append(sum_function(inputs[i], weights[i]))\n"," activation.append(step_function(net_input[i]))\n","\n","\n","df1 = pd.DataFrame({\n"," 'Inputs': inputs, \n"," 'Weights': weights, \n"," 'Net Input': net_input, \n"," 'Activation': activation\n","})\n","# display(df1)\n","\n","sns.lineplot(x='Net Input', y='Activation', data=df1)\n","plt.title('Step Function')\n","plt.show()"]},{"cell_type":"markdown","metadata":{},"source":["## 2. Single layer with Training\n","> Now a ANN to predict logic gate (AND, NAND, OR, NOR) outputs based on two inputs"]},{"cell_type":"code","execution_count":78,"metadata":{"execution":{"iopub.execute_input":"2024-09-23T22:05:27.230633Z","iopub.status.busy":"2024-09-23T22:05:27.230175Z","iopub.status.idle":"2024-09-23T22:05:27.240407Z","shell.execute_reply":"2024-09-23T22:05:27.239036Z","shell.execute_reply.started":"2024-09-23T22:05:27.230590Z"},"trusted":true},"outputs":[],"source":["inputs = np.array([\n"," [0,0], # 0\n"," [0,1], # 1\n"," [1,0], # 2\n"," [1,1], # 3\n","])\n","\n","outputs = {\n"," 'AND': np.array([0,0,0,1]),\n"," 'NAND': np.array([1,1,1,0]),\n"," 'OR': np.array([0,1,1,1]),\n"," 'NOR': np.array([1,0,0,0]),\n","}\n","\n","LEARN_RATE = 0.1"]},{"cell_type":"code","execution_count":105,"metadata":{"execution":{"iopub.execute_input":"2024-09-23T22:06:51.503104Z","iopub.status.busy":"2024-09-23T22:06:51.502560Z","iopub.status.idle":"2024-09-23T22:06:51.518048Z","shell.execute_reply":"2024-09-23T22:06:51.516346Z","shell.execute_reply.started":"2024-09-23T22:06:51.503057Z"},"trusted":true},"outputs":[],"source":["def get_output(inputs, weights):\n"," '''\n"," Computes the output of a perceptron using a step function.\n","\n"," Args:\n"," inputs (list of float): The input values to the perceptron.\n"," weights (list of float): The weights associated with the inputs.\n","\n"," Returns:\n"," int: The output of the perceptron after applying the step function.\n"," '''\n"," s = sum_function(inputs, weights)\n"," return step_function(s)\n","\n","def train(gate):\n"," total_error = 1\n"," weights = np.array([0.0, 0.0]) # manually initialized\n"," GATE = outputs[gate]\n"," epoch = 0\n"," \n"," while(total_error != 0): # STOP CONDITION -----------------------------------------------\n"," '''\n"," Checks for stop condition\n"," If != 0, reset total_error and continue training\n"," '''\n"," \n"," # Reset total_error\n"," total_error = 0\n"," \n"," print(f'\\n --- EPOCH {epoch}', '----------------------------', '\\n')\n"," print(f'WEIGHTS: {weights}')\n"," for i in range(len(GATE)): # ERROR UPDATE -------------------------------------------\n"," current_output = get_output(np.asarray(inputs[i]), weights)\n"," current_error = abs(GATE[i] - current_output)\n"," total_error += current_error\n"," \n","\n"," print(f'IN{[i]}: ________ {inputs[i]}')\n"," for j in range(len(weights)): # LEARNING PHASE ----------------------------------\n"," tmp_weight = weights[j]\n"," weights[j] = weights[j] + (LEARN_RATE * inputs[i][j] * current_error)\n","\n"," print(f'\\tOUT[{j}]: {current_output}', end='')\n"," \n"," if weights[j] != tmp_weight:\n"," print(f', Weight[{j}] updated: {weights[j]}')\n"," else:\n"," print()\n"," \n"," print(f'\\tcurrent_error: {current_error}')\n"," \n"," # Update the epoch\n"," epoch += 1\n","\n","\n"," print(f' ---------------------------- Total error: {total_error}')\n"," print('_'*50)\n"," \n"," print()\n"," print(f'>>> Training complete!')\n"," print(f'Final weights: W0={weights[0]} and W1={weights[1]}')"]},{"cell_type":"code","execution_count":106,"metadata":{"collapsed":true,"execution":{"iopub.execute_input":"2024-09-23T22:06:54.010218Z","iopub.status.busy":"2024-09-23T22:06:54.009791Z","iopub.status.idle":"2024-09-23T22:06:54.024485Z","shell.execute_reply":"2024-09-23T22:06:54.023164Z","shell.execute_reply.started":"2024-09-23T22:06:54.010177Z"},"jupyter":{"outputs_hidden":true},"trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["\n"," --- EPOCH 0 ---------------------------- \n","\n","WEIGHTS: [0. 0.]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.1\n","\tOUT[1]: 0, Weight[1] updated: 0.1\n","\tcurrent_error: 1\n"," ---------------------------- Total error 1\n","__________________________________________________\n","\n"," --- EPOCH 1 ---------------------------- \n","\n","WEIGHTS: [0.1 0.1]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.2\n","\tOUT[1]: 0, Weight[1] updated: 0.2\n","\tcurrent_error: 1\n"," ---------------------------- Total error 1\n","__________________________________________________\n","\n"," --- EPOCH 2 ---------------------------- \n","\n","WEIGHTS: [0.2 0.2]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.30000000000000004\n","\tOUT[1]: 0, Weight[1] updated: 0.30000000000000004\n","\tcurrent_error: 1\n"," ---------------------------- Total error 1\n","__________________________________________________\n","\n"," --- EPOCH 3 ---------------------------- \n","\n","WEIGHTS: [0.3 0.3]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.4\n","\tOUT[1]: 0, Weight[1] updated: 0.4\n","\tcurrent_error: 1\n"," ---------------------------- Total error 1\n","__________________________________________________\n","\n"," --- EPOCH 4 ---------------------------- \n","\n","WEIGHTS: [0.4 0.4]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.5\n","\tOUT[1]: 0, Weight[1] updated: 0.5\n","\tcurrent_error: 1\n"," ---------------------------- Total error 1\n","__________________________________________________\n","\n"," --- EPOCH 5 ---------------------------- \n","\n","WEIGHTS: [0.5 0.5]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n"," ---------------------------- Total error 0\n","__________________________________________________\n","\n",">>> Training complete!\n","Final weights: W0=0.5 and W1=0.5\n"]}],"source":["train('AND')"]},{"cell_type":"code","execution_count":9,"metadata":{"collapsed":true,"execution":{"iopub.execute_input":"2024-09-23T22:07:15.312100Z","iopub.status.busy":"2024-09-23T22:07:15.311614Z","iopub.status.idle":"2024-09-23T22:07:15.330061Z","shell.execute_reply":"2024-09-23T22:07:15.328726Z","shell.execute_reply.started":"2024-09-23T22:07:15.312052Z"},"jupyter":{"outputs_hidden":true},"trusted":true},"outputs":[{"name":"stdout","output_type":"stream","text":["WEIGHTS: [0. 0.]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.1\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.1\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.2\n","\tOUT[1]: 0, Weight[1] updated: 0.2\n","\tcurrent_error: 1\n","\n"," --- END OF EPOCH 1 Total error 3 ---------------------------- \n","\n","WEIGHTS: [0.2 0.2]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.30000000000000004\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.30000000000000004\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 0, Weight[0] updated: 0.4\n","\tOUT[1]: 0, Weight[1] updated: 0.4\n","\tcurrent_error: 1\n","\n"," --- END OF EPOCH 2 Total error 3 ---------------------------- \n","\n","WEIGHTS: [0.4 0.4]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.5\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.5\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 3 Total error 2 ---------------------------- \n","\n","WEIGHTS: [0.5 0.5]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.6\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.6\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 4 Total error 2 ---------------------------- \n","\n","WEIGHTS: [0.6 0.6]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.7\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.7\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 5 Total error 2 ---------------------------- \n","\n","WEIGHTS: [0.7 0.7]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.7999999999999999\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.7999999999999999\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 6 Total error 2 ---------------------------- \n","\n","WEIGHTS: [0.8 0.8]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.8999999999999999\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.8999999999999999\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 7 Total error 2 ---------------------------- \n","\n","WEIGHTS: [0.9 0.9]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 0.9999999999999999\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 0.9999999999999999\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 8 Total error 2 ---------------------------- \n","\n","WEIGHTS: [1. 1.]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 0\n","\tOUT[1]: 0, Weight[1] updated: 1.0999999999999999\n","\tcurrent_error: 1\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 0, Weight[0] updated: 1.0999999999999999\n","\tOUT[1]: 0\n","\tcurrent_error: 1\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 9 Total error 2 ---------------------------- \n","\n","WEIGHTS: [1.1 1.1]\n","IN[0]: ________ [0 0]\n","\tOUT[0]: 0\n","\tOUT[1]: 0\n","\tcurrent_error: 0\n","IN[1]: ________ [0 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","IN[2]: ________ [1 0]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","IN[3]: ________ [1 1]\n","\tOUT[0]: 1\n","\tOUT[1]: 1\n","\tcurrent_error: 0\n","\n"," --- END OF EPOCH 10 Total error 0 ---------------------------- \n","\n",">>> Training complete!\n","Final weights: W0=1.0999999999999999 and W1=1.0999999999999999\n"]}],"source":["train('OR')"]},{"cell_type":"code","execution_count":12,"metadata":{},"outputs":[],"source":["# WONT STOP BECAUSE OF STOP CONDITION\n","# train('NAND') - Keeps increasing weights\n","# train('NOR') - Never updates weights"]},{"cell_type":"markdown","metadata":{},"source":["## 3. Multi-layer perceptron"]},{"cell_type":"code","execution_count":13,"metadata":{},"outputs":[],"source":["# TODO"]}],"metadata":{"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":30761,"isGpuEnabled":false,"isInternetEnabled":true,"language":"python","sourceType":"notebook"},"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.4"}},"nbformat":4,"nbformat_minor":4} diff --git a/step_function_plot.png b/step_function_plot.png new file mode 100644 index 0000000000000000000000000000000000000000..e46ebe07d0ec14981bbe8d2df1eb078b3808b99d GIT binary patch literal 18326 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⋙uP=~_ZmObRYnDWCh+1tETsvI09 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