[GO] Versuchen Sie, assoziativen Speicher durch Hop-Field-Netzwerk in Python zu implementieren

Einführung

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.

image.png

Wenn Sie das verrauschte Muster als Ausgangsmuster festlegen (linkes Bild unten) und die Aktualisierung wiederholen, wird das Speichermuster abgerufen (rechtes Bild unten). image.pngimage.png

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).

Modell [1] [2]

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. HopfieldNetWork.png

Erinnerungsprozess

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 $.

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}

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.

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}

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.

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}
(N × N-Matrix)
\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}
(N × N-Matrix)
\tag{5}

Erinnerungsprozess

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. $ 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}

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}

Klassen und Funktionen

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

Trainieren

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 image.png

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 image.png

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.

Verweise

[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

Versuchen Sie, assoziativen Speicher durch Hop-Field-Netzwerk in Python zu implementieren
Lassen Sie uns Yuma in Python 3 implementieren
Versuchen Sie, mit Binärdaten in Python zu arbeiten
Versuchen Sie, zwei Stapel in Python auf einem Array zu implementieren
Versuchen Sie, mit Mongo in Python auf dem Mac zu arbeiten
Versuchen Sie, die Monte-Carlo-Methode in Python zu implementieren
Versuchen Sie es mit Python.
Versuchen Sie gRPC in Python
Probieren Sie 9 Slices in Python aus
Versuchen Sie, Yuma mit Brainf * ck 512-Zeilen zu implementieren (Code mit Python generieren und ausführen)
Versuchen Sie, Python mit pybind11 in ein C ++ - Programm einzubetten
Schaben mit Selen in Python
Betreiben Sie LibreOffice mit Python
Versuchen Sie, RBM mit Chainer zu implementieren.
Schaben mit Chromedriver in Python
Neuronales Netzwerk mit Python (Scikit-Learn)
Debuggen mit pdb in Python
Probieren Sie die Python-Ausgabe mit Haxe 3.2 aus
Versuchen Sie, XOR mit PyTorch zu implementieren
Umgang mit Sounds in Python
Scraping mit Selen in Python
Versuchen Sie LINE Notify mit Python
Scraping mit Tor in Python
Tweet mit Bild in Python
Kombiniert mit Ordnungszahl in Python
Versuchen Sie, Python mit Try Jupyter auszuführen
Versuchen Sie, Parfüm mit Go zu implementieren
Implementierung eines neuronalen Netzwerks in Python
Versuchen Sie die Gesichtserkennung mit Python
Netzwerkprogrammierung mit Python Scapy
Versuchen Sie, Python in der mit pipenv erstellten Django-Umgebung auszuführen
Versuchen Sie, COVID-19 Tokyo-Daten mit Python zu kratzen
Versuchen Sie, Ihre eigenen Objekte mit Prioritätswarteschlangen in Python zu sortieren
Versuchen Sie, den Betrieb von Netzwerkgeräten mit Python zu automatisieren
Versuchen Sie, ein neuronales Netzwerk in Python aufzubauen, ohne eine Bibliothek zu verwenden
Zahlenerkennung in Bildern mit Python
Überprüfen Sie Python auf Speicherlecks
Versuchen Sie es mit Python + Beautiful Soup
Testen mit Zufallszahlen in Python
Neuronales Netzwerk mit OpenCV 3 und Python 3
GOTO in Python mit erhabenem Text 3
[Python] Generiert QR-Code im Speicher
Arbeiten mit LibreOffice in Python: Importieren
Einwegverzögerungsmessung des Netzwerks mit Python
CSS-Analyse mit cssutils in Python
Versuchen Sie, Facebook mit Python zu betreiben
Versuchen Sie die Singularwertzerlegung mit Python
Numer0n mit Elementen, die mit Python erstellt wurden
Versuchen Sie es mit LevelDB mit Python (plyvel)
Öffnen Sie UTF-8 mit Stückliste in Python
Versuchen wir es mit Fizz Buzz mit Python
Versuchen Sie, Trace in Python zu berechnen
Versuchen Sie den Zugriff auf das SPS-Register in Python
Verwenden Sie rospy mit virtualenv in Python3
Versuchen Sie die Gesichtserkennung mit Python + OpenCV
Verwenden Sie Python in pyenv mit NeoVim
Heatmap mit Dendrogramm in Python + Matplotlib