Das Hopfield Network wurde Anfang der 1980er Jahre vom amerikanischen Physiker Hopfield vorgeschlagen. Hopfield führte das Konzept der Energie in neuronale Netze ein. Darüber hinaus zeigte er, dass es nicht nur auf das assoziative Gedächtnis angewendet werden kann, sondern auch auf Optimierungsprobleme wie das Problem des Handlungsreisenden. ** Hier beschäftigen wir uns mit dem assoziativen Gedächtnis. ** Lassen Sie das neuronale Netzwerk das Muster auswendig lernen (Speicherprozess) und Sie daran erinnern (Erinnerungsprozess). Betten Sie das folgende Schwarzweißbild (die Zeichenfolge hat keine besondere Bedeutung) in das neuronale Netzwerk ein und geben Sie ihm ein verrauschtes Muster, um Sie daran zu erinnern.
Wenn Sie das verrauschte Muster als Ausgangsmuster festlegen (linkes Bild unten) und die Aktualisierung wiederholen, wird das Speichermuster abgerufen (rechtes Bild unten).
Ich habe assoziatives Gedächtnis in Python implementiert. Wenn Sie ein Google-Konto haben, können Sie dies sofort von [hier (Google Colab)] aus tun (https://colab.research.google.com/drive/1IYHOElNxQCCHHyjmpw5-n4p0CZ3srE_t?usp=sharing).
Die Struktur des Hopfenfeldnetzwerks ist wie folgt (für 5 Neuronen): Beide Pfeile stehen für Verbindungen. Die folgende Abbildung ist eine Struktur, die keine Selbstverbindung berücksichtigt.
Das Muster wird durch Ändern der Verbindungslast des neuronalen Netzwerks gespeichert. Das Muster wird durch den Vektor $ \ boldsymbol {x} = (x_1, ..., x_N) (x_i: 1 \ leqq i \ leqq N) $ dargestellt. $ N $ ist die Anzahl der Neuronen (Anzahl der Einheiten). $ P $ Anzahl der zu speichernden Vektoren (\ boldsymbol {x} ^ {(1)}, ..., \ boldsymbol {x} ^ {(P)}) (\ boldsymbol {x} ^ {(k) }: 1 \ leqq k \ leqq P) $ Wenn vorhanden, in einer Matrix
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}
(P × N-Matrix)
\tag{1}
Es wird ausgedrückt als. Das Muster, das Sie sich merken möchten, wird als gespeichertes Muster bezeichnet. Sobald das Speichermuster fertig ist, werden wir es in das neuronale Netzwerk einbetten. Wenn Sie es auswendig lernen, bitten Sie sie, sich eins nach dem anderen daran zu erinnern. Die Kopplungslast wird jedes Mal geändert, wenn ein Muster auf das neuronale Netzwerk angewendet wird. Die Verbindungslast $ w_ {ij} $, die das Neuron $ i $ mit dem Neuron $ j $ verbindet, ändert sich in der folgenden Gleichung um $ \ Delta w $.
\Delta w = (2x_i^{(k)} - 1)(2x_j^{(k)} - 1) \tag{2}
Gleichung (2) ist, wenn das Element des einzubettenden Mustervektors ein Binärwert von 1 oder 0 ist. Wenn die Elemente des Mustervektors -1,0,1 sind, wird $ \ Delta w $ zur folgenden Formel.
\Delta w = x_i^{(k)} x_j^{(k)} \tag{3}
Die obigen Gleichungen (2) und (3) sind Lernregeln, die als ** Hebbsche Regel ** bezeichnet werden. Die Bindungslast zwischen Neuronen mit derselben Leistung wird erhöht und die Bindungslast zwischen Neuronen mit unterschiedlichen Ausgaben wird geschwächt. Wenn die Anzahl der Neuronen $ N $ beträgt, gibt es $ N × N $ der Verbindungslast $ w_ {ij} $. Wenn das in Gleichung (1) hergestellte Muster in die Gleichungen (2) und (3) eingebettet ist, kann die kombinierte Last $ W $ in Matrixform wie in der folgenden Gleichung ausgedrückt werden.
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}
(N × N-Matrix)
\tag{4}
W
=
\begin{bmatrix}
w_{11} & \cdots & w_{1N} \\
\vdots & \ddots & \vdots \\
w_{N1} & \cdots & w_{NN}
\end{bmatrix}
=
X^TX
\hspace{10pt}
(N × N-Matrix)
\tag{5}
Der Rückrufvorgang beginnt mit dem Festlegen eines beliebigen Eingabemusters $ \ boldsymbol {x '} = (x_1', ..., x_N ') $ als Anfangszustand des neuronalen Netzwerks. Dieses Eingabemuster $ \ boldsymbol {x '} $ wird als Anfangsmuster bezeichnet. Der Brummabstand wird verwendet, um zu zeigen, wie unterschiedlich das Anfangsmuster und das Speichermuster sind. Nachfolgend finden Sie die Definition des Brummabstands $ d $ für das Speichermuster $ \ boldsymbol {x} $ und das Anfangsmuster $ \ boldsymbol {x '} $. Im Fall von $ x_i ^ {(k)} = -1,0,1 $ wird 1/2 zu der folgenden Formel hinzugefügt.
d = \sum_{i=1}^N |x_i - x_i'| \tag{6}
Wiederholen Sie die folgenden Aktualisierungsschritte ① und ② so oft, nachdem Sie das Anfangsmuster in den Anfangszustand versetzt haben. ① Wählen Sie zufällig ein Neuron $ m $ aus den Neuronen aus. Als nächstes finden Sie die Ausgabe $ y_m (t) $ des Neurons $ m $.
s(u):Stufenfunktion\\
s(u) = \left\{
\begin{array}{ll}
1 & (u > 0) \\
0 & (u \leqq 0)
\end{array}
\right. \hspace{10pt}
Oder\hspace{10pt}
s(u) = \left\{
\begin{array}{lll}
1 & (u > 0) \\
0 & (u = 0) \\
-1 & (u < 0)
\end{array}
\right. \\
\boldsymbol{w_m}:Bindungslast an Neuron m\\
b_m:Bias (Schwelle, Schwelle)
y_m(t)=s(u)=s(\boldsymbol{x} \boldsymbol{w_m} + b_m) \tag{7}
(2) Aktualisiere den nächsten Zustand $ y_m (t + 1) $ des Neurons $ m $ auf den durch Gleichung (7) erhaltenen Wert. Anders als das Neuron $ m $ bleibt es unverändert.
y_m(t+1)←y_m(t) \tag{8}
Diese Methode zum Aktualisieren nur eines Neurons wird als asynchrone Aktualisierung bezeichnet. Das Hopfield-Netzwerk scheint sich auf asynchrone Updates zu beziehen. Es wurde theoretisch gezeigt, dass die Energie des Netzwerks weiter sinkt, wenn die Aktualisierungen wiederholt werden. Energie ist wie folgt definiert.
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
: Eine Klasse, die Muster liest.
weight_cal1 (X)
: Legt die Kopplungslast fest, wenn das Element des Mustervektors 0,1 ist.
weight_cal2 (X)
: Legt die Kopplungslast fest, wenn das Element des Mustervektors -1,0,1 ist.
hamming (ptn_vec1, ptn_vec2)
: Gibt den Brummabstand der beiden im Argument angegebenen Mustervektoren zurück.
set_ptn_vec1 (ptn_vec, different_rate)
: Funktion zur anfänglichen Mustererzeugung, wenn das Element des Mustervektors 0,1 ist.
set_ptn_vec2 (ptn_vec, different_rate)
: Funktion zur anfänglichen Mustererzeugung, wenn die Elemente des Mustervektors -1,0,1 sind.
Eine Schrittfunktion, die step_function1 (x)
zurückgibt: 0,1.
Eine Schrittfunktion, die step_function2 (x)
zurückgibt: -1,0,1.
sync (ptn_vec, weight, Bias, func)
: Eine Funktion, die synchrone Aktualisierungen durchführt.
async (ptn_vec, weight, Bias, func)
: Eine Funktion, die asynchrone Aktualisierungen durchführt.
energy_cal (Ausgabe, Gewicht, Vorspannung)
: Berechnet die Energie des neuronalen Netzwerks.
display_pattern (ptn_vec)
: Gibt den Mustervektor, der dem Argument gegeben wurde, auf dem Bildschirm aus.
display_pattern_all (ptn)
: Gibt alle im Argument angegebenen Muster auf dem Bildschirm aus.
Die folgenden drei Module werden verwendet.
HopfieldNetwork.ipynb
import numpy as np
import random
import matplotlib.pyplot as plt
Lesen Sie zuerst das Muster und stellen Sie die Kopplungslast ein.
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]])
#Lademuster
row = column = 8
pattern = Pattern(row, column, ptn)
#Zeigen Sie das geladene Muster an
display_pattern_all(pattern.X)
#Bestimmen Sie die Bindungslast
weight = weight_cal1(pattern.X)
#Alle Vorurteile sind 0
bias = np.zeros(pattern.unit)
Ausführungsergebnis
Als nächstes erinnern wir uns an den Fall von k = 1. Der Brummabstand zwischen dem Speichermuster und dem Anfangsmuster wurde auf 10 eingestellt.
HopfieldNetwork.ipynb
%%time
#Legen Sie die Obergrenze für die Anzahl der Aktualisierungen fest
time = 1000
#Wählen Sie ein Muster
k = 1
#Anfangsmuster erzeugen
hamming_distance = 10
ini_ptn_vec = set_ptn_vec1(pattern.X[k-1], hamming_distance/pattern.unit)
#Anfangsmuster anzeigen
print("Anfangsmuster")
display_pattern(ini_ptn_vec)
#Anfängliche Musterenergie
energy = []
energy.append(energy_cal(ini_ptn_vec, weight, bias))
#Aktualisieren Sie bis zu 1000 Mal
for i in range(time):
#Asynchrones Update
async(ini_ptn_vec, weight, bias, step_function1)
#Fügen Sie beim Aktualisieren der Liste Energie hinzu
energy.append(energy_cal(ini_ptn_vec, weight, bias))
#Verlassen Sie die Schleife, wenn Sie das Speichermuster abrufen können
if(hamming(ini_ptn_vec, pattern.X[k-1]) == 0):
print("Anzahl der Aktualisierungszeiten=", i)
break
#Zeigen Sie das Muster an, das endgültig abgerufen wurde
print("Gesammeltes Muster")
display_pattern(ini_ptn_vec)
Ausführungsergebnis
Überprüfen Sie den Übergang der zu "Energie" hinzugefügten Energie.
HopfieldNetwork.ipynb
plt.plot(energy)
plt.ylabel("energy", fontsize=18)
plt.xlabel("time", fontsize=18)
plt.show()
Ausführungsergebnis
Derzeit ist der Fluss des assoziativen Speichers durch das Sprungfeldnetzwerk wie oben beschrieben. Zu einem späteren Zeitpunkt möchte ich einige Experimente veröffentlichen.
[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