ホップフィールドネットワークを作ってみた
やあ、、、、うん、言いたいことはわかるよ。
最近、noteから離れすぎじゃないかってほどご無沙汰してるからね。
こうなった原因は他のものに興味が移ってしまったからかな。
もちろん、記事を書くのは嫌いじゃないんだけどね。
じゃあ実際は何をしてたかというと、
ほぼ神経科学の学習に費やしていたよ。
少しだけ情報理論にも触れたかな。
もしかすると、受験のころよりも熱心に勉強しているかも(笑)
もしかすると、この状態がしばらく続くかもしれないけれど
最低でも週一で更新はする予定だよ。
スキはできるだけ頑張る!!!
今後とも、お互い気を張らずにやっていこうよ。
さて、今日はホップフィールドネットワークについてだよ(笑)
うん、誰が興味あるんだよって思ったでしょ。
僕も思ったよ(笑)
派手な深層学習とかベイズ推定だとかのショーだと、食いついてくれる人もいるだろうけど、
実践より機械学習の理論を勉強したい!
ついでにSNNで機械学習の基盤の学習をしたい!!
そのための理論が知りたい!
なんて、人の記事を読んでくれるとは思わないからね。
だから、詳しい数式や理論の話はするつもりはないよ。
そんなことしたら、フォロワーさんが半分ほど消えそうだからね。
なんか難しそうなことしてるように見えるけど、やってることは単純。
システムにいくつか画像を覚えさせた後にその画像に似た画像を見せて、
元の画像を想起させるだけ。
これがあまりうまくいかなかった(´;ω;`)
もともと、そこまで優秀なネットワークという訳ではないのだろうね。
2枚の画像ではそれぞれの画像が局所解になって、逆にほとんど関連が無い情報でもどちらかにたどり着くようになっていたから良かったんだけど、
3枚以上になると、不適切な局所解に最終的に陥るようになってしまったからね。
この局所解は、エネルギーが元画像の状態よりも低く、かつ元画像のちょうど平均のような画像になっている事はグラフで可視化することで分かった。
この問題をどうやって回避するのかは大きな悩みだね。
もっと適切なネットワークもあるそうだから、もう少し調べてみようと思う。
今日はこんなところかな
ここまで付き合ってくれてありがとう
あ、今回、僕が作ったプログラムは下に置いておくよ
インターネット上にはもっと良いプログラムが転がってるから、
参照するならそっちがおすすめだよ。
それじゃあ、また
この店で
import numpy as np
import random
import matplotlib.pyplot as plt
n = 3 #画像数
p = 10000 #想起の試行回数 単位回
noise = 5 #ノイズの発生率 単位%
data = np.load('mnist.npz')['train_x']
#画像を適当な形に変換
def images_to_vectors(X):
X = np.reshape(X, (-1,28*28))
return X
#文字を書くための形式へ変換
def images_to_vector(X):
X = np.reshape(X, (28, -1))
return X
#文字を書く
def pict(x):
fig = plt.figure(dpi=100)
ax = fig.add_subplot(1,1,1)
im = ax.imshow(x,cmap='gray_r')
fig.colorbar(im)
plt.show()
#いろいろなグラフ(散布図)を書く
def show_graph(X, Y):
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(X, Y, marker='.')
ax.grid()
plt.show()
#エネルギーの関数
def E(w,x):
theta = np.zeros(28*28)
return -0.5*np.dot(np.dot(x,w),x.T) - np.dot(theta,x.T)
#学習させる
def fit(w,x):
a = 0
for i in range(np.shape(x)[0]):
try :
w += np.dot(x[i].T,x[i])/np.shape(x)[0]
except:
w = np.dot(x[i].T,x[i])/np.shape(x)[0]
for i in range(np.shape(w)[0]):
w[i][i]=0
return w
#想起させ、その時点での誤差やエネルギーを調べる(非同期)
def do(w,x,p):
global E_old,Dis,x2,n
y = list(range(28*28))
for i in range(p):
j = random.randint(0,np.shape(x)[1]-1)
#j = i % 784
y[j] = np.dot(x,w[j].T)
x[0][j] = np.sign(y[j][0])
E_time.append(i)
E_old = np.append(E_old,E(w,x))
Dis = np.append(Dis,sum([np.sum(np.abs(x-x2[r])) for r in range(n)]))
return x
E_old = []
E_time = []
Dis = []
x = []
for i in range(3):
x.append(data[i])
for k in range(np.shape(x)[0]):
for i in range(np.shape(x)[1]):
for j in range(np.shape(x)[1]):
if x[k][i][j]>0.5:
x[k][i][j]=1
elif x[k][i][j]==0.5:
x[k][i][j]=0
else :
x[k][i][j]=-1
#pict(x[k])
#テスト入力を決定する
x1 = np.copy(x[random.randint(0,np.shape(x)[0]-1)])
#x1 = np.eye(28,k=5)*-1
pict(x1)
#テスト入力にノイズをつける
for i in range(np.shape(x1)[0]):
for j in range(np.shape(x1)[0]):
r = np.sign(random.random()-0.01*noise)
x1[i][j] *= r
pict(x1)
#学習に適当な形式へ変換
x2 =list(range(n))
for k in range(np.shape(x)[0]):
x[k] = np.array(images_to_vectors(x[k]))
x2[k] = np.copy(x[k])
x1 = images_to_vectors(x1)
#学習する
w = np.copy(x1)
x1 = do(fit(w,x),x1,p)
x1 = images_to_vector(x1)
pict(x1)
#エネルギーの推移を表示
show_graph(E_time,E_old)
#各画像との違いの総和の推移を表示
show_graph(E_time,Dis)