3 minute read

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()