Maschinelles Lernen und tiefes Lernen sind reich an Bibliotheken, sodass Sie Vorhersagen durch einfaches Kopieren und Einfügen treffen können. Ich selbst habe Programme ausgeführt, die von vielen Vorfahren erstellt wurden, und bin auf ein Niveau gekommen, auf dem ich die Gliederung verstehen kann. Insbesondere wird Deep Learning (neuronales Netzwerk) auf die Verarbeitung von GAN und natürlicher Sprache angewendet. Es ist ein Genre, in dem neue Technologien in schwindelerregendem Tempo entwickelt werden, und ich glaube, dass ihre Anwendung auf Gesellschaft und Industrie rasant voranschreitet. Daher erkennen wir es als die Technologie an, die im Zentrum eines solchen Wandels steht, und möchten ein sehr interessantes und tiefes Verständnis dieser Bereiche haben! Es gibt ein Motiv.
Derzeit lernen wir hier aus den Grundlagen, die als Lehrbuch für tiefes Lernen bekannt sind. https://www.oreilly.co.jp/books/9784873117584/ Dieses Mal möchte ich durch den Aufbau eines neuronalen Netzwerks von Grund auf (obwohl ich Numpy verwende) einen echten Eindruck von den dort durchgeführten Berechnungen bekommen.
Die Zusammenfassung ist unten.
Perceptron bedeutet, dass es mehrere Signale als Ein- und Ausgangssignale empfängt. Im Bereich des maschinellen Lernens wird das Nichtausgeben eines Signals als 0 und das Ausgeben eines Signals als 1 behandelt.
Die obige Abbildung ist ein einfaches Diagramm dieser Idee. x ist das Eingangssignal, y ist das Ausgangssignal und w ist das Gewicht. Dieses 〇 wird als Neuron bezeichnet. Dem Neuron wird die Summe des Gewichts multipliziert mit dem Eingabewert gesendet. Zu diesem Zeitpunkt wird Ausgang 1 ausgegeben, wenn die Gesamtsumme den Schwellenwert θ überschreitet. Die Formel lautet wie folgt.
Lassen Sie uns nun tatsächlich ein Programm erstellen. Ich habe das in der obigen Abbildung gezeigte einfache Muster reproduziert. Berechnen wir zunächst, wann der Schwellenwert 0,4 beträgt.
NN.ipynb
def AND(x1,x2):
w1,w2,theta = 0.5,0.5,0.4
tmp = x1*w1 + x2*w2
b = -0.5
if tmp <= theta:
return 0
elif tmp > theta:
return 1
python
print(AND(0,0))
print(AND(1,0))
print(AND(0,1))
print(AND(1,1))
0
1
1
1
Als Ergebnis wurde festgestellt, dass, wenn entweder x1 oder x2 1 ist, 1 als Ausgabe ausgegeben wird. Wenn andererseits der Schwellenwert 0,7 beträgt, ist dies wie folgt.
print(AND(0,0))
print(AND(1,0))
print(AND(0,1))
print(AND(1,1))
0
0
0
1
Wenn nur eines von x1 und x2 1 ist, spuckt der Ausgang nicht mehr 1 aus. Sie können sehen, dass sich die erhaltene Ausgabe abhängig von der Schwellenwerteinstellung ändert.
Ein mehrschichtiges Perzeptron ist ein Netzwerk mit einer Schicht, die als Zwischenschicht zwischen der Eingangsschicht und der Ausgangsschicht bezeichnet wird. Die Beschreibung kann je nach Buch unterschiedlich sein, aber im Fall der folgenden Abbildung wird die Eingabeebene als 0-Schicht, die Zwischenschicht als 1-Schicht und die Ausgabeschicht als 2-Schichten bezeichnet.
Hier scheint es einen Stil zu geben (benutzerdefiniert?), Wie man zählt, wenn man es ein neural-Schicht-Neuronales Netzwerk nennt. Es scheint, dass wir die Gewichtsschicht zählen oder die Schicht der Neuronen nennen können. Ich habe nicht viel Erfahrung mit dem, was üblicher ist, aber ich möchte O'Reillys Lehrbuch folgen und es auf Gewichtsbasis benennen.
Als nächstes führen wir einen Wert namens Bias b ein. Durch Umordnen der obigen Gleichung mit dem vorherigen Schwellenwert & thgr; als -b ist es möglich, die Ausgabe von y auf 0 oder 1 mit 0 als Referenz zu bestimmen, wie in der obigen Gleichung. Bias ist die Bedeutung eines Korrekturwerts, der in der Kleinarbeitsindustrie (Fertigungsindustrie) "verstopft", und es ist möglich, den Wert auf der y-Achse insgesamt zu erhöhen oder zu senken.
Die Funktion, die bestimmt, ob y 0 oder 1 ist, wird als Aktivierungsfunktion bezeichnet. Da der durch diese Aktivierungsfunktion erhaltene Wert ein Wert nahe 0 oder 1 sein kann, gibt es auch eine Funktion, die verhindern kann, dass die Berechnung divergiert. Es gibt verschiedene Arten dieser Aktivierungsfunktion.
Dies ist eine der Funktionen, die häufig in der Aktivierungsfunktion verwendet werden. Es ist ein Bruchteil der Funktion der Napier-Zahl e, die die Basis des natürlichen Logarithmus ist, wie unten gezeigt. Die Form dieser Funktion ist schwer zu finden, sieht aber wie folgt aus.
NN.ipynb
import numpy as np
def sigmoid(x):
return 1/(1+np.exp(-x))
xxx = np.arange(-5.0,5.0,0.1)#Sigmoidfunktion anzeigen
yyy = sigmoid(xxx)
plt.plot(xxx,yyy)
plt.ylim(-0.1,1.1)
plt.show
Es ist ersichtlich, dass wenn x> 0 mit x = 0 als Grenze ist, es sich allmählich y = 1 nähert. Im Gegenteil, wenn x <0 ist, nähert es sich allmählich y = 0. Es stellt sich heraus, dass der Punkt, an dem der Eingabewert zwischen 0 und 1 ausgegeben werden kann, sehr praktisch ist, da er die Rolle der Aktivierungsfunktion spielt.
Als nächstes gibt es eine Sprungfunktion als eine Funktion, die 0,1 bis zum Äußersten der Sigmoidfunktion ausgibt. Dies würde wie folgt geschrieben werden.
NN.ipynb
def step_function(x):
return np.array(x > 0, dtype=np.int)
x = np.arange(-5.0, 5.0, 0.1)
y = step_function(x)
plt.plot(xxx,yyy)
plt.plot(x, y)
plt.ylim(-0.1, 1.1)
plt.show()
Blau ist die Schrittfunktion und Orange ist die Sigmoidfunktion. Sie können sehen, dass der Ausgabewert nur 0 oder 1 ist. Ich habe wenig Ahnung, wie ich diese Funktion richtig verwenden kann. Lassen Sie sie daher als meine zukünftigen Hausaufgaben. ** Als Gefühl verstehe ich, dass die Sigmoid-Funktion eine Funktion hat, um den Unterschied auch bei einem geringfügigen Eingabedifferenz zu unterscheiden, da sie den Wert feiner annehmen kann. Wenn es dagegen mehrere Ebenen gibt und die Berechnungslast hoch ist, denke ich, dass es möglich ist, eine Unterscheidung zu treffen und gleichzeitig die Last zu reduzieren, indem die entsprechende Schrittfunktion verwendet wird. ** **.
Abschließend möchte ich auf die ReLU-Funktion (Rectified Linear Unit) eingehen, die auch den Eindruck hat, dass sie häufig verwendet wird. Wenn x 0 überschreitet, wird der Wert so ausgegeben, wie er ist, und wenn er 0 oder weniger ist, wird 0 ausgegeben.
NN.ipynb
def relu(x):
return np.maximum(0,x)
xx = np.arange(-5.0,5.0,0.1)
yy = relu(xx)
plt.plot(xx,yy)
plt.ylim(-0.1,5)
plt.show
Dieses Mal werden wir ein neuronales Netzwerk vom Typ Vorwärtsausbreitung erstellen. Dieser Vorwärtsausbreitungstyp zeigt an, dass der Fluss in einer Richtung vom Eingang zum Ausgang fließt. Wenn Sie überlegen, ein Modell zu trainieren, wird die Berechnung von der Ausgabe zur Eingabe durchgeführt. Dies wird als Backpropagation-Methode bezeichnet.
Nun möchte ich tatsächlich ein dreischichtiges neuronales Netzwerk beschreiben.
Ziehen Sie in Betracht, ein dreischichtiges neuronales Netzwerk zu erstellen, wie in der obigen Abbildung gezeigt. Lassen Sie uns zunächst nur die Berechnungen herausnehmen, die in der obigen Abbildung fett hervorgehoben sind.
NN.ipynb
def init_network():
network = {}
network['W1'] = np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])
network['b1'] = np.array([0.1,0.2,0.3])
return network
def forword(network,x):
W1= network['W1']
b1= network['b1']
a1 = np.dot(x,W1)+b1
z1 = sigmoid(a1)
return y
network = init_network()
x = np.array([2,1])
z1 = forword(network,x)
print(z1)
[0.40442364 0.59557636]
Ich lasse die Funktion init_network () Gewichte und Verzerrungen definieren und die Funktion forword () die Formeln definieren, die tatsächlich berechnet werden. Danach wird die Funktion aufgerufen und der Anfangswert x zugewiesen, damit die Antwort ausgespuckt werden kann. Es ist einfacher zu verstehen als zu schreiben, ohne eine Funktion in einer Reihe zu definieren.
** Beachten Sie auch die Funktion, die das innere Produkt der hier als np.dot beschriebenen Matrix darstellt. Seien Sie vorsichtig, wenn Sie das Produkt von Matrizen beschreiben, da sich die Abmessungen der Matrix in der Reihenfolge der Multiplikation ändern. ** **.
NN.ipynb
def init_network():
network = {}
network['W1'] = np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])
network['b1'] = np.array([0.1,0.2,0.3])
network['W2'] = np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
network['b2'] = np.array([0.1,0.2])
network['W3'] = np.array([[0.1,0.3],[0.2,0.4]])
network['b3'] = np.array([0.1,0.2])
return network
def forword(network,x):
W1,W2,W3 = network['W1'],network['W2'],network['W3']
b1,b2,b3 = network['b1'],network['b2'],network['b3']
a1 = np.dot(x,W1)+b1
z1 = sigmoid(a1)
a2 = np.dot(z1,W2)+b2
z2 = sigmoid(a2)
a3 = np.dot(z2,W3)+b3
y = softmax(a3)
return y
Wenn Sie die beiden Funktionen bis zum Ende beschreiben lassen, wird es so geschrieben. Nun, ich habe es hier bereits erwähnt, aber am Ende steht eine Beschreibung als softmax. Dies ist unten zusammengefasst.
Danach können wir sehen, dass wir diesen beiden Funktionen Ebenen hinzufügen sollten. Betrachten Sie dann den Wert y, der am Ende ausgegeben werden soll. Wenn Probleme wie das Erraten von 0 bis 9 Arten von Zahlen klassifiziert werden müssen, wird die jedem Typ entsprechende Wahrscheinlichkeit ausgegeben und die mit der höchsten Wahrscheinlichkeit als vorhergesagter Wert verwendet. Eine bequeme Funktion, um eine solche Wahrscheinlichkeit auszudrücken, ist die Softmax-Funktion.
Die Summe der Werte, die für alle Elemente in einer bestimmten Klassifizierung verwendet wurden, wird als Nenner verwendet, und die einzeln genommenen Werte werden als Zähler verwendet, um die Wahrscheinlichkeit darzustellen. Durch das Beenden mit dieser Softmax-Funktion wird das Klassifizierungsproblem auf die Wahrscheinlichkeit reduziert, und der höchste Wert ist der vorhergesagte Wert.
In Bezug auf die Implementierung besteht das Problem, dass der Wert sehr leicht zu divergieren ist, da es sich um eine Exponentialfunktion von exp handelt. Daher scheint es der Einfachheit halber oft so zu sein, dass es schwierig wird, auseinander zu gehen, indem eine bestimmte Konstante mit dem Nenner und dem Molekül multipliziert und in den Exponenten von exp gesetzt wird.
NN.ipynb
def softmax(a):
c = np.max(a)
exp_a = np.exp(a-c)
sum_exp_a = np.sum(exp_a)
y = exp_a/sum_exp_a
return y
NN.ipynb
network = init_network()
x = np.array([2,1])
y = forword(network,x)
print(y)
[0.40442364 0.59557636]
Als Test habe ich einen geeigneten Wert in x eingegeben und die Antwort wurde wie folgt zurückgegeben. Es wurde ein Wert ausgegeben, der angibt, dass y1 eine Wahrscheinlichkeit von 40% und y2 eine Wahrscheinlichkeit von 60% hat. Danach verstehe ich, dass eine komplizierte Klassifizierung möglich wird, wenn die Eingabematrix größer und die Ebenen tiefer werden (≈ Zunahme).
Dieses Mal habe ich von Hand ein sehr einfaches neuronales Netzwerk erstellt. Nur indem ich meine Hand bewegte, vertiefte ich mein Verständnis. ** Endlich habe ich die Grundlagen des GAN-Algorithmus verstanden, den ich kopiert und verschoben habe. ** Indem hier Ideen wie Modelllernen und Faltung eingefügt werden, wird es mit dem neuronalen Faltungsnetzwerk und weiter mit GAN verbunden. Es mag ein Auftakt sein, die neueste Technologie zu erreichen, aber ich hoffe, dass ich durch eine stetige Vertiefung meines Verständnisses auf diese Weise meine technischen Fähigkeiten verbessern kann.
Das vollständige Programm finden Sie hier. Es ist unterteilt in eine Datei, die Sie gerade mit der Funktion abgespielt haben, und eine Datei, die ein 3-Schicht-neuronales Netzwerk ist. https://github.com/Fumio-eisan/neuralnetwork_20200318
Recommended Posts