<jupyter_start><jupyter_text>CCNSS 2018 Module 4: High dimensional representations and neural dynamics Tutorial 4: Perceptron learning[source](https://colab.research.google.com/drive/1V4PFwp0qYizOEjh1n68ZYh7CxJPe_7PQ) *Please execute the cell bellow in order to initialize the notebook environment*<jupyter_code>import matplotlib.pyplot as plt    # import matplotlib
import numpy as np                 # import numpy
import math                        # import basic math functions
import random                      # import basic random number generator functions

fig_w, fig_h = (6, 4)
plt.rcParams.update({'figure.figsize': (fig_w, fig_h)})<jupyter_output><empty_output><jupyter_text>ObjectivesIn this notebook we will implement the perceptron learning algorithm and introduce the concept of gradient descent for extensions to multiple layers.   BackgroundThe perceptron belongs to the category of supervised learning algorithms, single-layer binary linear classifiers to be more specific. A typical task that can be accomplished by the perceptron is to to predict to which of two possible categories a certain data point belongs based on a set of input variables.The perceptron can be thought of an artificial neuron that receives an input pattern from N other neurons and converting that input pattern to a single output value (e.g., a single binary value.) The most important elements of the perceptron are thus: 1. The input pattern, which is represented by $\vec{x^{\mu}}\in\mathbb{R}^N$ (N is the number of connections and $\mu$ indexes the pattern) 2. The connection weights from the N inputs, represented by a  a vector of real-valued weights $\vec{J}\in\mathbb{R}^N$, 3. An output value that depends on the input pattern and weights as $$g(\vec{x}) = \begin{cases}                1 & \text{if }\vec{J} \cdot \vec{x}+b> 0\,,\\                0 & \text{otherwise};             \end{cases}$$where $g$ is a step function, $\vec{J} \cdot \vec{x}$ is  $\sum_{i=1}^N J_i x_i$ and b is a threshold. The learning algorithm refers to the updating of the weights $\vec{J}$ based on target ouput values $y^{\mu}$ and actual output values $y$.We update the weights and threshold using the perceptron rule:$$\begin{align*}J_i & = J_i + \alpha (y - \hat{y}) x_{i} \,,\  i=1,\ldots, N\,;\\b & = b + \alpha (y - \hat{y})\,\end{align*}$$where $$\hat{y} = g\left(\vec{J}\cdot\vec{x} + b\right).$$and $\alpha\in\left(0,1\right]$ is the learning rate. In this notebook we will illustrate how to train a simple network and introduce the concept of linear separability. In exercises 1 and 2 we will train a simple perceptron to represent the AND function, which takes two binary input values (1 and 0) and ouputs a 1 only if both input values are 1.  **EXERCISE 1**Given a perceptron with two inputs (n =2), there are $2^2$ possible patterns: (0,0), (0,1), (1,0), (1,1). - For the AND function: list the possible patterns (inputs) and plot the inputs in the x-y plane, so that both outputs are distinguished (in red and blue, for example)- plot the line that separates the inputs that map onto "1" from inputs that map onto "0" - find values for $\vec{J}$ and $b$ by inspection that solves the AND problem (there is more than one solution!)  **EXERCISE 2** We will now, instead of finding weights by inspection, assume that the weights are random and use the learning algorithm to learn the weights. - using the function np.random.random(), initialize the vector weights randomly on the interval [0,1]<jupyter_code>#insert code here 
np.random.seed(1)
J_ini = np.random.random(2)
b_ini = 0<jupyter_output><empty_output><jupyter_text>Expected output ```[0.417022   0.72032449]``` We will establish the training algorithm in a few steps:  - Define the output target values and the learning rate. Use $\alpha = 0.1$ - First, build a function "g_step()" with the properties described in the background above, i..e, a step function. - Define a function error () that calculates the difference between the target (desired output) and the real output (dependent on the weights), and then is multiplied by $\alpha$.<jupyter_code>## insert code here

def g(arguments):
   '''
   arguments: these are the inputs to your activation function.
   the function retunrs either a 1 or a zero depending on the arguments
   '''
def get_error ():
    return error

  
J_ini<jupyter_output><empty_output><jupyter_text>- define a function(s) percep_train () that takes as inputs the initial weights $\vec{J}$ and initial threshold $b$, and calls the function error to output new weights via the update rule. Hint: You may define a list of input-output pairs for the function AND and use that as an input. There are many ways of doing this.<jupyter_code>#insert code here
def percep_train(weights_ini,b_ini,inputs):
  '''
  weights_ini: This is a vector of your (random) initial weights
  b_ini: This is your bias or threshold, it was initialized at 0
  inputs: This is a set of your input-output pairs that you will use for training.
  The function returns new weights and b based on the update rule (perceptron learning rule)'''<jupyter_output><empty_output><jupyter_text>- Train your perceptron for 20, 60, and 150 steps. Using your learned weights and bias b, plot the line that separates the points (the line that defines the AND function). Hint: Loop over your perceptron training algorithm N times.   Expected output ![](https://github.com/ccnss/ccnss2018_students/raw/master/module4/4_perceptron/figures/Mod4T4E2.png) - Do the same training for the function OR. There are many solutions, but to compare to expected output, initialize your random seed as before.   Expected output ![](https://github.com/ccnss/ccnss2018_students/raw/master/module4/4_perceptron/figures/Mod4T4E2b.png) **EXERCISE 3** (the XOR problem)The XOR function is a binary function whose output is "1" only if exactly one of the inputs is 1, and the output is "0" otherwise.- plot the possible input patterns for the XOR function (with a different color for different ouputs). Can you find a line that can separate the inputs? (try inspection and training) - try training a network to achieve XOR. How would you solve the problem? (Try pen and paper. Hint: How many lines would you need to separate the input patterns? What does this imply for the number of layers required?)  Exercise 4 In this exercise we will perform linear regression using the perceptron. The data is composed of 8 points in two dimensional space. To perform linear regression, you have to change (or extend) your activation function g so that the output is linear, i.e., $g(x) = x$- First, plot the data.<jupyter_code>x_1 = np.array([0,2.7])
x_2 = np.array([2,3.6])
x_3 = np.array([3.2,5])
x_4 = np.array([2.3,4.5])
x_5 = np.array([3.2,4])
x_6 = np.array([0.3,3.3])
x_7 = np.array([-0.4, 2.3])
x_8 = np.array([1.3, 4.5])

#Insert code here<jupyter_output><empty_output><jupyter_text>- Train your perceptron to find the weights and b for linear regression. Plot the line using your new weights and b. Optional: Check your results with the built in function np.linalg.lstsq() (least squares)<jupyter_code>#insert code here
np.random.seed(5)
J_ini = np.random.random(1)
b_ini = 0<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09133683919180736, 'fraction_numerical': 0.019651259341267643, 'mean_word_length': 4.310066127847171, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 26, 'https://': 3, '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': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '592556', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 2160, 'n_tokens_neox': 2040, 'n_words': 973, 'path': 'module4/4_perceptron/4_perceptron_learning.ipynb', 'repo_name': 'ruyuanzhang/ccnss2018_students', 'size': '7226'}