Sei sulla pagina 1di 10

070005210

Title: Implementation of a Hopeld Network in Python

Matriculation number: 070005210 Module number: PS4066 Supervisor: Peter Foldiak Date:
1

070005210

Implementation of a Hopeld Network in Python


1 Introduction

An articial neural network (ANN) is a mathematical or computational model inspired by the structure or function of biological neural networks. An ANN consists of an interconnected group of articial neurons, known as units. The network can adapt by changing its structure based on internal or external information it receives while in the learning phase. Modern neural networks are used to model complex relationships between inputs and outputs or to nd patterns within a set of data. Neural networks, either articial or biological in nature, can be simulated by software applications. Various implementations of neural networks are accessible in a number of programming languages, on a number of platforms. There are many programming libraries available in computing environments such as MATLAB which contain neural network functionality, allowing for custom implementations. Basic neural networks, however, are easy to implement directly. In order to further explore the functionality of the Hopeld network, a relatively simple neural net, I have chosen to implement it using the Python programming language. This report will begin with an overview of the Hopeld network, including its usage. The relative merits of the Python programming language will then be put forward and the code of the implementation outlined. Finally, the limitations of the Hopeld network will be discussed.

2
2.1

An overview of the Hopeld net


Recurrent neural networks

A recurrent neural network (RNN) is a special class of articial neural network, where connections between units form a directed cycle. They are dierent from feed-forward architectures in that they do not simply operate on input space, but also take into account the internal state space of the network. The internal state space contains a trace of what the network has previously processed, and allows for exhibition of dynamic temporal behaviour. This means that the network can use the state space for the representation and learning of arbitrary sequences of inputs (e.g. patterns) over an unspecied period of time. The basic architecture of an RNN consists of a network of simulated neurons (known as units). Each unit has a directed connection to every other unit and these connections have modiable weights. Algorithms such as back-propagation allow for the weights of the RNN to be adjusted so that an output may be produced on the appropriate unit when a particular pattern is observed at the input. The back-propagation algorithm works by propagating back the dierences between desired and actual outputs 2

070005210

to the input and hidden layers. Propagation occurs by modication of the weights of each component neuron (node). RNNs operate by modifying this algorithm to allow for temporal classication in the form of a context layer, which retains information between observations. 2.1.1 The Hopeld net: a specialised case of recurrent neural networks

A Hopeld net is a specialised case of a RNN which requires stationary inputs, unlike an ordinary RNN which is designed to process sequences of patterns. No reexive connections are allowed. It assumes symmetric weights, as this guarantees that the energy function will decrease in a monotonic manner while following the activation rules. If non-symmetric weights are used, chaotic behaviour may occur; however, Hopeld (1982) observed that this chaotic behaviour is conned to small parts of the phase space only and does not impair the ability of the network to act as a content-addressable memory system. The architecture of the network guarantees that its dynamics (energy function) will converge to a local minimum, but convergence to a stored pattern is not guaranteed.

2.2

Hopeld nets and Hebbian learning

Hebbs rule (Hebb, 1949) postulated that the more often a pair of cells re simultaneously, the more likely the synaptic strength is to increase between those cells. This principle can be thought of as a method of how to alter weights between units in an ANN. If both nodes are positive or negative, this corresponds in a strong positive weight, but if the nodes are opposite in state from one another this corresponds in a strong negative weight. When connections between units in a Hopeld net are trained using the Hebb rule, the net can perform as robust content-addressable memory.

2.3

The structure of the net

The units in a Hopeld net are known as binary threshold units. This means that the units can only take on two dierent values (in this case 1) for their states. These values are determined by whether the units input exceeds their threshold value. In this case, the denition for unit i s activation ai is thus: ai 1 1 if j wij sj > i , otherwise (1)

wij is the strength of connection weight from unit j to unit i sj is the state of unit j i is the state of unit i

070005210

Connections in a Hopeld net typically have the following restrictions: wii = 0, i (no unit has a connection with itself) wij = wji , i, j (connections are symmetric) 2.3.1 Running the net

When the network is run, at each step a node is picked at random. The behaviour of the node is then deterministic - the node attempts to move to a state which minimizes the energy of itself and its neighbours. The Boltzmann Machine is a variant of the Hopeld net which instead utilises stochastic updating in order to simulate a non-zero temperature. 2.3.2 Training the net

Training a Hopeld net involves lowering the energy of states which the network should remember. This allows the net to serve as a content-addressable memory system as the network will converge to a remembered state if given (a) only part of the state or (b) a scrambled or noisy version of the state.

3
3.1

Using a Hopeld net


Lyapunov functions

In a Hopeld net, a scalar value is associated with each network state. This is referred to as the energy of the network and is calculated in the following manner: E= 1 2 wij si sj +
i, j i

i si

(2)

This denition of the energy of the network ensures that if units are updates asynchronously, the network will converge to states that are local minima in the energy function. Computation in this system may be considered as starting from an initial state from which a nal state evolves by moving downhill on E. The reason that the network can not guarantee convergence to a stored pattern is because of the existence of the Lyapunov function in the dynamics of the network. Any asymptotic output is in the form of an attractor state. Lyapunov functions in a Hopeld network are useful, as they allow optimisation problems to be represented within the net (Hopeld & Tank, 1985). Optimisation problems are represented within the network by transformation of the problem into variables such

070005210

that the desired optimisation corresponds to the minimisation (i.e. energy minima) of the respective Lyapunov function. The Travelling Salesman problem is a problem in graph theory which requires the total smallest amount of travel distance a salesman can take in order to visit n number of cities. This is a problem of optimisation which can be solved as detailed above by a Hopeld Network making use of a Lyapunov function.

3.2

Solving problems which do not appear to be problems of optimisation

Problems which, at rst glance, appear not to be optimisation problems can usually be reinstated in the language of optimisation. Hopeld (2006) gives an example in which a sudoku puzzle be solved using a Hopeld net. The puzzle is described thus, using the language of optimisation: Place the largest number of integers 1-9 into the blank spaces as possible, without violating any rules. (Hopeld, 2006) The correct solution for this reinstatement of the problem is a unique pattern within a 9-by-9 grid which has no blanks left and has maximised the number of entries in the grid.

4
4.1

Choosing Python to code the net


Why choose this language?

Python is known as a scripting language - an interpretive language with built-in memory management and facilities for calling and cooperating with other programs. While some programs, such as Perl, advocate that there is more than one way to do it, this can lead to inconsistency in style across a wider code base (code longer than a couple hundred lines) and therefore less elegant code. Python, on the other hand, places an emphasis on code readability and the principles of KISS (placing importance in design simplicity) and DRY (reduction of repetition of pieces of code). This makes code written in Python relatively easy to share with others. Python also supports multiple programming paradigms such as object-oriented, imperative and functional programming styles. This allows for a framework in which programmers can choose the style they code in, and availability to freely interleave constructs from dierent paradigms (Budd, n.d.). Excellent tutorials are available for both individuals with extensive programming experience and those with little-to-none. The opensource and cross-platform nature of Python mean that programming in this language is supported on most operating systems (Windows, Mac OSX and other BSD/UNIX-style 5

070005210

platforms) and that there is an extensive support network available. Python has proven itself to be more accessible than other languages and it was ultimately this aspect of the language that led the author to choose it as the language in which they would implement a neural network.

4.2

Why use it to code a neural net?

The modular nature of Python means that there are a large number of libraries available with are targeted at aiding implementation of articial neural networks (i.e. Pybrain, Brian, FANN among others). This makes it easier to design and implement an ANN using the language. In particular, commonly-used library NumPy allows more complex networks to be programmed from scratch due to its support for large, multidimensional arrays. A number of high-level mathematical functions are also included to operate on these arrays. Most modern neural network architecture makes use of an orientated-programming paradigm. Each neuron (or unit) is encapsulated in a single class; neurons are connected to each other through a weight. This weight can be part of the neuron or weight class. Use of this paradigm ensures that reusable code (which can be implemented in a variety of ANNs) is generated. It is this last feature of Python that assured the author it was one of the best manners in which to implement a Hopeld net.

Implementation of the network

The programs source code is available in full at the end of this document. When ran with patterns and number of nodes specied, the network rst initialises all weights to zero. It then runs the patterns through a learning algorithm and consequently adjusts the weights according to a slightly modied method of Hebbian learning. The network becomes initialised to a random or predetermined state and is updated using the Hopeld algorithm. After a set number of iterations, the network then settles to a stable state.

6
6.1

Limitations of the program


Inversion

This implementation of a Hopeld network often settles on a pattern which is inverted. Lopez-Rodriguez et al (2005) address and justify this problem. Since X and X have the same associated vector, the energy increase will be identical for both when a pattern is introduced into the network (LopezRodriguez et al, 2005) 6

070005210

This identical energy increase means that retrieval of an inverted pattern is feasible; as, stated previously, convergence of the network to a stored pattern is not guaranteed. 1 1 1 1 1 instead of 1 1 1 1 1 Figure 1: An example of inversion

6.2

Dreaming

The calculated maximum number of patterns that this implementation of a Hopeld net can store is 0.15N , where N = number of nodes. This is consistent with previous ndings (Hopeld, 1982). When the network is overloaded, it no longer converges to a clearly dened pattern. Instead, the network settles to a new pattern which is a combination of the patterns being stored. This is known as dreaming (Hopeld, 1982). Crick & Mitchison (1983) observed this dreaming state which a Hopeld net can settle to and asked why the human brain does not suer from the same problem (namely, overload of information). They hypothesised that we dream in order to forget. This hypothesis has been supported, as when the net is passed through alternative phases of learning and forgetting, the problem of overloading is solved - at the cost of dramatically reducing the memory capacity of the network.

Conclusion

Implementation of a Hopeld network in Python was a worthwhile challenge. It improved the authors in-depth knowledge of the Hopeld net and the Python programming language. Limitations of the network were also discussed and justied. The modular nature of Python made implementation simple, if not necessarily easy. The network could be improved with the addition of the library Numpy, allowing for more complex patterns to be input (in the form of matrices as opposed to vectors). Overall, the author would recommend Python for the implementation of articial neural networks - especially if libraries targeted towards NN are considered (i.e. Pybrain).

070005210

References

Budd, T. (n.d.) The Leda Programming Language. Available from: <http://web.engr.oregonstate.edu/budd/leda.html> [16th November 2010] Crick, F. & Mitchison, G. (1983) The function of dream sleep. Nature, 304, pp. 111-114 Hebb, D.O. (1949) The organization of behavior. New York: Wiley & Sons, pp. 70 Hopeld, J. J. (1982) Neural networks and physical systems with emergent collective computational properties. Proc. Nat. Acad. Sci. (USA), 79, pp. 2554-2558. Hopeld, J. J. (2006) Searching for memories, Sudoku, implicit check-bits, and the iterative use of not-always-correct rapid neural computation. <http://arxiv.org/abs/qbio.NC/0609006> Hopeld, J. J. and Tank, D. W. (1985) Neural computation of decisions in optimization problems. Biological Cybernetics. 55, pp. 141-146 Lopez-Rodriguez, D., Merida-Casermeiro, E. & Ortiz-de-Lazcano-Lobato, J. M. (2005) Hopeld Network as Associative Memory with Multiple Reference Points. World Academy of Science, Engineering and Technology, 7, pp. 62-67

070005210

Code
Listing 1: An Implementation of a Hopeld Net Using Python

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

#! / u s r / b i n / python2 This program i s c a p a b l e o f running a s i m p l e H o p f i e l d n e t . P a t t e r n s , number o f u n i t s and i n i t i a l i s a t i o n v a l u e s can e i t h e r be d e f i n e d by t h e used i n t h e . py f i l e or can be d y n a m i c a l l y s e t as t h e program runs . import random import time p a t t e r n s = [ [ 1 , 1 , 1, 1, 1] , [ 1 , 1, 1 , 1, 1 ] ] n = 5 #p a t t e r n s = i n p u t ( I n p u t p r e f e r r e d p a t t e r n s i n t h i s f o r m a t [ [ x1 , x2 , x3 ] # , [ x4 , x5 , x6 ] ] : \n \ t \n ) #n = i n p u t ( I n p u t number o f u n i t s ( n o t e : must be same as number o f e l e m e n t s #i n p a t t e r n ) : \n \ t \n ) alpha = 0.01 weights = [ ] output = [ ]

def i n i t W e i g h t s ( n ) : # s e t w e i g h t s t o z e ro , n i s t h e number o f u n i t s global w e i g h t s weights = [ [ 0 for in r a n g e ( n ) ] f o r in r a n g e ( n ) ] print ( w e i g h t s ) def i n i t N e t w o r k ( p ) : global output output = p print ( p ) # i n i t i a l i s e s units to a c t i v a t i o n

def updateNetwork ( k ) : # p i c k u n i t a t random and u p d a t e k t i m e s global output , w e i g h t s f o r l in r a n g e ( k ) : u n i t = random . r a n d i n t ( 0 , n1) print ( u p d a t i n g u n i t , u n i t ) , act = 0 f o r i in r a n g e ( n ) :

070005210

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79

a c t += output [ i ] w e i g h t s [ u n i t ] [ i ] output [ u n i t ] = 1 i f a c t > 0 e l s e 1 time . s l e e p ( 0 . 2 ) print ( \ t . . . . . . . . . . \ t ) , print ( output ) def l e a r n ( p ) : global alpha , n , w e i g h t s f o r i in r a n g e ( n ) : f o r j in r a n g e ( n ) : i f i != j : w e i g h t s [ i ] [ j ] += a l p h a p [ i ] p [ j ] print ( \n\n\ n i n i t i a l i s i n g a l l w e i g h t s t o z e r o . . . ) print ( w e i g h t s i n i t i a l i s e d : ) initWeights (n) learn ( patterns [ 0 ] ) learn ( patterns [ 1 ] ) print ( \ n i n i t i a l p a t t e r n s : ) print ( p a t t e r n s ) print ( \nnow c h o o s i n g a p a t t e r n a t random . . . \ n ) print ( a d j u s t i n g w e i g h t s v i a Hebbian l e a r n i n g . . . ) print ( a d j u s t e d w e i g h t s f o r c h o s e n p a t t e r n : ) print ( w e i g h t s ) print ( \ n i n i t i a l i s i n g t h e network t o a random s t a t e . . . ) print ( network i n i t i a l i s e d : ) i n i t N e t w o r k ( [ 1 , 1, 1 , 1, 1]) # e a s y t o i n i t i a l i s e network w i t h own chosen v a l u e s #initNums = [ 1 , 1 , 1 , 1 , 1 , 1, 1, 1, 1, 1] #i n i t N e t w o r k ( random . sample ( initNums , 2) ) # n o t e : w i t h random i n i t i a l i s a t i o n , run r i s k o f p a t t e r n f l i p p i n g print ( \ nupdating t h e network : ) #i n i t N e t w o r k ( [ random {} f o r r i n range ( 5 ) ] ) updateNetwork ( 1 0 ) print ( \ n f i n a l p a t t e r n : ) print ( output ) print ( \n\n\n ) raw input ()

10

Potrebbero piacerti anche