{ "cells": [ { "cell_type": "markdown", "id": "controversial-austin", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "# The Simple Perceptron" ] }, { "cell_type": "markdown", "id": "referenced-platinum", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "The simple perceptron is a 1-layer feedforward network. It has one input layer, one output layer, and one connection matrix in between. Let the values of the input units be denoted by $S_i$ for $i = 1, \\cdots, N$, and that for the output units be $R_j$ for $j = 1, \\cdots, K$. Note that the number of input units, or the size of the input layer, does not have to be equal to that of the output, i.e., $N \\neq K$, so the connection matrix $W_{ji}$ does not need to be square. For given values of the input, the output of the network is given by:\n", "\\begin{equation}\n", "R_j = g \\Big( \\sum_i W_{ji} S_i \\Big)\n", "\\end{equation}\n", "where $g(\\cdot)$ is the activation function. It can be a threshold function like $g(x) = \\operatorname{sgn}(x)$, or simply a linear function $g(x) = x$, or a nonlinear function such as $g(x) = \\tanh(x)$." ] }, { "cell_type": "markdown", "id": "031d2f53-6fad-4942-bc0c-3bd2ff663a94", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "source": [ "The goal of a perceptron network is to store input-output pairs. Let us label such pairs of patterns by an index $\\mu = 1, \\cdots, M$. Let an input pattern be $\\xi^\\mu$, which is an $N$-dimensional vector with components $\\xi^\\mu_i$; let the corresponding output pattern be $\\zeta^\\mu$, which is an $K$-dimensional vector with components $\\zeta^\\mu_j$. We would like to train the network so that, when presented $\\xi^\\mu$ as the input, the network will output $\\zeta^\\mu$. That is, we would like to have:\n", "\\begin{equation}\n", "\\zeta^\\mu_j = g \\Big( \\sum_i W_{ji} \\xi^\\mu_i \\Big) \\quad \\textsf{for all $\\mu$}\n", "\\end{equation}\n", "The challenge is to find a connection matrix $W_{ji}$ that satisfies these equations." ] }, { "cell_type": "markdown", "id": "conscious-executive", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "It turns out that there is a simple expression for $W_{ji}$ when $M \\leq N$:\n", "\\begin{equation}\n", "W_{ji} = \\frac{1}{N} \\sum_{\\mu\\nu} \\zeta^\\mu_j \\big( Q^{-1} \\big)_{\\mu\\nu} \\, \\xi^\\nu_i\n", "\\quad \\textsf{where} \\quad\n", "Q^{\\mu\\nu} = \\frac{1}{N} \\sum_i \\xi^\\mu_i \\xi^\\nu_i\n", "\\end{equation}\n", "The matrix $Q^{\\mu\\nu}$ can be viewed as the cross-correlation between the input patterns. If the patterns are largely uncorrelated, like when they are chosen at random, then $\\mathbf{Q} \\approx \\mathbf{I}$, the identity matrix, so the connection matrix simplifies to:\n", "\\begin{equation}\n", "W_{ji} \\approx \\frac{1}{N} \\sum_\\mu \\zeta^\\mu_j \\xi^\\mu_i\n", "\\end{equation}" ] }, { "cell_type": "markdown", "id": "10767a35-9b21-4696-94c8-c6bebd2ce7c8", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "source": [ "This expression may be reminiscent of the Hopfield model, except that here the input and output patterns are not the same. Another difference between the perceptron and the Hopfield network is that, in the Hopfield network, we used discrete units $S_i = \\pm 1$ (recall that the images we stored were black and white). We may still do that for the perceptron, by using the threshold activation function $g(x) = \\operatorname{sgn}(x)$. However, we can also use continuous-valued units for the perceptron (therefore we can now use gray-scale images, as shown below). For simplicity we can use the linear activation function $g(x) = x$. The connection matrix above works for both the threshold and linear units, as long as the number of input-output pairs to be stored is less than $N$." ] }, { "cell_type": "markdown", "id": "broad-portrait", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "Let us implement the perceptron network as follows. We will first define a base class for a general 1-layer feedforward network." ] }, { "cell_type": "code", "execution_count": 1, "id": "synthetic-humanity", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": 2, "id": "blocked-adobe", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "outputs": [], "source": [ "class FeedforwardNetwork:\n", " \"\"\"\n", " base class of 1-layer feedforward network.\n", " \"\"\"\n", "\n", " def __init__(self, Ni, No, input=None, connection=None, activation='threshold'):\n", " \"\"\"\n", " declare internal variables.\n", " inputs:\n", " Ni: int, number of input nodes.\n", " No: int, number of output nodes.\n", " input: 1-d array, input nodes (can be pointer to array).\n", " connection: 2-d array, connection matrix between input and output nodes.\n", " activation: 'threshold'|'linear'|other, activation function, can be user-supplied.\n", " \"\"\"\n", " self.Ni = int(Ni) # number of input nodes\n", " self.No = int(No) # number of output nodes\n", " self.input = np.zeros(self.Ni) # input nodes\n", " self.output = np.zeros(self.No) # output nodes\n", " self.connection = np.zeros((self.No, self.Ni)) # connection matrix\n", " self.set_network(input, connection) # set input and connections if given\n", " self.set_units(activation) # set activation function\n", "\n", " def set_network(self, input=None, connection=None):\n", " \"\"\"\n", " set input and connection of the network.\n", " inputs:\n", " input: 1-d array, state of input nodes (can be pointer to array).\n", " connection: 2-d array, connection matrix.\n", " \"\"\"\n", " if input is not None:\n", " self.input = input\n", " if connection is not None:\n", " self.connection = np.asarray(connection, dtype=float)\n", " \n", " def set_units(self, activation):\n", " \"\"\"\n", " set activation function.\n", " inputs:\n", " activation: 'threshold'|'linear'|other, activation function, can be user-supplied.\n", " \"\"\"\n", " if activation == 'threshold': # using discrete units +-1\n", " self.activation = np.sign # `np.sign` without the brackes is a function object\n", " elif activation == 'linear': # using linear units\n", " self.activation = lambda x: x # lambda function that simply returns the input\n", " else:\n", " self.activation = activation # `activation` can be a user-defined function handle\n", " \n", " def run(self, input=None):\n", " \"\"\"\n", " run network to generate output, using input if given.\n", " inputs:\n", " input: 1-d array, state of input nodes.\n", " outputs:\n", " output: 1-d array, state of output nodes.\n", " \"\"\"\n", " if input is not None:\n", " self.input[:] = input\n", " self.output[:] = self.activation(np.dot(self.connection, self.input))\n", " return self.output" ] }, { "cell_type": "markdown", "id": "31f7e005-2bbc-4ff6-9428-2623ab441653", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "## Prescribing weights" ] }, { "cell_type": "markdown", "id": "norman-metadata", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "We can define a derived class to implement the simple perceptron network. We will define a function `store()` that calculates the connection matrix for storing the input-output pairs. " ] }, { "cell_type": "code", "execution_count": 3, "id": "native-newton", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "outputs": [], "source": [ "class SimplePerceptron(FeedforwardNetwork):\n", " \"\"\"\n", " simple perceptron as a 1-layer feedforward network.\n", " \"\"\"\n", " \n", " def store(self, inputs, outputs):\n", " \"\"\"\n", " store input/output pairs by calculating the connection matrix.\n", " inputs:\n", " inputs: 2-d array, each row is an input pattern.\n", " outputs: 2-d array, each row is an output pattern.\n", " \"\"\"\n", " inputs = np.asarray(inputs)\n", " outputs = np.asarray(outputs)\n", " corr = np.dot(inputs, inputs.T) / self.Ni\n", " dual = np.linalg.solve(corr, inputs)\n", " self.connection = np.dot(outputs.T, dual) / self.Ni" ] }, { "cell_type": "markdown", "id": "loaded-characterization", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "Let us create a network to \"remember\" the names of our guests. The input to the network will be the images we used before for the Hopfield network, except that now we can use the gray-scale versions if we use linear units in the network." ] }, { "cell_type": "code", "execution_count": 4, "id": "36507e12-b1ab-44ca-98e4-f898b19e5243", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "outputs": [], "source": [ "def grayscale(img):\n", " \"\"\"\n", " convert RGB image (3d-array) to grayscale (2d-array).\n", " input:\n", " img: 3d array, last axis is RGB channel; if 2d array, then assume it is already grayscale.\n", " output:\n", " gray: 2d array, grayscale image.\n", " \"\"\"\n", " if np.ndim(img) == 3 and np.shape(img)[2] >= 3:\n", " gray = np.sum(img[:,:,:3] * np.array([0.2989, 0.5870, 0.1140]), axis=2)\n", " else:\n", " gray = img\n", " # gray = gray / np.amax(gray)\n", " return gray\n", "\n", "def blackwhite(gray):\n", " \"\"\"\n", " convert grayscale image to black & white.\n", " input:\n", " gray: 2d array, grayscale image.\n", " output:\n", " bw: 2d array, black & white image.\n", " \"\"\"\n", " med = np.median(gray)\n", " bw = (gray > med).astype(float)\n", " return bw\n", "\n", "def img2vec(img):\n", " \"\"\"\n", " convert a 2D black & white image to a 1D vector of +/-1.\n", " input:\n", " img: 2d-array of binary numbers (0 for black and 1 for white);\n", " some grayscale images have an extra dimension which is redundant and will be removed.\n", " output:\n", " vec: 1d-array of +/-1 values.\n", " \"\"\"\n", " vec = np.reshape(img, -1) # flatten array\n", " vec = 1-2*vec # convert from 0/1 to +/-1\n", " return vec\n", "\n", "def vec2img(vec, shape):\n", " \"\"\"\n", " convert a 1D vector of +/-1 to a 2D black & white image.\n", " input:\n", " vec: 1d-array of +/-1 values.\n", " shape: 2-tuple, shape of the 2d-array.\n", " output:\n", " img: 2d-array of binary numbers (0 for black and 1 for white).\n", " \"\"\"\n", " vec = (1-vec)/2\n", " img = np.reshape(vec, shape)\n", " return img" ] }, { "cell_type": "code", "execution_count": 5, "id": "naughty-athletics", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "img1 = plt.imread('source/AlbertGator_grayscale.png')\n", "img2 = plt.imread('source/AlbertEinstein_grayscale.png')\n", "img1 = grayscale(img1) # make sure the image is grayscale\n", "img_all = [img1, img2]\n", "M = len(img_all)\n", "\n", "fig, ax = plt.subplots(1,M, figsize=(2*M,2))\n", "for m in range(M):\n", " ax[m].imshow(img_all[m], cmap='Greys_r') # pixel values: 0 = black, 1 = white\n", " ax[m].axis('off')\n", " ax[m].set_title(f'input{m+1}')\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "accredited-passion", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "For the output, we will make some namecards for the guests. These are also gray-scale images, but of a different size from the input images. This is to remind us that the input and output layers do not have to be the same size." ] }, { "cell_type": "code", "execution_count": 6, "id": "behavioral-politics", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "name1 = plt.imread('source/Gator_grayscale.png')\n", "name2 = plt.imread('source/Einstein_grayscale.png')\n", "name1 = grayscale(name1) # make sure the image is grayscale\n", "name_all = [name1, name2]\n", "\n", "fig, ax = plt.subplots(1,M, figsize=(2*M,2))\n", "for m in range(M):\n", " ax[m].imshow(name_all[m], vmin=0, vmax=1, cmap='Greys_r') # pixel values: 0 = black, 1 = white\n", " ax[m].axis('off')\n", " ax[m].set_title(f'output{m+1}')\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "improved-browser", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "We have to convert both input and output images to 1-d arrays. Then we use the network to store these pairs of patterns." ] }, { "cell_type": "code", "execution_count": 7, "id": "bacterial-panama", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "outputs": [], "source": [ "shape_in = img1.shape # shape of input image\n", "Ni = np.prod(shape_in) # size of input pattern\n", "inputs = []\n", "for img in img_all:\n", " inp = img2vec(img)\n", " inputs.append(inp)\n", "\n", "shape_out = name1.shape # shape of output image\n", "No = np.prod(shape_out) # size of output pattern\n", "outputs = []\n", "for name in name_all:\n", " out = img2vec(name)\n", " outputs.append(out)" ] }, { "cell_type": "code", "execution_count": 8, "id": "121009b1-1910-414d-8a17-8e5e94455773", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "outputs": [], "source": [ "net = SimplePerceptron(Ni, No, activation='linear') # create perceptron network\n", "net.store(inputs, outputs) # store pairs of patterns" ] }, { "cell_type": "markdown", "id": "returning-prefix", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "Let us test the network by making it \"recall\" the name of our first guest." ] }, { "cell_type": "code", "execution_count": 9, "id": "overall-preview", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "inp = img2vec(img1) # first image as input pattern\n", "out = net.run(inp) # generate output\n", "name = vec2img(out, shape_out) # convert output back to image\n", "\n", "fig, ax = plt.subplots(1, 2, figsize=(4,2))\n", "ax[0].imshow(img1, cmap='Greys_r')\n", "ax[0].axis('off')\n", "ax[0].set_title('input')\n", "ax[1].imshow(name, vmin=0, vmax=1, cmap='Greys_r')\n", "ax[1].axis('off')\n", "ax[1].set_title('output')\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "billion-alabama", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "## Learning" ] }, { "cell_type": "markdown", "id": "dedicated-dover", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "The above expression for the connection matrix works precisely for linear units. Such a simple perceptron can store up to $N$ pairs of input and output patterns (recall that $N$ is the dimension of the input vector). The reason is that if we have more than $N$ input vectors, they simply cannot be independent of each other. However, it turns out that, if we use threshold units with discrete values, the storage capacity can go up to $2N$. The problem is, the above expression for the connection matrix no longer works. Therefore, we need a different way of finding a suitable connection matrix." ] }, { "cell_type": "markdown", "id": "2372836d-372a-43bd-bef4-8af7a767dc96", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "source": [ "This leads us to studying the \"learning rules\" for a network. In other words, we do not specify the connection matrices beforehand, but instead let the network learn from examples. Here we will use \"supervised online learning\", as we will present the network with sample inputs and the correct outputs, one pair at a time (these are called \"training data\"). The hope is that the network uses certain rules to update its connection matrix, which eventually converges to a working solution." ] }, { "cell_type": "markdown", "id": "intimate-purpose", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "For the simple perceptron, there is a simple learning rule. Suppose at one time the network is presented with the input pattern $\\xi^\\mu$, and with its current connection matrix $W_{ki}$ it outputs\n", "\\begin{equation}\n", "R_k = g \\Big( \\sum_i W_{ki} \\xi^\\mu_i \\Big)\n", "\\end{equation}\n", "which may be different from the target output $\\zeta^\\mu$. The learning rule is to update the connection matrix by:\n", "\\begin{equation}\n", "\\Delta W_{ki} = \\eta \\, (\\zeta^\\mu_k - R_k) \\, \\xi^\\mu_i\n", "\\end{equation}\n", "Here $\\eta$ is a small positive number called the \"learning rate\". It can be shown that, after presenting the network repeatedly with the input and output patterns, the network will find an appropriate connection matrix." ] }, { "cell_type": "markdown", "id": "palestinian-audit", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "source": [ "Let us test this learning rule. We first have to add it to our `SimplePerceptron` class as a new function, which will be called `train()`. This function takes two arguments, an input pattern and its associated output pattern." ] }, { "cell_type": "code", "execution_count": 10, "id": "contemporary-error", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "outputs": [], "source": [ "class SimplePerceptron(FeedforwardNetwork):\n", " \"\"\"\n", " simple perceptron as a 1-layer feedforward network.\n", " \"\"\"\n", " \n", " def store(self, inputs, outputs):\n", " \"\"\"\n", " store input/output pairs by calculating the connection matrix.\n", " inputs:\n", " inputs: 2-d array, each row is an input pattern.\n", " outputs: 2-d array, each row is an output pattern.\n", " \"\"\"\n", " inputs = np.asarray(inputs)\n", " outputs = np.asarray(outputs)\n", " corr = np.dot(inputs, inputs.T) / self.Ni\n", " dual = np.linalg.solve(corr, inputs)\n", " self.connection = np.dot(outputs.T, dual) / self.Ni\n", " \n", " def train(self, input, output, learning_rate=None):\n", " \"\"\"\n", " train network using the perceptron learning rule.\n", " inputs:\n", " input: 1-d array, given input values from training data.\n", " output: 1-d array, target output values from training data.\n", " learning_rate: float, learning rate, should be a small number.\n", " \"\"\"\n", " if learning_rate is None:\n", " learning_rate = 1/self.Ni\n", " out = self.run(input) # generate output with current connections\n", " diff = output - out # difference between target output and current output\n", " self.connection += learning_rate * diff[:,np.newaxis] * input # simple perceptron learning rule" ] }, { "cell_type": "markdown", "id": "contemporary-poster", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "Let us train a new network with the learning rule." ] }, { "cell_type": "code", "execution_count": 11, "id": "neither-birmingham", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "outputs": [], "source": [ "net = SimplePerceptron(Ni, No) # create perceptron network\n", "\n", "T = 200 # training time\n", "seq = np.random.randint(M, size=T) # random sequences of input patterns\n", "\n", "for s in seq:\n", " net.train(inputs[s], outputs[s]) # present an input-output pair every time" ] }, { "cell_type": "markdown", "id": "outside-obligation", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "Now we can test the network on our other guest." ] }, { "cell_type": "code", "execution_count": 12, "id": "silent-assumption", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "inp = img2vec(img2) # second image as input pattern\n", "out = net.run(inp) # generate output\n", "name = vec2img(out, shape_out) # convert output back to image\n", "\n", "fig, ax = plt.subplots(1, 2, figsize=(4,2))\n", "ax[0].imshow(img, cmap='Greys_r')\n", "ax[0].axis('off')\n", "ax[0].set_title('input')\n", "ax[1].imshow(name, vmin=0, vmax=1, cmap='Greys_r')\n", "ax[1].axis('off')\n", "ax[1].set_title('output')\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "corrected-income", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "source": [ "You can see that the network is already performing pretty well. If we train the network with more data, the performance may further improve. (There may be times when the training fails, as the process is stochastic; run again if that happens.)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.8.10" } }, "nbformat": 4, "nbformat_minor": 5 }