[学习笔记] Hebb 学习规则和Hopfield网络

Hebb 学习规则和Hopfield网络

Hebb学习规则

Hebb学习规则是Donald Hebb在1949年提出的一种学习规则,用来描述神经元的行为是如何影响神经元之间的连接的,通俗的说,就是如果相链接的两个神经元同时被激活,显然我们可以认为这两个神经元之间的关系应该比较近,因此将这两个神经元之间连接的权值增加,而一个被激活一个被抑制,显然两者间的权值应该减小。

此外,Hebb还有一句非常注明的话,我在很多资料中都见到这句话的引用:“neurons that fire together, wire together”,这句话就是对权值如何更新的一个解释,同被激活者连接的权重理应增加。

公式表示为:
\[ W_{ij}(t+1) := W_{ij}(t) + \alpha \times x_i \times x_j \]
即表明神经元xi和xj的连接权重由两者输出决定。

尽管已经给出了生物学上的解释(或者说是启发),但其实仅看这么一个公式是不可能完全理解的,需要一个例子来说明,到底什么网络才需要这样的权值更新。

下面将以Hopfield网络为例说明这种权值更新的具体实现。

Hopfield 网络

定义和作用

Hopfield网络是一个有向完全图(仅仅以我看到的资料去定义,并非严谨或者官方定义),是一种递归神经网络。有向完全图可以理解,每两个节点之间都有连接,递归即一个输入经过多次训练最终收敛。本文仅讨论离散Hopfield网络,即节点取值为离散的。

Hopfield网络的作用是:存储一个或更多的patterns,并且能够根据任意的输入从存储的这些patterns中将对应的原始数据还原。例如,我们的任务是一个手写数字分类,我们将数字1对应的图片作为一种pattern让网络存储起来,如果将数字1遮挡一半,我们希望网络利用存储的记忆将这个数字1恢复,并得到最接近的pattern,也就完成了一个分类任务。

训练

定义输入\(x_i\)为第i个神经元节点的值,\(W_{ij}\)为第i个和第j和节点之间的权值,则每个样本作为节点初始化的权值\(W_{ij}\)定义为:
\[ W_{ij} = x_i \times x_j \]
则N个样本的权值经过N次更新为:
\[ W_{ij}(N) = \sum_{n=1}^N x_i(n) \times x_j(n) \]
因此训练阶段很简单,仅仅是将所有样本的信息以权值求和的形式存储起来,因此,最终的权值存储的是每个样本的记忆,而测试阶段是需要利用这些权值恢复记忆。

测试

测试阶段先用测试样本初始化节点,利用训练阶段存储的权值,循环随机选择一个节点\(x_i\),将节点值根据下式更新:
\[ x_i = sgn(\sum_{j=1}^N W_{ji} \times x_j) \]
经过若干iter,则所有节点会收敛到一个合适的值。

Coding

以一张二值图为输入,将每个像素值定义为-1或+1,来初始化节点,探究遮挡一般图片时利用Hopfied网络恢复图像。

原图:

masked:

恢复的(iter = 10):

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
class Hopfield():
    def __init__(self,size = 64,iter = 10):
        self.iter = iter
        self.size = size
        self.W = np.zeros((size**2,size**2))
        
    def train(self,X): 
        n = self.size**2
        for x in X: # (-1,64*64)
            x = np.reshape(x,(n,))
            for i in range(n):
                for j in range(n):
                    if not(i==j):
                        self.W[i,j] += x[i] * x[j] / n
    def test_one_frame(self,x):
        n = self.size **2
        x = np.reshape(x,(n,))
        for iter in range(self.iter):
            h = np.zeros((n,))
            for i in range(n):
                i = np.random.randint(n)
                h[i] += self.W[i,:].dot(x)
            x = np.where(h>0,1,-1)
        return np.resize(x,(self.size,self.size))
def show(x):
    img = np.where(x >0,255,0).astype(np.uint8)
    cv.imshow("img",img)
    cv.waitKey(0)

if __name__ =="__main__":
    img = cv.imread("/home/xueaoru/图片/摄像头/handsome_boy.jpg",0)
    
    img = cv.resize(img,(64,64))
    x = np.where(img>255/2.5,1,-1)
    x_masked = x.copy()
    x_masked[64//2:,:] = -1
    #show(x_masked)
    model = Hopfield()
    model.train([x])
    y = model.test_one_frame(x_masked)
    show(y)

猜你喜欢

转载自www.cnblogs.com/aoru45/p/12443104.html