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.
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).
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).
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.
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.
\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.
\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.
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}
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}
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
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}
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
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
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
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.
[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