Implementierung eines neuronalen Netzwerks in Python

Einführung

Ich habe ein 3-Schicht-Neuronales Netzwerk mit Python implementiert und versucht, XNOR zu identifizieren. Ich habe auch die Formeln veröffentlicht. Wenn Sie interessiert sind, lesen Sie sie bitte. Ich habe ["Deep Learning"](http://www.amazon.co.jp/ Deep Learning-Maschinelles Lernen Professional Series-Okaya-Takayuki / dp / 4061529021) als Lehrbuch verwendet.

Struktur dieses Artikels

neurales Netzwerk

Ein neuronales Netzwerk ist ein Modell, das die neuronalen Schaltkreise des menschlichen Gehirns nachahmt. Mit diesem Modell sind Bilderkennung und Spracherkennung möglich. Das diesmal implementierte Netzwerk hat eine dreischichtige Struktur, die aus einer Eingangsschicht, einer Zwischenschicht (1 Schicht) und einer Ausgangsschicht besteht.

Gewichtsaktualisierung

Ich werde mit der folgenden Abbildung erklären.

neu.png

Das Gewicht von der $ i $ -ten Einheit in der $ l-1 $ -Ebene zur $ j $ -ten Einheit in der $ l $ -Ebene sei $ w_ {ji} ^ {(l)} $. Außerdem sei $ u_ {i} ^ {(l-1)} $ der Wert, der von der $ i $ -ten Einheit in der $ l-1 $ -Ebene gehalten wird. Die Sigmoidfunktion $ g (x) $ wird als Aktivierungsfunktion verwendet. Dies ist zweckmäßig, da der Differenzwert unter Verwendung des Werts vor der Differenzierung erhalten werden kann.

g(x) = \cfrac{1}{1 + \exp(-x)} \\
g'(x) = g(x)(1 - g(x))

Der quadratische Fehler $ E_n $ wird als Zielfunktion verwendet, und das Gewicht wird durch die folgende Formel aktualisiert, um es zu minimieren. $ E_n $ ist der Fehler, der durch eine Stichprobe verursacht wird, und die Methode zum Aktualisieren des Gewichts unter Verwendung dieser $ E_n $ wird als stochastische Gradientenabstiegsmethode bezeichnet. Die probabilistische Gradientenabstiegsmethode hat den Vorteil, dass sie weniger wahrscheinlich in der lokalen Lösung eingeschlossen ist, da sie sich jedes Mal ändert, wenn die Zielfunktion aktualisiert wird. $ \ Epsilon $ wird als Lernrate bezeichnet und ist ein Parameter, der die Lerngeschwindigkeit bestimmt. Der Punkt ist, wie der Begriff der partiellen Differenzierung berechnet wird.

{{w}_{ji}^{(l)}}_{new} = {w_{ji}^{(l)}}_{old} - \epsilon\cfrac{\partial E_n}{\partial {w_{ji}^{(l)}}_{old}}

Fehler bei der Weitergabe

Jetzt werde ich erklären, wie man $ \ cfrac {\ partielles E_n} {\ partielles w_ {ji} ^ {(l)}} $ findet. Da sich die Methode zum Erhalten der Ausgabeschicht und der Zwischenschicht geringfügig unterscheidet, werden sie separat erläutert.

** ** Der Lehrer wird durch $ t_j $ dargestellt. Wenn der quadratische Fehler $ E_n $ teilweise durch das Gewicht der Ausgabeschicht $ w_ {ji} ^ {(l)} $ differenziert wird,

\begin{align}
\cfrac{\partial E_n}{\partial w_{ji}^{(l)}} &= \cfrac{\partial}{\partial w_{ji}^{(l)}}\cfrac{1}{2}(t_j - g(u_{j}^{(l)}))^{2} \\
&= (t_j - g(u_{j}^{(l)}))\cdot\cfrac{\partial}{\partial w_{ji}^{(l)}}(t_j - g(u_{j}^{(l)})) \\
&= (t_j - g(u_{j}^{(l)}))\cdot\cfrac{\partial}{\partial u_{j}^{(l)}}(t_j - g(u_{j}^{(l)}))\cdot\cfrac{\partial u_{j}^{(l)}}{\partial w_{ji}^{(l)}} \\
\\
&= (g(u_{j}^{(l)}) - t_j)\cdot g'(u_{j}^{(l)})\cdot g(u_{i}^{(l-1)}) \\
\\
&= (g(u_{j}^{(l)}) - t_j)g(u_{j}^{(l)})(1 - g(u_{j}^{(l)}))g(u_{i}^{(l-1)})
\end{align}

** ** Wenn der quadratische Fehler $ E_n $ teilweise durch das Gewicht der mittleren Schicht $ w_ {ji} ^ {(l)} $ differenziert wird,

\begin{align}
\cfrac{\partial E_n}{\partial w_{ji}^{(l)}} &= \cfrac{\partial E_n}{\partial u_{j}^{(l)}}\cfrac{\partial u_{j}^{(l)}}{\partial w_{ji}^{(l)}} \\
\\
&= \delta_{j}^{(l)}\cfrac{\partial u_{j}^{(l)}}{\partial w_{ji}^{(l)}}
\end{align}

Der erste Begriff auf der rechten Seite ist

\begin{align}
\delta_{j}^{(l)} &= \cfrac{\partial E_n}{\partial u_{j}^{(l)}} \\
&= \sum_{k}\cfrac{\partial E_n}{\partial u_{k}^{(l+1)}}\cfrac{\partial u_{k}^{(l+1)}}{\partial u_{j}^{(l)}} \\
\\
&= \sum_{k}\delta_{k}^{(l+1)}w_{kj}^{(l+1)}g'(u_{j}^{(l)}) \\
\\
&= \Bigl(\sum_{k}\delta_{k}^{(l+1)}w_{kj}^{(l+1)}\Bigr)g(u_{j}^{(l)})(1 - g(u_{j}^{(l)}))
\end{align}

Der zweite Term auf der rechten Seite ist

\begin{align}
\cfrac{\partial u_{j}^{(l)}}{\partial w_{ji}^{(l)}} &= g(u_{i}^{(l-1)})
\end{align}

Von Oben,

\begin{align}
\cfrac{\partial E_n}{\partial w_{ji}^{(l)}} &= \delta_{j}^{(l)}\cfrac{\partial u_{j}^{(l)}}{\partial w_{ji}^{(l)}} \\
\\
&= \Bigl(\sum_{k}\delta_{k}^{(l+1)}w_{kj}^{(l+1)}\Bigr)g(u_{j}^{(l)})(1 - g(u_{j}^{(l)}))g(u_{i}^{(l-1)})
\end{align}

Beim Aktualisieren des Gewichts der mittleren Schicht $ l $ wird $ \ delta_ {k} ^ {(l + 1)} $ der nächsten Schicht $ l + 1 $ benötigt. $ \ Delta $ in der Ausgabeschicht kann als Differenz zwischen dem Ausgabewert und dem Lehrer erhalten werden, und indem dies in der Reihenfolge von der Ausgabeschicht zur Eingabeschicht weitergegeben wird, wird das Gewicht der Zwischenschicht aktualisiert. Dies ist der Grund, warum es als Fehlerrückübertragung bezeichnet wird.

XNOR

XNOR gibt $ 1 $ aus, wenn die Eingabewerte gleich sind, und $ 0 $, wenn die Eingabewerte unterschiedlich sind. Es kann nicht linear identifiziert werden.

x_1 x_2 t
0 0 1
0 1 0
1 0 0
1 1 1
xnor.png

Implementierung in Python

Wir haben ein neuronales Netzwerk implementiert, das XNOR identifiziert. Die Anzahl der Zwischenschichten beträgt eins und die Anzahl der Einheiten in der Zwischenschicht beträgt zwei. Die Lernrate beträgt $ \ epsilon = 0,1 $ und der Impulskoeffizient beträgt $ \ mu = 0,9 $. (Momentum ist eine der Methoden zur Verbesserung der Konvergenzleistung, und der Gewichtskorrekturbetrag wird addiert, indem der vorherige Gewichtskorrekturbetrag mit einem Koeffizienten multipliziert wird.)

neuralnetwork.py


import numpy
import math
import random
from matplotlib import pyplot

class Neural:

	# constructor
	def __init__(self, n_input, n_hidden, n_output):
		self.hidden_weight = numpy.random.random_sample((n_hidden, n_input + 1))
		self.output_weight = numpy.random.random_sample((n_output, n_hidden + 1))
		self.hidden_momentum = numpy.zeros((n_hidden, n_input + 1))
		self.output_momentum = numpy.zeros((n_output, n_hidden + 1))


# public method
	def train(self, X, T, epsilon, mu, epoch):
		self.error = numpy.zeros(epoch)
		N = X.shape[0]
		for epo in range(epoch):
			for i in range(N):
				x = X[i, :]
				t = T[i, :]

				self.__update_weight(x, t, epsilon, mu)

			self.error[epo] = self.__calc_error(X, T)


	def predict(self, X):
		N = X.shape[0]
		C = numpy.zeros(N).astype('int')
		Y = numpy.zeros((N, X.shape[1]))
		for i in range(N):
			x = X[i, :]
			z, y = self.__forward(x)

			Y[i] = y
			C[i] = y.argmax()

		return (C, Y)


	def error_graph(self):
		pyplot.ylim(0.0, 2.0)
		pyplot.plot(numpy.arange(0, self.error.shape[0]), self.error)
		pyplot.show()


# private method
	def __sigmoid(self, arr):
		return numpy.vectorize(lambda x: 1.0 / (1.0 + math.exp(-x)))(arr)


	def __forward(self, x):
		# z: output in hidden layer, y: output in output layer
		z = self.__sigmoid(self.hidden_weight.dot(numpy.r_[numpy.array([1]), x]))
		y = self.__sigmoid(self.output_weight.dot(numpy.r_[numpy.array([1]), z]))

		return (z, y)

	def __update_weight(self, x, t, epsilon, mu):
		z, y = self.__forward(x)

		# update output_weight
		output_delta = (y - t) * y * (1.0 - y)
		_output_weight = self.output_weight
		self.output_weight -= epsilon * output_delta.reshape((-1, 1)) * numpy.r_[numpy.array([1]), z] - mu * self.output_momentum
		self.output_momentum = self.output_weight - _output_weight

		# update hidden_weight
		hidden_delta = (self.output_weight[:, 1:].T.dot(output_delta)) * z * (1.0 - z)
		_hidden_weight = self.hidden_weight
		self.hidden_weight -= epsilon * hidden_delta.reshape((-1, 1)) * numpy.r_[numpy.array([1]), x]
		self.hidden_momentum = self.hidden_weight - _hidden_weight


	def __calc_error(self, X, T):
		N = X.shape[0]
		err = 0.0
		for i in range(N):
			x = X[i, :]
			t = T[i, :]

			z, y = self.__forward(x)
			err += (y - t).dot((y - t).reshape((-1, 1))) / 2.0

		return err

main.py


from neuralnetwork import *

if __name__ == '__main__':

	X = numpy.array([[0, 0], [0, 1], [1, 0], [1, 1]])
	T = numpy.array([[1, 0], [0, 1], [0, 1], [1, 0]])
	N = X.shape[0] # number of data

	input_size = X.shape[1]
	hidden_size = 2
	output_size = 2
	epsilon = 0.1
	mu = 0.9
	epoch = 10000

	nn = Neural(input_size, hidden_size, output_size)
	nn.train(X, T, epsilon, mu, epoch)
	nn.error_graph()

	C, Y = nn.predict(X)

	for i in range(N):
		x = X[i, :]
		y = Y[i, :]
		c = C[i]

		print x
		print y
		print c
		print ""

Ergebnis

Es kann korrekt identifiziert werden.

x_1 x_2 t y
0 0 [ 1, 0 ] [ 0.92598739, 0.07297757 ]
0 1 [ 0, 1 ] [ 0.06824915, 0.93312514 ]
1 0 [ 0, 1 ] [ 0.06828438, 0.93309010 ]
1 1 [ 1, 0 ] [ 0.92610205, 0.07220633 ]

Ich habe eine Grafik erstellt, die zeigt, wie der Fehler abnimmt. Die horizontale Achse ist die Anzahl der Epochen und die vertikale Achse ist der Fehler.

error.png

abschließend

Wir haben ein dreischichtiges neuronales Netzwerk implementiert und konnten XNOR identifizieren. Es gibt noch viel zu tun, wie zum Beispiel Lerntricks (wie man den anfänglichen Gewichtswert bestimmt, wie man die Lernrate bestimmt, AdaGrad, Impuls), aber dies ist das Ende.

Recommended Posts

Implementierung eines neuronalen Netzwerks in Python
PRML Kapitel 5 Python-Implementierung für neuronale Netze
RNN-Implementierung in Python
ValueObject-Implementierung in Python
SVM-Implementierung in Python
Implementierung der schnellen Sortierung in Python
Implementierung eines neuronalen Netzwerks (nur NumPy)
Einfache Implementierung eines neuronalen Netzwerks mit Chainer
Neuronales Netzwerk mit OpenCV 3 und Python 3
Sortieralgorithmus und Implementierung in Python
Implementierung der HMM-Parameterschätzung in Python
Implementierung einer gemischten Normalverteilung in Python
Implementierung eines zweischichtigen neuronalen Netzwerks 2
Implementierung eines Lebensspiels in Python
Einfache Theorie und Implementierung des neuronalen Netzes
Implementierung der ursprünglichen Sortierung in Python
Versuchen Sie, ein neuronales Netzwerk in Python aufzubauen, ohne eine Bibliothek zu verwenden
Quadtree in Python --2
CURL in Python
Metaprogrammierung mit Python
Python 3.3 mit Anaconda
Geokodierung in Python
SendKeys in Python
PRML Kapitel 5 Python-Implementierung eines Netzwerks mit gemischter Dichte
Metaanalyse in Python
Unittest in Python
Warteschlangen- und Python-Implementierungsmodul "deque"
Implementierung eines 3-Schicht-Neuronalen Netzwerks (kein Lernen)
Zwietracht in Python
DCI in Python
Quicksort in Python
nCr in Python
N-Gramm in Python
Programmieren mit Python
Plink in Python
Konstante in Python
SQLite in Python
Schritt AIC in Python
Implementierung von "verschwommenen" neuronalen Netzen mit Chainer
Einfache Implementierung eines neuronalen Netzwerks mithilfe der Chainer-Datenaufbereitung
Implementiert in Python PRML Kapitel 5 Neuronales Netzwerk
LINE-Bot [0] in Python
CSV in Python
Reverse Assembler mit Python
Reflexion in Python
Konstante in Python
nCr in Python.
Format in Python
Scons in Python 3
Python & Machine Learning Study Memo ③: Neuronales Netz
Puyopuyo in Python
Python in Virtualenv
PPAP in Python
Quad-Tree in Python
Reflexion in Python
Einfache Implementierung eines neuronalen Netzwerks mithilfe der Beschreibung des Chainer-Modells
Chemie mit Python
Hashbar in Python
DirectLiNGAM in Python