
| Current Path : /var/www/web-klick.de/dsh/50_dev2017/1310__algorithms/Julia/Notebooks/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : /var/www/web-klick.de/dsh/50_dev2017/1310__algorithms/Julia/Notebooks/Hopfield Networks.ipynb |
{
"metadata": {
"language": "Julia",
"name": "",
"signature": "sha256:c567d0cf8a3b76c51377e3c3d8921f7af10592b3b77af430e20ce859866664bb"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Hopfield Networks"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Hopfield networks were invented in the 1980\u2032s to demonstrate how a network of simple neurons might learn to associate incoming stimuli with a fixed pool of existing memories. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To see how Hopfield networks work, we need to define their internal structure. We\u2019ll assume that a Hopfield network is made up of N neurons. At every point in time, this network of neurons has a simple binary state, which I\u2019ll associate with a vector of -1\u2032s and +1\u2032s."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Incoming stimuli are also represented using binary vectors of length N. Every time one of these stimuli is shown to the network, the network will use a simple updating rule to modify its state. The network will keep modifying its state until it settles into a stable state, which will be one of many fixed points for the updating rule. We\u2019ll refer to the stable state that the network reaches as the memory that the network associates with the input stimulus."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For example, let\u2019s assume that we have a network consisting of 42 neurons arranged in a 7\u00d76 matrix. We\u2019ll train our network to recognize the letters X and O, which will also be represented as 7\u00d76 matrices. After training the network, we\u2019ll present corrupted copies of the letters X and O to show that the network is able to associate corrupted stimuli with their uncorrupted memories. We\u2019ll also show the network an uncorrupted copy of the unfamiliar letter F to see what memory it associates with an unfamiliar stimulus."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"abstract HopfieldNet\n",
"\n",
"function energy(net::HopfieldNet)\n",
" e = 0.0\n",
" n = length(net.s)\n",
" for i in 1:n\n",
" for j in 1:n\n",
" e += net.W[i, j] * net.s[i] * net.s[j]\n",
" end\n",
" end\n",
" e *= -0.5\n",
" for i in 1:n\n",
" e += net.W[i] * net.s[i]\n",
" end\n",
" return e\n",
"end\n",
"\n",
"function settle!(net::HopfieldNet,\n",
" iterations::Integer = 1_000,\n",
" trace::Bool = false)\n",
" for i in 1:iterations\n",
" update!(net)\n",
" if trace\n",
" @printf \"%5.0d: %.4f\\n\" i energy(net)\n",
" end\n",
" end\n",
" return\n",
"end\n",
"\n",
"function associate!{T <: Real}(net::HopfieldNet,\n",
" pattern::Vector{T};\n",
" iterations::Integer = 1_000,\n",
" trace::Bool = false)\n",
" copy!(net.s, pattern)\n",
" settle!(net, iterations, trace)\n",
" # TODO: Decide if this should really be a copy\n",
" return copy(net.s)\n",
"end\n",
"\n",
"# Hebbian learning steps w/ columns as patterns\n",
"function train!{T <: Real}(net::HopfieldNet, patterns::Matrix{T})\n",
" n = length(net.s)\n",
" p = size(patterns, 2)\n",
" # Could use outer products here\n",
" # (1 / p) * (patterns[:, mu] * patterns[:, mu]')\n",
" for i in 1:n\n",
" for j in (i + 1):n\n",
" s = 0.0\n",
" for mu in 1:p\n",
" s += patterns[i, mu] * patterns[j, mu]\n",
" end\n",
" s = s / p # May need to be careful here\n",
" net.W[i, j] += s\n",
" net.W[j, i] += s\n",
" end\n",
" end\n",
" return\n",
"end\n",
"\n",
"function h{T <: Real}(i::Integer, j::Integer, mu::Integer, n::Integer,\n",
" W::Matrix{Float64}, patterns::Matrix{T})\n",
" res = 0.0\n",
" for k in 1:n\n",
" if k != i && k != j\n",
" res += W[i, k] * patterns[k, mu]\n",
" end\n",
" end\n",
" return res\n",
"end\n",
"\n",
"# Storkey learning steps w/ columns as patterns\n",
"function storkeytrain!{T <: Real}(net::HopfieldNet, patterns::Matrix{T})\n",
" n = length(net.s)\n",
" p = size(patterns, 2)\n",
" for i in 1:n\n",
" for j in (i + 1):n\n",
" for mu in 1:p\n",
" s = patterns[i, mu] * patterns[j, mu]\n",
" s -= patterns[i, mu] * h(j, i, mu, n, net.W, patterns)\n",
" s -= h(i, j, mu, n, net.W, patterns) * patterns[j, mu]\n",
" s *= 1 / n\n",
" net.W[i, j] += s\n",
" net.W[j, i] += s\n",
" end\n",
" end\n",
" end\n",
" return\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 1,
"text": [
"storkeytrain! (generic function with 1 method)"
]
}
],
"prompt_number": 1
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type ContinuousHopfieldNet <: HopfieldNet\n",
" s::Vector{Float64} # State\n",
" W::Matrix{Float64} # Weights\n",
"end\n",
"\n",
"function ContinuousHopfieldNet(n::Integer)\n",
" s = ones(n)\n",
" W = zeros(n, n)\n",
" ContinuousHopfieldNet(s, W)\n",
"end\n",
"\n",
"# Perform one asynchronous update on randomly selected neuron\n",
"function update!(net::ContinuousHopfieldNet)\n",
" i = rand(1:length(net.s))\n",
" net.s[i] = tanh(dot(net.W[:, i], net.s))\n",
" return\n",
"end\n",
"\n",
"function Base.show(io::IO, net::ContinuousHopfieldNet)\n",
" @printf io \"A continuous Hopfield net with %d neurons\\n\" length(net.s)\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 2,
"text": [
"show (generic function with 89 methods)"
]
}
],
"prompt_number": 2
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"type DiscreteHopfieldNet <: HopfieldNet\n",
" s::Vector{Float64} # State -- could have used Int's\n",
" W::Matrix{Float64} # Weights\n",
"end\n",
"\n",
"function DiscreteHopfieldNet(n::Integer)\n",
" s = ones(n)\n",
" W = zeros(n, n)\n",
" DiscreteHopfieldNet(s, W)\n",
"end\n",
"\n",
"# Perform one asynchronous update on randomly selected neuron\n",
"function update!(net::DiscreteHopfieldNet)\n",
" i = rand(1:length(net.s))\n",
" net.s[i] = dot(net.W[:, i], net.s) > 0 ? +1 : -1\n",
" return\n",
"end\n",
"\n",
"function Base.show(io::IO, net::DiscreteHopfieldNet)\n",
" @printf io \"A discrete Hopfield net with %d neurons\\n\" length(net.s)\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 3,
"text": [
"show (generic function with 90 methods)"
]
}
],
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"X = vec([+1 -1 -1 -1 -1 +1;\n",
" -1 +1 -1 -1 +1 -1;\n",
" -1 -1 +1 +1 -1 -1;\n",
" -1 -1 +1 +1 -1 -1;\n",
" -1 -1 +1 +1 -1 -1;\n",
" -1 +1 -1 -1 +1 -1;\n",
" +1 -1 -1 -1 -1 +1.])\n",
"\n",
"O = vec([+1 +1 +1 +1 +1 +1;\n",
" +1 -1 -1 -1 -1 +1;\n",
" +1 -1 -1 -1 -1 +1;\n",
" +1 -1 -1 -1 -1 +1;\n",
" +1 -1 -1 -1 -1 +1;\n",
" +1 -1 -1 -1 -1 +1;\n",
" +1 +1 +1 +1 +1 +1.])\n",
"\n",
"F1 = vec([-1 -1 -1 -1 -1 -1;\n",
" -1 +1 +1 +1 +1 -1;\n",
" -1 +1 -1 -1 -1 -1;\n",
" -1 +1 +1 +1 +1 -1;\n",
" -1 +1 -1 -1 -1 -1;\n",
" -1 +1 -1 -1 -1 -1;\n",
" -1 -1 -1 -1 -1 -1.])\n",
"\n",
"F2 = vec([+1 +1 +1 +1 +1 -1;\n",
" +1 -1 -1 -1 -1 -1;\n",
" +1 -1 -1 -1 -1 -1;\n",
" +1 +1 +1 +1 +1 -1;\n",
" +1 -1 -1 -1 -1 -1;\n",
" +1 -1 -1 -1 -1 -1;\n",
" +1 -1 -1 -1 -1 -1.])"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 4,
"text": [
"42-element Array{Float64,1}:\n",
" 1.0\n",
" 1.0\n",
" 1.0\n",
" 1.0\n",
" 1.0\n",
" 1.0\n",
" 1.0\n",
" 1.0\n",
" -1.0\n",
" -1.0\n",
" 1.0\n",
" -1.0\n",
" -1.0\n",
" \u22ee \n",
" -1.0\n",
" 1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0"
]
}
],
"prompt_number": 4
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"patterns = hcat(X, 2)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"ename": "LoadError",
"evalue": "mismatch in dimension 1\nwhile loading In[12], in expression starting on line 1",
"output_type": "pyerr",
"traceback": [
"mismatch in dimension 1\nwhile loading In[12], in expression starting on line 1",
" in cat at abstractarray.jl:616",
" in hcat at abstractarray.jl:656"
]
}
],
"prompt_number": 12
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"X"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 13,
"text": [
"42-element Array{Float64,1}:\n",
" 1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" 1.0\n",
" -1.0\n",
" 1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" 1.0\n",
" \u22ee \n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" 1.0\n",
" -1.0\n",
" 1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" 1.0"
]
}
],
"prompt_number": 13
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"tmp = DiscreteHopfieldNet(size(X, 1))"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 6,
"text": [
"A discrete Hopfield net with 42 neurons\n"
]
}
],
"prompt_number": 6
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"train!(tmp, hcat(X))"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"reshape(X, 6, 7)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 15,
"text": [
"6x7 Array{Float64,2}:\n",
" 1.0 1.0 1.0 1.0 1.0 -1.0 -1.0\n",
" -1.0 -1.0 -1.0 -1.0 1.0 -1.0 -1.0\n",
" -1.0 1.0 -1.0 -1.0 -1.0 -1.0 -1.0\n",
" -1.0 -1.0 -1.0 -1.0 -1.0 1.0 -1.0\n",
" -1.0 -1.0 1.0 -1.0 -1.0 -1.0 -1.0\n",
" -1.0 -1.0 1.0 1.0 1.0 1.0 1.0"
]
}
],
"prompt_number": 15
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Xcorrupt = copy(X)\n",
"for i = 2:7\n",
" Xcorrupt[i] = 1\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 9
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"Xrestored = associate!(h, vec(Xcorrupt))"
],
"language": "python",
"metadata": {},
"outputs": [
{
"ename": "LoadError",
"evalue": "no method associate!(Function, Array{Float64,1})\nwhile loading In[10], in expression starting on line 1",
"output_type": "pyerr",
"traceback": [
"no method associate!(Function, Array{Float64,1})\nwhile loading In[10], in expression starting on line 1"
]
}
],
"prompt_number": 10
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"vec(Xcorrupt)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 11,
"text": [
"42-element Array{Float64,1}:\n",
" 1.0\n",
" 1.0\n",
" 1.0\n",
" 1.0\n",
" 1.0\n",
" 1.0\n",
" 1.0\n",
" -1.0\n",
" 1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" 1.0\n",
" \u22ee \n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" 1.0\n",
" -1.0\n",
" 1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" -1.0\n",
" 1.0"
]
}
],
"prompt_number": 11
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
}