おいも貴婦人ブログ

生物系博士課程満期退学をしたAIエンジニアのブログ。

ホップフィールド(Hopfield)

Hopfieldはアメリカの物理学者J.J. Hopfieldによって提唱された。一種の連想記憶モデルであり、パターンを学習させると、そのパターンを再起するというものである。Hopfieldネットワークは相互結合型のネットワークで、1つのノードは他のすべてのノードとつながっており、それぞれのエッジは重み係数により定義される。各ノードは-1,1の二値をとる。パターンを覚えさせる最の学習則は、以下とした。プログラミングするにあたり、以下のURLを参考にさせていただいた。ただ、エネルギー関数を定義するのを忘れていたので、後々修正する予定。
http://www-ailab.elcom.nitech.ac.jp/lecture/neuro/hop2.html

f:id:oimokihujin:20140603025242g:plain
この図は、一番最初の図が学習させていないパターンであり、最後に学習させたパターンになっている。

#! /usr/bin/env python
# coding:utf-8

import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
import random
N=12


pos={}
edge_list=[]
tpatern=[]
tpatern.append(np.array([0,0,0,1,1,1,0,0,0,1,1,1]))
tpatern.append(np.array([1,0,0,0,0,0,0,0,1,1,0,0]))
random.seed(10)

weight=np.zeros((N,N))
for i in range(N):
    for j in range(N):
        edge_list.append([i,j])

for i,x in enumerate(np.arange(0,np.pi*2,np.pi*2/N)):
    pos[i]=np.array([np.cos(x),np.sin(x)])

def learn_weight():
    for i in range(N):
        for j in range(N):
            for k in range(len(tpatern)):
                if i != j:
                    weight[i,j]+=tpatern[k][i]*tpatern[k][j]
                else:
                    break

def func(x):
    return 2/(1+np.exp(-20*x))-1


def remember(data,i):
    data[i]=func(np.dot(weight[i],data))
    return data
data=np.array([1,0,1,0,1,0,1,1,0,1,0,0])



learn_weight()

E=0
E2=0
number=0
while(True):
    G=nx.Graph()
    zeronodes=[]
    onenodes=[]
    learn_node=random.randint(0,N-1)
    data=remember(data,learn_node)

    for j in range(N):
        if data[j]==0:
            zeronodes.append(j)
        else:
            onenodes.append(j)
    
    nx.draw_networkx_nodes(G,pos,nodelist=zeronodes,node_color='w')
    nx.draw_networkx_nodes(G,pos,nodelist=onenodes,node_color='b')
    nx.draw_networkx_edges(G,pos,edgelist=edge_list)
    plt.axis("off")
    E=np.sum(np.abs(data-tpatern[0]))
    E2=np.sum(np.abs(data-tpatern[1]))

    num="%04d" % number
    plt.savefig("hopfiled"+num+".png")
    print E,E2
    if E==0 or E2==0:
        break
    number+=1