Replication of Hopfield Model
You can view all my work (including slides) here
Some codes:
- Discrete Hopfield Model
import numpy as np
#define a Hopfield Model
class Hopfield_Model:
def __init__(self, num_of_neurons):
self.num_of_neurons = num_of_neurons
self.weights = np.zeros((num_of_neurons, num_of_neurons))
#Hebbian Theory
def hebbian(self, states):
for state in states:
adjusted_state = state*2 - 1
self.weights += np.outer(adjusted_state, adjusted_state)
np.fill_diagonal(self.weights, 0)
self.weights /= self.num_of_neurons
#update Algorithm
def update(self, state):
for i in range(self.num_of_neurons):
judge = np.dot(self.weights, state)
if judge[i] >= 0:
state[i] = 1
else: state[i] = 0
return state
#processing
def process(self, state, time):
for _ in range(time):
state = self.update(state)
return state
N = 100
num_of_memories = 1
noise_level = 0.1
tries_per_memory = 50
memories = np.random.choice([0, 1],size=(num_of_memories, N))
hopfield = Hopfield_Model(num_of_neurons=N)
hopfield.hebbian(memories)
test = np.random.choice([0,1],size=(100,))
output = hopfield.process(test,time=100)
print(memories)
print(output)
- Continuous Hopfield Model-A/D Converter
import numpy as np
from math import tanh
class Hopfield_Model:
# initialization
def __init__(self, num_of_neurons):
self.num_of_neurons = num_of_neurons
self.u0 = 0.5
self.delta_t = 0.001
self.energy = []
# set T
self.T = np.zeros((self.num_of_neurons,self.num_of_neurons))
for i in range(self.num_of_neurons):
for j in range(self.num_of_neurons):
if j != i:
self.T[i][j] = - 2**(i+j)
else: self.T[i][j] = 0
# set u, V
self.u = np.zeros(self.num_of_neurons)
self.u1 = self.u.copy()
self.V = np.zeros(self.num_of_neurons)
# set I
def set_I(self, X=int):
self.X = X
self.I = np.zeros(self.num_of_neurons)
self.I = [- 2**(2*i - 1) + 2**i * X for i in range(self.num_of_neurons)]
# update function
def update(self):
self.V = [1/2 * (1 + tanh(self.u[i]/self.u0)) for i in range(self.num_of_neurons)]
for i in range(self.num_of_neurons):
dot = 0
for j in range(self.num_of_neurons):
dot += self.T[i][j]*self.V[j]
delta_u = self.delta_t * (self.I[i] -self.u[i] + dot)
self.u1[i] += delta_u
self.u = self.u1.copy()
# processing
def process(self, times):
for j in range(times):
self.update()
self.energy.append(self.energy_cal())
return self.V, self.energy
def energy_cal(self):
X1 = 0
for i in range(self.num_of_neurons):
X1 += 2**i * self.V[i]
energy = 1/2 * (self.X - X1)**2
for i in range(self.num_of_neurons):
energy = energy + 2**(2*i-1) * self.V[i] * (1-self.V[i])
return energy
i = 13
model = Hopfield_Model(4)
model.set_I(i)
v, energy = model.process(150000)
print('X = ', i, ' v =', v, 'energy = ',energy[-1])
import matplotlib.pyplot as plt
x = np.arange(0,150000)
plt.bar(x, energy, color='blue', alpha=0.7)
plt.xlabel('Number of Iterations')
plt.ylabel('Energy')
plt.savefig('/Users/qiyuchen/Desktop/3.png')
plt.show()
- Continuous Hopfield Model-TSP
import numpy as np
class Hopfield:
def __init__(self, num_of_cities, A = 100, D = 100, study_rate = 0.01, u0 = 0.2):
self.num_of_cities = num_of_cities
self.distance = np.zeros((self.num_of_cities, self.num_of_cities))
self.u = np.zeros((self.num_of_cities, self.num_of_cities))
self.V = np.zeros((self.num_of_cities, self.num_of_cities))
self.A = A
self.D = D
self.u0 = u0
self.study_rate = study_rate
self.energy = []
for X in range(self.num_of_cities):
for i in range(self.num_of_cities):
self.u[X][i] = np.arctanh(2/self.num_of_cities - 1)*(1 + np.random.uniform(-0.1,0.1))
def cal_energy(self):
energy = 0
for X in range(self.num_of_cities):
t = 0
for i in range(self.num_of_cities):
t += self.V[X][i]
energy += 0.5 * self.A * (t-1)**2
for i in range(self.num_of_cities):
t = 0
for X in range(self.num_of_cities):
t += self.V[X][i]
energy += 0.5 * self.A * (t-1)**2
for X in range(self.num_of_cities):
for Y in range(self.num_of_cities):
for i in range(self.num_of_cities):
energy += 0.5 * self.D * self.distance[X][Y] * self.V[X][i%self.num_of_cities] * \
self.V[Y][(i+1)%self.num_of_cities]
return energy
def get_distance(self, distance):
self.distance = distance
def update(self):
for X in range(self.num_of_cities):
for i in range(self.num_of_cities):
self.V[X][i] = 0.5 * (1 + np.tanh(self.u[X][i]/self.u0))
for X in range(self.num_of_cities):
for i in range(self.num_of_cities):
delta = 0
term1, term2 = 0, 0
for j in range(self.num_of_cities):
term1 += self.V[X][j]
for Y in range(self.num_of_cities):
term2 += self.V[Y][i]
delta = - self.A * (term1 - 1) - self.A * (term2 - 1)
for Y in range(self.num_of_cities):
delta += -self.D * self.distance[X][Y] * self.V[Y][(i+1)%self.num_of_cities]
self.u[X][i] += delta * self.study_rate
def process(self, times):
for i in range(1, times+1):
self.update()
self.energy.append(self.cal_energy())
return self.V, self.energy
np.random.seed(3407)
points = np.random.rand(10, 2)
distance_matrix = np.linalg.norm(points[:, np.newaxis, :] - points[np.newaxis, :, :], axis=2)
tsp = Hopfield(num_of_cities=10)
tsp.get_distance(distance=distance_matrix)
import matplotlib.pyplot as plt
V, energy = tsp.process(1000)
print(V, energy)
plt.imshow(V)
plt.colorbar()
plt.title('10 Cities')
plt.savefig('/Users/qiyuchen/Desktop/9.png')
plt.show()
plt.clf()
x = np.arange(1,1001)
plt.bar(x, energy, color='blue', alpha=0.7)
plt.xlabel('Number of Iterations')
plt.ylabel('Energy')
plt.savefig('/Users/qiyuchen/Desktop/10.png')
plt.show()