[GO] Essayez d'implémenter la mémoire associative par hop field network en Python

introduction

Le réseau Hopfield a été proposé par le physicien américain Hopfield au début des années 1980. Hopfield a introduit le concept d'énergie dans les réseaux de neurones. De plus, il a montré qu'elle pouvait s'appliquer non seulement à la mémoire associative mais aussi à des problèmes d'optimisation comme le problème du voyageur de commerce. ** Ici, nous traiterons de la mémoire associative. ** Faites en sorte que le réseau de neurones mémorise le schéma (processus de mémorisation) et vous le rappelle (processus de rappel). Plus précisément, intégrez l'image en noir et blanc suivante (la chaîne de caractères n'a pas de signification particulière) dans le réseau neuronal et donnez-lui un motif bruyant pour vous le rappeler.

image.png

Si vous définissez le motif bruyant comme motif initial (image de gauche ci-dessous) et répétez la mise à jour, le motif de mémoire sera rappelé (image de droite ci-dessous). image.pngimage.png

J'ai implémenté la mémoire associative en Python. Si vous avez un compte Google, vous pouvez le faire immédiatement depuis ici (Google Colab).

Modèle [1] [2]

La structure du réseau de champ de saut est la suivante (pour 5 neurones): Les deux flèches représentent les interconnexions. La figure ci-dessous est une structure qui ne considère pas l'auto-adhésion. HopfieldNetWork.png

Processus de mémorisation

Le modèle est mémorisé en modifiant la charge de connexion du réseau neuronal. Le motif est représenté par le vecteur $ \ boldsymbol {x} = (x_1, ..., x_N) (x_i: 1 \ leqq i \ leqq N) $. $ N $ est le nombre de neurones (nombre d'unités). $ P $ nombre de vecteurs à stocker (\ boldsymbol {x} ^ {(1)}, ..., \ boldsymbol {x} ^ {(P)}) (\ boldsymbol {x} ^ {(k) }: 1 \ leqq k \ leqq P) $ Quand il y en a, dans une matrice

X
=
\begin{bmatrix}
\boldsymbol{x}^{(1)} \\
\vdots \\
\boldsymbol{x}^{(P)}
\end{bmatrix}
=
\begin{bmatrix}
x_1^{(1)} & \cdots & x_N^{(1)} \\
\vdots & \ddots & \vdots \\
x_1^{(P)} & \cdots & x_N^{(P)}
\end{bmatrix}
(Matrice P × N)
\tag{1}

Il est exprimé comme. Le motif que vous souhaitez mémoriser est appelé un motif mémorisé. Une fois le modèle de stockage prêt, nous l'intégrerons dans le réseau neuronal. Lorsque vous le mémorisez, demandez-leur de s'en souvenir un par un. La charge de couplage est modifiée chaque fois qu'un modèle est appliqué au réseau neuronal. La charge de connexion $ w_ {ij} $ qui relie le neurone $ i $ au neurone $ j $ change de $ \ Delta w $ dans l'équation suivante.

x_i ^ {(k)} = 0,1 \ hspace {10pt} (1 \ leqq i \ leqq N, 1 \ leqq k \ leqq P)
\Delta w = (2x_i^{(k)} - 1)(2x_j^{(k)} - 1) \tag{2}

L'équation (2) est lorsque l'élément du vecteur de motif à incorporer est une valeur binaire de 1 ou 0. Si les éléments du vecteur de motif sont -1,0,1, $ \ Delta w $ devient la formule suivante.

x_i ^ {(k)} = -1,0,1 \ hspace {10pt} (1 \ leqq i \ leqq N, 1 \ leqq k \ leqq P)
\Delta w = x_i^{(k)} x_j^{(k)} \tag{3}

Les équations ci-dessus (2) et (3) sont des règles d'apprentissage appelées ** loi de Heb **. La charge de connexion entre les neurones avec la même sortie est augmentée et la charge de connexion entre les neurones avec des sorties différentes est affaiblie. Lorsque le nombre de neurones est $ N $, il y a $ N × N $ de charge de connexion $ w_ {ij} $. Si le motif préparé dans l'équation (1) est incorporé dans les équations (2) et (3), la charge combinée $ W $ sous forme de matrice peut être exprimée comme dans l'équation suivante.

x_i ^ {(k)} = 0,1 \ hspace {10pt} (1 \ leqq i \ leqq N, 1 \ leqq k \ leqq P)
W
=
\begin{bmatrix}
w_{11} & \cdots & w_{1N} \\
\vdots & \ddots & \vdots \\
w_{N1} & \cdots & w_{NN}
\end{bmatrix}
=
(2X-1)^T(2X-1)
\hspace{10pt}
(Matrice N × N)
\tag{4}
x_i ^ {(k)} = -1,0,1 \ hspace {10pt} (1 \ leqq i \ leqq N, 1 \ leqq k \ leqq P)
W
=
\begin{bmatrix}
w_{11} & \cdots & w_{1N} \\
\vdots & \ddots & \vdots \\
w_{N1} & \cdots & w_{NN}
\end{bmatrix}
=
X^TX
\hspace{10pt}
(Matrice N × N)
\tag{5}

Processus de recollection

Le processus de rappel commence par définir n'importe quel modèle d'entrée $ \ boldsymbol {x '} = (x_1', ..., x_N ') $ comme état initial du réseau neuronal. Ce modèle d'entrée $ \ boldsymbol {x '} $ est appelé le modèle initial. La distance de bourdonnement est utilisée pour montrer à quel point le modèle initial et le modèle de mémoire sont différents. Voici la définition de la distance de bourdonnement $ d $ pour le modèle de stockage $ \ boldsymbol {x} $ et le modèle initial $ \ boldsymbol {x '} $. Dans le cas de $ x_i ^ {(k)} = -1,0,1 , 1/2 est ajouté à la formule suivante. $ x_i ^ {(k)} = 0,1 \ hspace {10pt} (1 \ leqq i \ leqq N, 1 \ leqq k \ leqq P) $$

d = \sum_{i=1}^N |x_i - x_i'| \tag{6}

Après avoir réglé le motif initial sur l'état initial, répétez les étapes de mise à jour suivantes ① et ② le nombre de fois spécifié. ① Sélectionnez au hasard un neurone $ m $ parmi les neurones. Ensuite, trouvez la sortie $ y_m (t) $ du neurone $ m $.

s(u):Fonction Step\\
s(u) = \left\{
\begin{array}{ll}
1 & (u > 0) \\
0 & (u \leqq 0)
\end{array}
\right. \hspace{10pt}
Ou\hspace{10pt}
s(u) = \left\{
\begin{array}{lll}
1 & (u > 0) \\
0 & (u = 0) \\
-1 & (u < 0)
\end{array}
\right. \\
\boldsymbol{w_m}:Charge de liaison au neurone m\\
b_m:Biais (seuil, seuil)
y_m(t)=s(u)=s(\boldsymbol{x} \boldsymbol{w_m} + b_m) \tag{7}

(2) Mettre à jour l'état suivant $ y_m (t + 1) $ du neurone $ m $ à la valeur obtenue par l'équation (7). A part le neurone $ m $, il reste inchangé.

y_m(t+1)←y_m(t) \tag{8}

Cette méthode de mise à jour d'un seul neurone est appelée mise à jour asynchrone. Le réseau Hopfield semble faire référence à des mises à jour asynchrones. Il a été théoriquement démontré que l'énergie du réseau ne cesse de baisser à mesure que les mises à jour se répètent. L'énergie est définie comme suit.

E(t) = -\frac{1}{2} \sum_{i=1}^N \sum_{j=1}^N w_{ij}x_i(t)x_j(t) - \sum_{j=1}^N b_jx_j(t) \tag{9}

Classes et fonctions

Pattern: une classe qui lit les modèles.

weight_cal1 (X): Définit la charge de couplage lorsque l'élément du vecteur de motif est 0,1. weight_cal2 (X): Définit la charge de couplage lorsque l'élément du vecteur de motif est -1,0,1. hamming (ptn_vec1, ptn_vec2): Renvoie la distance de bourdonnement des deux vecteurs de motif donnés dans l'argument. set_ptn_vec1 (ptn_vec, difference_rate): Fonction de génération de motif initiale lorsque l'élément du vecteur de motif est 0,1. set_ptn_vec2 (ptn_vec, difference_rate): Fonction de génération de motif initiale lorsque les éléments du vecteur de motif sont -1,0,1. step_function1 (x): Une fonction pas à pas qui renvoie 0,1. Une fonction pas à pas qui renvoie step_function2 (x): -1,0,1. sync (ptn_vec, weight, bias, func): Une fonction qui effectue des mises à jour synchrones. ʻAsync (ptn_vec, weight, bias, func) : Une fonction qui effectue des mises à jour asynchrones. ʻEnergy_cal (sortie, poids, biais) : Calcule l'énergie du réseau neuronal. display_pattern (ptn_vec): Affiche le vecteur de motif donné à l'argument à l'écran. display_pattern_all (ptn): Affiche tous les modèles donnés dans l'argument à l'écran.

Les trois modules suivants sont utilisés.

HopfieldNetwork.ipynb


import numpy as np
import random
import matplotlib.pyplot as plt

Entraine toi

Tout d'abord, lisez le modèle et réglez la charge d'accouplement.

HopfieldNetwork.ipynb


ptn = np.array([[0, 0, 0, 1, 1, 0, 0, 0, 
                 0, 0, 1, 1, 1, 1, 0, 0, 
                 0, 0, 1, 0, 0, 1, 0, 0, 
                 0, 1, 1, 0, 0, 1, 1, 0, 
                 0, 1, 1, 1, 1, 1, 1, 0, 
                 1, 1, 1, 1, 1, 1, 1, 1, 
                 1, 1, 0, 0, 0, 0, 1, 1, 
                 1, 0, 0, 0, 0, 0, 0, 1],
                [0, 0, 0, 0, 0, 0, 0, 0, 
                 1, 1, 0, 0, 0, 0, 1, 1, 
                 1, 1, 0, 0, 0, 0, 1, 1, 
                 1, 1, 1, 1, 1, 1, 1, 1, 
                 1, 1, 1, 1, 1, 1, 1, 1, 
                 1, 1, 0, 0, 0, 0, 1, 1, 
                 1, 1, 0, 0, 0, 0, 1, 1, 
                 0, 0, 0, 0, 0, 0, 0, 0],
                [1, 1, 1, 1, 1, 1, 1, 1, 
                 1, 1, 1, 1, 1, 1, 1, 1, 
                 1, 0, 0, 1, 1, 0, 0, 1, 
                 0, 0, 0, 1, 1, 0, 0, 0, 
                 0, 0, 0, 1, 1, 0, 0, 0, 
                 0, 0, 0, 1, 1, 0, 0, 0, 
                 0, 0, 0, 1, 1, 0, 0, 0, 
                 0, 0, 1, 1, 1, 1, 0, 0]])

#Modèle de charge
row = column = 8
pattern = Pattern(row, column, ptn)
#Afficher le motif chargé
display_pattern_all(pattern.X)
#Déterminer la charge de liaison
weight = weight_cal1(pattern.X)
#Tous les biais sont 0
bias = np.zeros(pattern.unit)

Résultat d'exécution image.png

Ensuite, rappelons le cas de k = 1. La distance de bourdonnement entre le motif de mémoire et le motif initial a été réglée sur 10.

HopfieldNetwork.ipynb


%%time
#Définir la limite supérieure du nombre de mises à jour
time = 1000
#Sélectionnez un motif
k = 1
#Générer un motif initial
hamming_distance = 10
ini_ptn_vec = set_ptn_vec1(pattern.X[k-1], hamming_distance/pattern.unit)
#Afficher le modèle initial
print("Modèle initial")
display_pattern(ini_ptn_vec)
#Énergie du motif initial
energy = []
energy.append(energy_cal(ini_ptn_vec, weight, bias))
#Continuez à mettre à jour jusqu'à 1000 fois
for i in range(time):
    #Mise à jour asynchrone
    async(ini_ptn_vec, weight, bias, step_function1)
    #Ajoutez de l'énergie dans le processus de mise à jour de la liste
    energy.append(energy_cal(ini_ptn_vec, weight, bias))
    #Quittez la boucle si vous pouvez rappeler le motif mémoire
    if(hamming(ini_ptn_vec, pattern.X[k-1]) == 0):
        print("Nombre de temps de mise à jour=", i)
        break
#Afficher le motif qui a finalement été rappelé
print("Motif rappelé")
display_pattern(ini_ptn_vec)

Résultat d'exécution

Vérifiez la transition de l'énergie ajoutée à «énergie».

HopfieldNetwork.ipynb


plt.plot(energy)
plt.ylabel("energy", fontsize=18)
plt.xlabel("time", fontsize=18)
plt.show()

Résultat d'exécution image.png

Pour le moment, le flux de mémoire associative par le réseau de champ de saut est tel que décrit ci-dessus. À une date ultérieure, j'aimerais publier quelques expériences.

Les références

[1] Hopfield, J.J. (1982): “Neural networks and physical systems with emergent collective computational abilities”, Proc. Natl. Sci. USA, 79, 2554-2558. [2] Kaoru Nakano et al. (1990): Fundamentals of Neurocomputer Corona

Recommended Posts

Essayez d'implémenter la mémoire associative par hop field network en Python
Implémentons Yuma dans Python 3
Essayez de travailler avec des données binaires en Python
Essayez d'implémenter deux piles en Python sur un seul tableau
Essayez de travailler avec Mongo en Python sur Mac
Essayez d'implémenter la méthode Monte Carlo en Python
Essayez de gratter avec Python.
Essayez gRPC en Python
Essayez 9 tranches en Python
Essayez d'implémenter Yuma avec Brainf * ck 512 lignes (générer et exécuter du code avec Python)
Essayez d'incorporer Python dans un programme C ++ avec pybind11
Grattage au sélénium en Python
Exploitez LibreOffice avec Python
Essayez d'implémenter RBM avec chainer.
Grattage avec chromedriver en python
Réseau de neurones avec Python (scikit-learn)
Débogage avec pdb en Python
Essayez la sortie Python avec Haxe 3.2
Essayez d'implémenter XOR avec PyTorch
Gérer les sons en Python
Grattage avec du sélénium en Python
Essayez LINE Notify avec Python
Grattage avec Tor en Python
Tweet avec image en Python
Combiné avec ordinal en Python
Essayez d'exécuter Python avec Try Jupyter
Essayez d'implémenter le parfum avec Go
Implémentation de réseau neuronal en python
Essayez la reconnaissance faciale avec Python
Programmation réseau avec Python Scapy
Essayez d'exécuter python dans l'environnement Django créé avec pipenv
Essayez de gratter les données COVID-19 Tokyo avec Python
Essayez de trier vos propres objets avec des files d'attente prioritaires en Python
Essayez d'automatiser le fonctionnement des périphériques réseau avec Python
Essayez de créer un réseau de neurones en Python sans utiliser de bibliothèque
Reconnaissance des nombres dans les images avec Python
Rechercher les fuites de mémoire dans Python
Essayez de gratter avec Python + Beautiful Soup
Tester avec des nombres aléatoires en Python
Réseau neuronal avec OpenCV 3 et Python 3
GOTO en Python avec Sublime Text 3
[Python] Générer un code QR en mémoire
Travailler avec LibreOffice en Python: import
Mesure de retard unidirectionnelle du réseau par python
Analyse CSS avec cssutils en Python
Essayez d'exploiter Facebook avec Python
Essayez la décomposition de valeurs singulières avec Python
Numer0n avec des objets fabriqués avec Python
Essayez d'utiliser LevelDB avec Python (plyvel)
Ouvrez UTF-8 avec BOM en Python
Essayons Fizz Buzz avec Python
Essayez de calculer Trace en Python
Essayez l'accès au registre PLC en Python
Utiliser rospy avec virtualenv dans Python3
Essayez la reconnaissance faciale avec python + OpenCV
Utiliser Python mis en pyenv avec NeoVim
Heatmap avec dendrogramme en Python + matplotlib