Homework 3: Hopfield Networks

Due Friday, 14 March

This assignment is worth 15% of your grade. You will write an implementation of a Hopfield network that allows you to store and retrieve and a small set of images.

It will be convenient to use a vector to represent the activations and a matrix (a vector of vectors) to represent the weights in the network. These, along with the number of units in the network, which never changes after the network is created, can be global variables if you wish. Units are referenced by their indeces in the activation vector and the weight matrix. Since we will be using images as inputs to the network, it will be convenient to represent them, and the units in the network, in terms of x and y coordinates, even though these values are irrelevant to the behavior of the network.

  1. Write a procedure init which takes the two dimensions of the input images (width and height) and initializes the activation vector and the weight matrix accordingly (the activation vector holds width * height values and the weight matrix holds the square of that). Initial activations are random (either -1 or +1) and initial weights are 0.0. Make sure that you create a separate vector for each row of the weight matrix rather than re-using the same vector for each row.

  2. Write getter and setter procedures that return or update the activation of a unit with a given index and return or update the weight of a pair of units with given indeces. Note: the weights must be symmetric. This means you can either maintain two copies of each weight (one from unit i to unit j, the other from unit j to unit i) or maintain only one copy but allow it to be accessed from both directions.

  3. Write procedures print-net, print-weights, and print-pattern, which pretty-print network activation and weights and the values in input patterns.

  4. Write a procedure input-to-unit which calculates the input to a given unit i. This is just the sum of the products of the activations of the other units and the weights connecting them to i. The unit should not receive input from itself.

  5. Write a procedure update1 which updates the activation of a given unit i. This simply calls input-to-unit, and if it returns a value greater than 0.0, the activation is set to 1; otherwise it is set to -1. update1 should return #t if the activation has changed, #f if it hasn't.

  6. Write a procedure update which, one a time, randomly selects a unit from the network and updates it (using update1) until it has selected twice as many units are there are units in the network. update should return #t if any unit changes its activation in the process.

  7. Write a procedure input-pattern which takes an input pattern and activates the network with it. An input pattern is a vector of -1s, +1s, and 0s. The -1s and +1s are copied as activations in the corresponding units of the network. The 0s leave the activations of the corresponding units unspecified; these units should have their activations set randomly to +1 or -1.

  8. Write a procedure run which takes an input pattern, activates the network with it (calling input-pattern) and then repeatedly calls update until it returns #f, that is, until no units change their activation on a given set of updates.

  9. Write a procedure learn1 which takes a training pattern, an input pattern with only -1s and +1s, calculates the outer product of the pattern vector with itself, and adds the values in the outer product to the corresponding weights in the weight matrix. Note that for each pair of units, the product needs to be calculated only once.

  10. Write a procedure learn which takes a set of training patterns, adjusts the weight matrix for each using learn1, and then normalizes the weights by dividing each by the number of training patterns.

  11. Train a network on a set of 4 or 5 images. This file contains seven character images that you can use. Start with subsets of the images which don't overlap much, for example, A, M, and S. Experiment with your trained network by testing it on images from the training set, on images from the training set with added noise, and on random images. You will probably want to write a procedure which adds a certain amount of noise to a pattern (but make sure you create a separate vector to add the noise to rather than mutating the original pattern vector). Briefly discuss your results.