Hopfield Network python 实现,网络不收敛到学习模式之一

数据挖掘 机器学习 Python 神经网络 循环神经网络
2022-02-22 12:25:58

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

它应该学习的 10 个图像

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

在此处输入图像描述

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

在此处输入图像描述

这是我尝试实现 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")

非常感谢任何有关网络为何以这种方式运行以及可以采取哪些措施来解决此问题的帮助。

0个回答
没有发现任何回复~