<jupyter_start><jupyter_text>Here's a simple version of a perceptron using Python and NumPy. It will take two inputs and learn to act like the logical OR function.<jupyter_code>from random import choice 
from numpy import array, dot, random
unit_step = lambda x: 0 if x < 0 else 1<jupyter_output><empty_output><jupyter_text>The first two entries of the NumPy array in each tuple are the two input values. The second element of the tuple is the expected result. And the third entry of the array is a "dummy" input (also called the bias) which is needed to move the threshold (also known as the decision boundary) up or down as needed by the step function. Its value is always 1, so that its influence on the result can be controlled by its weight.<jupyter_code>training_data = [ 
    (array([0,0,1]), 0), 
    (array([0,1,1]), 1), 
    (array([1,0,1]), 1), 
    (array([1,1,1]), 1), 
]<jupyter_output><empty_output><jupyter_text>As you can see, this training sequence maps exactly to the definition of the OR function:<jupyter_code>from IPython.display import Image
Image("fig1.png")
# Choose 3 random numbers between 0 and 1 as the initial weights:
w = random.rand(3) 
# Used to store the error values so that they can be plotted later on.
errors = [] 
# Controls the learning rate.
eta = 0.2 
# Specifies the number of learning iterations.
n = 100<jupyter_output><empty_output><jupyter_text>In order to find the ideal values for the weights w, we try to reduce the error magnitude to zero. In this simple case n = 100 iterations are enough; for a bigger and possibly "noisier" set of input data much larger numbers should be used. First we get a random input set from the training data. Then we calculate the dot product (sometimes also called scalar product or inner product) of the input and weight vectors. This is our (scalar) result, which we can compare to the expected value. If the expected value is bigger, we need to increase the weights, if it's smaller, we need to decrease them. This correction factor is calculated in the last line, where the error is multiplied with the learning rate (eta) and the input vector (x). It is then added to the weights vector, in order to improve the results in the next iteration.<jupyter_code>for i in range(n): 
    x, expected = choice(training_data) 
    result = dot(w, x) 
    error = expected - unit_step(result) 
    errors.append(error) 
    w += eta * error * x
for x, _ in training_data: 
    result = dot(x, w) 
    print("{}: {} -> {}".format(x[:2], result, 
                                unit_step(result)))
from pylab import plot, ylim 
%matplotlib inline
ylim([-1,1]) 
plot(errors)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.0788490284005979, 'fraction_numerical': 0.013452914798206279, 'mean_word_length': 4.079696394686907, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 18, '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}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '317403', 'license': 'MIT', 'n_tokens_mistral': 793, 'n_tokens_neox': 750, 'n_words': 381, 'path': 'Perceptron_Eg2.ipynb', 'repo_name': 'Not-A-Builder/Basics-of-AI', 'size': '2676'}