Python Hopfield网络实现不需要';t收敛到所学的模式之一

Python Hopfield网络实现不需要';t收敛到所学的模式之一,python,machine-learning,neural-network,artificial-intelligence,Python,Machine Learning,Neural Network,Artificial Intelligence,我正在尝试使用NumPy库在python中实现Hopfield网络。网络有2500个节点(50高x 50宽)。网络从存储在“patterns”文件夹中的大小为50x50的图像中学习10种图案。这些图像是数字0到9。图像转换为2d阵列,展平为1d(2500x1)并学习 在学习模式之后,它会得到一系列图像(我从中删除了一些像素),以匹配存储的模式。但我面临的问题是,它不会收敛到某个存储模式,而是输出某种随机的东西 即使我试着输入它所学的其中一个模式的精确模式,它仍然不会收敛到那个模式。 下面是

我正在尝试使用NumPy库在python中实现Hopfield网络。网络有2500个节点(50高x 50宽)。网络从存储在“patterns”文件夹中的大小为50x50的图像中学习10种图案。这些图像是数字0到9。图像转换为2d阵列,展平为1d(2500x1)并学习

在学习模式之后,它会得到一系列图像(我从中删除了一些像素),以匹配存储的模式。但我面临的问题是,它不会收敛到某个存储模式,而是输出某种随机的东西

即使我试着输入它所学的其中一个模式的精确模式,它仍然不会收敛到那个模式。

下面是我尝试实现Hopfield网络的代码

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import image
from os import listdir
import random
from os.path import isfile, join

# Hopefiel Network parameters
input_width = 50
input_height = 50
number_of_nodes = input_width * input_height
learning_rate = 1

# initialise node/input array to -1, and weights array to 0
input = np.zeros((number_of_nodes))
input[True] = -1
weights = np.zeros((number_of_nodes,number_of_nodes))

#*******************************
# Main Hopefield Functions
#********************************
# Randomly fire nodes until the overall output doesn't change
# match the pattern stored in the Hopefield Net.
def calculate_output(input, weights):
    changed = True
    while changed:
        indices = list(range(len(input)))
        random.shuffle(indices)
        new_input = np.zeros((number_of_nodes))
        
        clamped_input = input.clip(min=0) # eliminate nodes with negative value, doesn't work either way
        for i in indices:
            sum = np.dot(weights[i], clamped_input)
            new_input[i] = 1 if sum >= 0 else -1
            changed = not np.allclose(input[i], new_input[i], atol=1e-3)
        input = np.array(new_input)
    
    return np.array(input)
            
# activation(W x I) = Output
# match the pattern stored in the Hopefield Net.
def calculate_output_2(input, weights):
    output = np.dot(weights,input)
    # apply threshhold
    output[output >= 0] = 1 # green in image
    output[output < 0] = -1 # purple in image
    return output


# Store the patterns in the Hopfield Network
def learn(input, weights):
    I = np.identity(number_of_nodes) # diagnol will always be 1 if input is only 1/-1
    updates = learning_rate * np.outer(input,input) - I
    updates = updates/number_of_nodes
    weights[:] = weights + updates



#*******************************
# Misc. Functions
#*******************************
# plot an array and show on the screen
def show_array(arr):
    data = arr.reshape((-1, input_width))
    plt.imshow(data) # plotting by columns
    plt.show()
    
# learn the patterns (images) placed in "patterns" folder (images of numbers 0-9)
def learn_numbers():
    for f in listdir("patterns/"):
        file = join("patterns/", f)
        if isfile(file):
            print(file)
            im = image.imread(file)
            grey = im[:,:,0] # convert to 2d array from 3channel rgb image
            grey = np.where(grey==1,-1,1) # convert white pixel to -1 and otherwise (black) to 1
            learn(grey.flatten(), weights) # convert 2d image to 1d array (2500) and store in weights

# read a test image and match the nearest pattern
def calculate_img_output(weights, image_address):
    # show the image being tested
    im = image.imread(image_address)
    grey = im[:,:,0] # convert to 2d array from 3channel rgb image
    grey = np.where(grey==1,-1,1) # convert white pixel to -1 and otherwise (black) to 1
    plt.imshow(grey) # plotting by columns
    plt.show()
    
    # retrieve the pattern using random firing
    output = calculate_output(grey.flatten(), weights)
    # show the pattern
    show_array(output)
    
    # retrieve the pattern
    output = calculate_output_2(grey.flatten(), weights)
    # show the pattern
    show_array(output)
    
    
#****************************    
# Testing code
#*****************************

    
# learn the patterns of image of number 0-9
learn_numbers()
# Try to match the partial pattern
calculate_img_output(weights, "partial/p.png")
将numpy导入为np
将matplotlib.pyplot作为plt导入
从matplotlib导入图像
从操作系统导入listdir
随机输入
从os.path导入isfile,加入
#Hopefiel网络参数
输入宽度=50
输入高度=50
节点数=输入宽度*输入高度
学习率=1
#将节点/输入数组初始化为-1,将数组权重初始化为0
输入=np.0((节点数))
输入[真]=-1
权重=np.0((节点数,节点数))
#*******************************
#主要Hopefield函数
#********************************
#随机激发节点,直到总体输出不变
#匹配存储在Hopefield网络中的图案。
def计算输出(输入、重量):
更改=真
更改时:
索引=列表(范围(长度(输入)))
随机。随机(索引)
新输入=np.0((节点数))
钳制_input=input.clip(min=0)#消除具有负值的节点,两种方式都不起作用
对于指数中的i:
总和=np.点(权重[i],钳制输入)
如果总和>=0,则新输入[i]=1,否则为-1
更改=非np.ALLCOSE(输入[i],新输入[i],atol=1e-3)
输入=np.数组(新输入)
返回np.array(输入)
#激活(W x I)=输出
#匹配存储在Hopefield网络中的图案。
def计算输出(输入、权重):
输出=np.点(权重,输入)
#打谷
输出[输出>=0]=1#图像中为绿色
输出[输出<0]=-1#图像中的紫色
返回输出
#将模式存储在Hopfield网络中
def读入(输入、重量):
I=np.identity(节点数)#如果输入仅为1/-1,则diagnol将始终为1
更新=学习率*np.外部(输入,输入)-I
更新=更新/节点数
权重[:]=权重+更新
#*******************************
#杂项。功能
#*******************************
#绘制阵列并在屏幕上显示
def显示_阵列(arr):
数据=arr.reformate((-1,输入宽度))
plt.imshow(数据)#按列绘制
plt.show()
#学习放置在“模式”文件夹中的模式(图像)(数字0-9的图像)
def学习_数字():
对于listdir中的f(“模式/”):
file=join(“patterns/”,f)
如果是isfile(文件):
打印(文件)
im=image.imread(文件)
灰色=im[:,:,0]#从3通道rgb图像转换为二维阵列
灰色=np。其中(灰色==1,-1,1)#将白色像素转换为-1,否则(黑色)转换为1
学习(grey.flatte(),权重)#将2d图像转换为1d数组(2500)并存储在权重中
#读取测试图像并匹配最近的模式
def计算图像输出(权重、图像地址):
#显示正在测试的图像
im=image.imread(图像地址)
灰色=im[:,:,0]#从3通道rgb图像转换为二维阵列
灰色=np。其中(灰色==1,-1,1)#将白色像素转换为-1,否则(黑色)转换为1
plt.imshow(灰色)#按列绘制
plt.show()
#使用随机触发检索模式
输出=计算输出(grey.flatte(),权重)
#显示模式
显示数组(输出)
#检索模式
输出=计算输出(灰色.flatte(),权重)
#显示模式
显示数组(输出)
#****************************    
#测试代码
#*****************************
#学习数字0-9的图像模式
学习数字
#尝试匹配部分模式
计算输出(权重,“部分/p.png”)
非常感谢您提供有关网络为何会出现这种情况以及如何解决此问题的任何帮助。

请不要对代码段(已编辑)同时使用反引号和缩进。