离散Hopfield网络

简 介: 第一题是对离散Hopfield网络的构造与回复进行测试。利用外积方法可以很容易计算出DHNN的系数。对于存储的八个字符,在没有噪声的情况下,它们都是DHNN的吸引子。在分别增加10%,20%的噪声下,可以通过迭代将它们恢复。随着增加的噪声增加,恢复的可能性越来越小。在10%,20%的噪声情况下,可以看到,2, 9 都会存在伪吸引子。
关键词 DHNN伪吸引子

01 一题:DHNN

一、题目要求

1、题目内容

  离散Hopfield网络,也被称为联想存储器,通过迭代方式可以增加网络恢复能力。请设计一个离散Hopfield网络,将右边八个字符点阵进行存储。并测试在不同噪声下恢复的情况。

▲ 图1.1.1 八个点阵字符

  在 截取图片中的点阵模式 - 012345.9[2] 通过Python程序将图片转换成对应0101编码字符了。

  下面是字符“0,1,2,3,4,6,.,9”字符对应的10×12的01编码:

000000000000011110000011111100011100111001110011100111001110011100111001110011100111001110001111110000011110000000000000
000111100000011110000001111000000111100000011110000001111000000111100000011110000001111000000111100000011110000001111000
111111110011111111000000001100000000110000000011001111111100111111110011000000001100000000110000000011111111001111111100
001111110000111111100000000110000000011000000001100000111100000011110000000001100000000110000000011000111111100011111100
011000011001100001100110000110011000011001100001100111111110011111111000000001100000000110000000011000000001100000000110
111111000011111100001100000000110000000011000000001111110000111111000011001100001100110000110011000011111100001111110000
111110000011111000001111100000111110000011111000001111100000000000000000000000000000000000000000000000000000000000000000
000011111100001111110000110011000011001100001100110000111111000011111100000000110000000011000000001100001111110000111111

2、题目要求

  1. 通过外积方法建立DHNN网络权系数,并验证上述存储的字符都是DHNN的吸引子。

  2. 测试在原来图片中增加10%,20% 的噪声的情况下,也就是随机选择其中一定比例像素值将其从原来的0修改为1,从1修改0,测试信息恢复情况;

  3. 对于2,6,两个字符,测试在多大噪声情况下,这两个字符就不可以完全恢复了。

  4. 观察在无法恢复的情况下出现的“伪吸引子”的情况。

二、题目求解

1、读取数据显示

(1)显示代码

from headm import *

textid = 3
filename = tspgetdopfile(textid)
printf(filename)

chardim = []
with open(filename, 'r'as f:
    lines = f.readlines()
    for l in lines:
        str01 = [int(c) for c in l if c * '0' or c * '1']
        chardim.append(str01)

def showchar01(c, offsetx=0, offsety=0):
    cc = list(zip(*([iter(c)]*10)))

    x = []
    y = []

    X = []
    Y = []

    for id,a in enumerate(cc):
        YY = offsety+12 - id
        for iidd, b in enumerate(a):
            XX = offsetx+iidd
            if b * 0:
                x.append(XX)
                y.append(YY)
            else:
                X.append(XX)
                Y.append(YY)

    plt.scatter(x, y, s = 1)
    plt.scatter(X, Y, s = 40)

for id, c in enumerate(chardim):
    offsety = 15
    offsetx = id*12
    if id >= 4:
        offsety = 0
        offsetx = (id-4)*12

    showchar01(c, offsetx, offsety)

plt.show()

(2)字符显示

▲ 图1.2.1 显示八个字符

2、计算离散Hopfield网络

  利用外积方法计算离散Hopfield链接权系数矩阵,并将对角线置零。

  在计算外积之前,将原来的 0,1表示的向量转换成 -1,1表示的向量。

(1)计算代码

cca = array(chardim)*2-1
cclen = len(chardim[0])

for id,c in enumerate(cca):
    if id * 0:
        w = outer(c,c)
    else:
        w += outer(c,c)

for i in range(cclen):
    w[(i, i)] = 0

(2)显示权系数矩阵

  计算出的矩阵系数,存储在 w中。

[[ 0  6  4 ... -2 -2  0]
 [ 6  0  6 ...  0  0 -2]
 [ 4  6  0 ...  2 -2 -4]
 ...
 [-2  0  2 ...  0  4  2]
 [-2  0 -2 ...  4  0  6]
 [ 0 -2 -4 ...  2  6  0]]

  利用plt.show()显示矩阵。

▲ 图1.2.2 显示离散Hopfield矩阵

3、测试八个字符恢复

(1)测试代码

#------------------------------------------------------------
plt.clf()

def dhnn(w, x):
    xx = dot(w, x)
    xx01 = [(lambda x: 1 if x > 0 else -1)(a) for a in xx]
    return xx01

#------------------------------------------------------------

for id, c in enumerate(chardim):
    offsety = 15
    offsetx = id*12
    if id >= 4:
        offsety = 0
        offsetx = (id-4)*12

    x = dhnn(w, array(c)*2-1)
    showchar01(x, offsetx, offsety)

plt.show()

(2)测试八个字符恢复结果

  将八个字符分别乘以w,利用符号函数判定之后,便可以获得网络的输出。可以看到这八个字符都是DHNN的吸引子。

▲ 图1.2.3 八个字符经过一次迭代便可以恢复,证明它们都是DHNN的吸引子

4、增加10%噪声

(1)增加噪声

def addnoise(c, noise_ratio = 0.1):
    noisenum = int(len(c) * noise_ratio)
    noisepos = [1]*len(c)
    noisepos[:noisenum] = [-1]*noisenum
    random.shuffle(noisepos)

    cc = array([x*y for x,y in zip(c, noisepos)])
    return cc

plotgif = PlotGIF()

for i in range(50):
    plt.clf()

    for id, c in enumerate(cca):
        offsety = 15
        offsetx = id*12
        if id >= 4:
            offsety = 0
            offsetx = (id-4)*12

        cn = addnoise(c, 0.1)
#        x = dhnn(w, cn)
        showchar01(cn, offsetx, offsety)

    plt.draw()
    plt.pause(.1)
    plotgif.append(plt)

plotgif.save()
▲ 图1.2.4  增加10%的噪声,50个样本情况

(2)经过一次迭代恢复情况

  下面是将增加有10%的样本进行一次DHNN迭代回复的情况。

▲ 图1.2.5  经过一次迭代后恢复的情况

(3)经过两次迭代恢复情况

▲ 图1.2.6  经过两次迭代恢复情况

(4)经过10次迭代恢复情况

def addnoise(c, noise_ratio = 0.1):
    noisenum = int(len(c) * noise_ratio)
    noisepos = [1]*len(c)
    noisepos[:noisenum] = [-1]*noisenum
    random.shuffle(noisepos)

    cc = array([x*y for x,y in zip(c, noisepos)])
    return cc

plotgif = PlotGIF()

for i in range(50):
    plt.clf()

    for id, c in enumerate(cca):
        offsety = 15
        offsetx = id*12
        if id >= 4:
            offsety = 0
            offsetx = (id-4)*12

        cn = addnoise(c, 0.1)
        x = cn
        for _ in range(10):
            x = dhnn(w, x)

        showchar01(x, offsetx, offsety)

    plt.draw()
    plt.pause(.1)
    plotgif.append(plt)

plotgif.save()
▲ 图1.2.7  经过10次迭代恢复情况

5、串行与并行工作

  下面代码分别给出了并行与穿行工作模式。

  • 并行工作模式: dhnn(w,x)
  • 串行工作模式: dhnns(w,x)
def dhnn(w, x):
    xx = dot(w, x)
    xx01 = [(lambda x: 1 if x > 0 else -1)(a) for a in xx]
    return xx01

def dhnns(w, x):
    for i in range(len(x)):
        xx = inner(w[i], x)
        if xx > 0: xx = 1
        else: xx = -1
        x[i] = xx

    return x

  串行工作模式,迭代10次恢复情况:

▲ 图1.2.8  串行工作模式,迭代10次恢复情况

  串行工作模式,迭代100次恢复情况:

▲ 图1.2.9  串行工作模式,迭代100次恢复情况

6、增加20%噪声

  增加20%的噪声利用串行工作模式,迭代100次恢复情况。

▲ 图1.2.10  增加20%的噪声样本情况
▲ 图1.2.10  增加20%的噪声利用串行工作模式,迭代100次恢复情况

7、增加更多的噪声

(1)增加25%噪声

▲ 图A1.2.12  增加25%噪声样本
▲ 图A1.2.13  增加25%噪声样本,串行工作,迭代100次恢复情况

(2)增加30%噪声

▲ 图1.2.14  增加30%噪声样本
▲ 图1.2.15  增加30%噪声样本,串行工作,迭代100次恢复情况

(3)增加50%噪声

▲ 图1.2.12  增加50%的噪声
▲ 图1.2.13  增加50%的噪声,串行工作,迭代100次恢复情况

  通过上面讨论,可以看到:

  • 随着增加的噪声比率越大,回复错误率越高;
  • 使用同步工作,异步工作对应的回复效果很相似。

业总结 ※

  一题是对离散Hopfield网络的构造与回复进行测试。

  利用外积方法可以很容易计算出DHNN的系数。对于存储的八个字符,在没有噪声的情况下,它们都是DHNN的吸引子。

  在分别增加10%,20%的噪声下,可以通过迭代将它们恢复。随着增加的噪声增加,恢复的可能性越来越小。

  在10%,20%的噪声情况下,可以看到,2, 9 都会存在伪吸引子。

参考资料

[1]

2021年人工神经网络第三次作业要求以及参考答案: https://zhuoqing.blog.csdn.net/article/details/121508788

[2]

截取图片中的点阵模式 - 012345.9: https://zhuoqing.blog.csdn.net/article/details/121467190