{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Training a Perceptron\n",
    "\n",
    "In this notebook, we will construct simple perceptron models. We'll start by implementing a perceptron model, and seeing how it behaves. We'll then outline the steps to train a perceptron to classify a point as above or below a line.\n",
    "\n",
    "This discussion follows the excellent example and discussion at [The Nature of Code](https://natureofcode.com/book/chapter-10-neural-networks/). Please see that reference for additional details, and a more sophisticated coding strategy (using Classes in Python)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Preliminaries\n",
    "Text preceded by a `#` indicates a 'comment'.  I will use comments to explain what we're doing and to ask you questions.  Also, comments are useful in your own code to note what you've done (so it makes sense when you return to the code in the future).  It's a good habit to *always* comment your code.  I'll try to set a good example, but won't always . . . \n",
    "\n",
    "Before beginning, let's load in the Python packages we'll need:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pylab import *\n",
    "%matplotlib inline\n",
    "rcParams['figure.figsize']=(12,3)                # Change the default figure size"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Part 1:   A simple perceptron model.\n",
    "\n",
    "Let's examine a simple perceptron that accepts inputs, processes those inputs, and returns an output. To do so, please consider this function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def my_perceptron(input1, input2, w1, w2, theta):\n",
    "    # Define the activity of the perceptron, x.\n",
    "    x = input1*w1 + input2*w2 + theta\n",
    "    \n",
    "    # Apply a binary threshold,\n",
    "    if x > 0:\n",
    "        return 1\n",
    "    else:\n",
    "        return 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"question\">\n",
    "\n",
    "**Q:** How many inputs does the function take?  How many outputs does it return?\n",
    "\n",
    "**Q:** Looking at this code, could you sketch a model of this perceptron?\n",
    "\n",
    "**Q:** Apply this function to different sets of inputs. Consider,\n",
    "\n",
    "  `input1 = 1, input2 = 0, w1 = 0.5, w2 = -0.5, theta = 0`\n",
    "\n",
    "  and\n",
    "\n",
    "  `input1 = 1, input2 = 0, w1 = 0.5, w2 = -0.5, theta = -1`\n",
    "\n",
    "  What do you find?\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##   Part 2.  Build a perceptron classifier.\n",
    "\n",
    "We'd like to create a method to train a perceptron to classify a point (x,y) as above or below a line. Let's implement this training procedure.\n",
    "\n",
    "###  Step 1. Provide perceptron with inputs and known answer. \n",
    "\n",
    "  First, let's make a function that computes a line, and determines if \n",
    "  a given `y` value is above or below the line. We'll use this function\n",
    "  to return the correct (\"known\") answer. Having known answers is\n",
    "  important for training the perceptron. We'll use the known answers to\n",
    "  tell the when it's right or wrong (i.e., when the perceptron makes an\n",
    "  error).\n",
    "\n",
    "  Let's define the function (`known_answer`) should take four inputs:\n",
    "\n",
    "  - `slope`\n",
    "  - `intercept`\n",
    "  - `x`\n",
    "  - `y`\n",
    "\n",
    "where the (x,y) value is a point we choose on the plane. The function\n",
    "  should return one output:\n",
    "\n",
    " - `desired_output`\n",
    "\n",
    "where,\n",
    "\n",
    "`desired_output = 1`, if the `y` value (the last input) is above the line,\n",
    "\n",
    "`desired_putput = 0`, if the `y` value (the last input) is below the line.\n",
    "\n",
    "Consider the function below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def known_answer(slope, intercept, x, y):\n",
    "\n",
    "  yline = slope*x + intercept  # Compute y-value on the line.\n",
    "  if y > yline:                # If the input y value is above the line,\n",
    "      return 1                 # ... indicate this with output = 1;\n",
    "  else:                        # Otherwise, the input y is below the line,\n",
    "      return 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"question\">\n",
    "\n",
    "**Q:** Consider the (x,y) point,\n",
    "\n",
    "`x,y = 0.7,3` \n",
    "\n",
    "and the line with slope and intercept, \n",
    "\n",
    "`slope = 2` \n",
    "`intercept = 1`\n",
    "\n",
    "Is the (x,y) point above or below the line?\n",
    "\n",
    "**A:** To answer this, let's ask our function,\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "x,y = 0.7,3\n",
    "slope = 2\n",
    "intercept = 1\n",
    "correct_answer = known_answer(slope, intercept, x, y)\n",
    "print(correct_answer)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"question\">\n",
    "\n",
    "**A (Continued):** We find a `correct_answer` of 1.\n",
    "\n",
    "So, the point `(x,y)=(0.7,3)` is above the line with slope 2 and intercept 1.\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Step 2: Ask perceptron to guess an answer.\n",
    "\n",
    " Our next step is to compare our desired output (computed in Step 1) to\n",
    " the output guessed by the perceptron. To do so, we'll need to compute\n",
    " the *feedforward* solution for the perceptron (i.e., given the inputs\n",
    " and bias, determine the perceptron output). Let's do so,"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def feedforward(x, y, wx, wy, wb):\n",
    "\n",
    "  # Fix the bias.\n",
    "  bias = 1\n",
    "\n",
    "  # Define the activity of the neuron, activity.\n",
    "  activity = x*wx + y*wy + wb*bias\n",
    "  \n",
    "  # Apply the binary threshold,\n",
    "  if activity > 0:\n",
    "      return 1\n",
    "  else:\n",
    "      return 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This function takes five inputs:\n",
    "\n",
    " - `x`  = the x coordinate of the point we choose in the plane.\n",
    " - `y`  = the y coordinate of the point we choose in the plane.\n",
    " - `wx` = the weight of x input.\n",
    " - `wy` = the weight of y input.\n",
    " - `wb` = the weight of the bias.\n",
    "\n",
    "And this function returns one output:\n",
    " \n",
    " - the perceptron's guess, is the point above (=1) or below (=0) the line."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"question\">\n",
    "\n",
    "**Q:**  Again consider the (x,y) point, \n",
    "\n",
    "`x,y = 0.7,3` \n",
    "\n",
    "and set initial values for the perceptron weights. Let's just set these all to 0.5;  our goal in the rest of this notebook will be to train the perceptron by adjusting these weights.  But for now,\n",
    "\n",
    "`wx,wy,wb = 0.5` \n",
    "\n",
    "Then, ask the perceptron for it's guess for it's guess, is the point above or below the line?\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "x,y = 0.7, 3\n",
    "wx,wy,wb = 3 * [0.5]\n",
    "perceptron_guess = feedforward(x, y, wx, wy, wb)\n",
    "print(perceptron_guess)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"question\">\n",
    "\n",
    "**A (Continued):** We find a `peceptron_guess` of 1.\n",
    "\n",
    "So, the perceptron guesses that the point `(x,y)=(0.7,3)` is above the line.\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Step 3: Compute the error.\n",
    "\n",
    " We've now answered the question \"*Is the (x,y) point above the line?*\" in \n",
    " two ways:\n",
    " \n",
    " - the known answer, and \n",
    " - the perceptron's guess.\n",
    "\n",
    "Let's compute the error as the difference between these two answers:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n"
     ]
    }
   ],
   "source": [
    "error = correct_answer - perceptron_guess\n",
    "print(error)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"question\">\n",
    "\n",
    "**Q:**  What do you find for the `error`? Does it make sense?\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Step 4: Adjust all weights according to the error.\n",
    "\n",
    " To update the weights, we'll use the expression,\n",
    "\n",
    " `new weight = weight + error * input * learning constant`\n",
    "\n",
    " We need to compute this for each weight `(wx, wy, wb)`.\n",
    "\n",
    " First, let's set the learning constant,"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "learning_constant = 0.01"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then, we can compute the new weights,"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "wx = wx + error*x   *learning_constant\n",
    "wy = wy + error*y   *learning_constant\n",
    "wb = wb + error*1   *learning_constant"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice that, in the update to `wb` we use the fact that the bias equals 1."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"question\">\n",
    "\n",
    "**Q:**  What do you find for the new weights? Does it make sense?\n",
    "\n",
    "</div>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Step 5: Return to Step 1 and repeat ... \n",
    " We could try to compute these repetitions by hand, for example by repeating\n",
    " the cells above. To do so, we'd choose a new point in the (x,y) plane,\n",
    " determine whether it's above the line 2x+1, ask the perceptron to guess\n",
    " whether it's above the line, then use the error to update the\n",
    " perceptron's weights. \n",
    "\n",
    " But we want to evaluate this procedure 2000 times. Doing so by\n",
    " hand would be a total pain, and highly error prone. Instead, let's\n",
    " ask the computer to do the boring work of multiple repetitions. To do so,\n",
    " let's collect the code above, and examine 2000 (x,y) points chosen\n",
    " randomly in the plane. We'll wrap our code above inside a for-loop to\n",
    " make this efficient,"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x216 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "slope     = 2;                      # Define the line with slope, \n",
    "intercept = 1;                      # ... and intercept.\n",
    "\n",
    "wx,wy,wz = 3*[0.5];                 # Choose initial values for the perceptron's weights\n",
    "\n",
    "learning_constant = 0.01;           # And, set the learning constant.\n",
    "\n",
    "estimated_slope = zeros(2000)       # Variables to hold the perceptron estimates.\n",
    "estimated_intercept = zeros(2000)\n",
    "\n",
    "for k in arange(2000):              # For 2000 iteractions,\n",
    "    x = randn(1);                   # Choose a random (x,y) point in the plane\n",
    "    y = randn(1);\n",
    "                                    # Step 1: Calculate known answer.\n",
    "    correct_answer = known_answer(slope, intercept, x, y);\n",
    "    \n",
    "                                    # Step 2. Ask perceptron to guess an answer.\n",
    "    perceptron_guess = feedforward(x, y, wx, wy, wb);\n",
    "    \n",
    "                                    # Step 3. Compute the error.\n",
    "    error = correct_answer - perceptron_guess;\n",
    "    \n",
    "                                    # Step 4. Adjust weights according to error.\n",
    "    wx = wx + error*x*learning_constant;\n",
    "    wy = wy + error*y*learning_constant;\n",
    "    wb = wb + error*1*learning_constant;\n",
    "     \n",
    "    estimated_slope[k] = -wx/wy;               # Compute estimated slope from perceptron.\n",
    "    estimated_intercept[k] = -wb/wy;           # Compute estimated intercept from perceptron.\n",
    "\n",
    "# Display the results! ------------------------------------------------------------------------\n",
    "x_range = linspace(-2,2,100);                  # For a range of x-values,\n",
    "fig, ax = subplots()\n",
    "ax.plot(x_range, slope*x_range+intercept, 'k') # ... plot the true line,\n",
    "\n",
    "for k in range(1,2000,100):                    # ... and plot some intermediate perceptron guess\n",
    "    ax.plot(x_range, estimated_slope[k]*x_range+estimated_intercept[k], 'r')\n",
    "                                               # ... and plot the last perceptron guess\n",
    "ax.plot(x_range, estimated_slope[-1]*x_range+estimated_intercept[-1], 'b')\n",
    "xlabel('x')\n",
    "ylabel('y')\n",
    "title('Known answer (black), Perceptron final guess (blue)');"
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "formats": "ipynb,md:myst"
  },
  "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.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}