Ich musste den Code des neuronalen Netzwerks (NN) erklären und entschied mich, diese Gelegenheit zu nutzen, um ihn kurz zusammenzufassen. Im Folgenden wird davon ausgegangen, dass das Grundwissen über NN bekannt ist.
[Lern- und neuronale Netze (Reihe für elektronische Informations- und Kommunikationstechnik)](http://www.amazon.co.jp/gp/product/4627702914/ref=as_li_tf_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4627702914&linkCode=as2&o 22) <img src = "http://ir-jp.amazon-adsystem.com/e/ir?t=shimashimao06-22&l=as2&o=9&a=4627702914" width = "1" height = "1" border = " 0 "alt =" "style =" border: none! Wichtig; Rand: 0px! Wichtig; "/>
Eingabe in das Netzwerk: $ (x_ {1}, x_ {2}, ..., x_ {N}) $
Ausgabe aus dem Netzwerk: $ (y_ {1}, y_ {2}, ..., y_ {M}) $
Netzwerkeingabe / -ausgabe-Beziehung: $ (y_ {1}, y_ {2}, ..., y_ {M}) = F (x_ {1}, x_ {2}, ..., x_ {N}) $
Gewicht verbinden: {$ w_ {ij}
Das obige Nachschlagewerk enthält die folgende Beschreibung, warum BP weit verbreitet ist.
- Die Berechnung der partiellen Differenzierung der Bewertungsfunktion für jeden Parameter ist in einem allgemeinen nichtlinearen System tendenziell kompliziert, in BP gibt es jedoch eine systematische und systematische Berechnungsmethode. Darüber hinaus können die zur Bestimmung des Korrekturbetrags jedes Parameters erforderlichen Informationen unter Verwendung der dem Netzwerk bekannten Verbindungsstruktur an den erforderlichen Ort übertragen werden. Dies bedeutet, dass keine spezielle Kommunikationsleitung zum Lernen bereitgestellt werden muss, was zur Vereinfachung des Algorithmus und der Hardware zweckmäßig ist.
- Die funktionale Approximationsfähigkeit des Netzwerks ist theoretisch garantiert. Wenn eine ausreichende Anzahl von Zwischenschichtelementen verwendet wird, kann jede Funktion durch geeignete Bestimmung der Parameterwerte (Verbindungsgewicht, Schwellenwert) willkürlich mit hoher Genauigkeit angenähert werden. Es ist nicht immer möglich, einen Parameterwert zu finden, der die optimale Annäherung durch BP ergibt, aber der Beweis einer Art Existenzsatz gibt ein Gefühl der Sicherheit.
Führen Sie die folgenden Vorgänge aus.
Da die Lernmethode für sequentielle Aktualisierungen abgeleitet wird, wird die Gradientenmethode mit dem Ziel angewendet, die Bewertungsskala der folgenden Gleichung für jede Trainingsdaten ($ x ^ {(l)}, y ^ {(l)} $) zu reduzieren.
Die folgende Gleichung wird erhalten, indem die Fehlerbewertungsskala $ E (w_0, w_1, ..., w_N) $ durch $ w_n $ differenziert wird.
Wenn dies differenziert ist,
Um dies weiter zusammenzufassen,
Unter Verwendung des Wertes von $ \ partiell E (w_0, w_1, ..., w_N) / \ partiell w_n $, der aus dem Obigen erhalten wird, wird das Verbindungsgewicht wiederholt durch die folgende Gleichung korrigiert.
Die kleine Änderung von x erstreckt sich auf die Änderung anderer Variablenwerte in einer Kette entsprechend der Abhängigkeit der Variablen in der obigen Abbildung. Gemäß der Kettenregel gilt der folgende relationale Ausdruck zwischen den winzigen Änderungen dieser Variablen $ \ Delta x, \ Delta z_1, \ Delta x_2, \ Delta y $.
Um die obige Formel zusammenzufassen:
Basierend auf der obigen Kettenregel werden wir den BP von NN ableiten, der aus der Eingangsschicht, der Zwischenschicht und der Ausgangsschicht besteht. Die Anzahl der Einheiten für alle drei Schichten beträgt 3 (4 Einheiten für die Eingangsschicht und die Zwischenschicht unter Berücksichtigung des Bias-Terms). Nummerieren Sie die Ausgabeschicht: {1,2,3}, die Zwischenschicht: {4,5,6} und die Eingabeebene: {7,8,9} in der Reihenfolge der Einheit der Ausgabeschicht. Und
BP wird anhand dieser beiden Fälle als Beispiele abgeleitet. Ein Bild jeder Ausbreitung ist unten gezeigt.
Die Beziehung zwischen dem Änderungsbetrag in $ w_2 $ $ \ Delta w_2 $ und dem Änderungsbetrag in $ s_2 $ $ \ Delta s_2 $ wird durch die folgende Gleichung gezeigt.
Diese Änderung in $ y_2 $ ändert den Wert der Fehlerbewertungsskala, und der folgende relationale Ausdruck gilt.
Aus der obigen Gleichung wurde der partielle Differentialkoeffizient $ \ partielle E / \ partielle w_2 $ erhalten, der erforderlich ist, um $ w_2 $ durch das Gradientenverfahren zu korrigieren.
Auch von $ \ Delta s_2 = y_4 \ Delta w_2 $
Die Beziehung des Änderungsbetrags bei Änderung von $ w_4 $ wird nach der folgenden Formel berechnet.
Die auf diese Weise auftretende Änderung von $ y_4 $ wirkt sich auf $ s_1, s_2, s_3 $ am Verbindungsziel aus. Daher gilt der folgende relationale Ausdruck zwischen den Änderungsbeträgen.
Die obige Änderung ändert auch die Fehlerbewertungsskala, wie in der folgenden Gleichung gezeigt.
Organisieren Sie dies und teilen Sie beide Seiten durch $ \ Delta s_4 $ bis
Ist gesucht. Es ist ersichtlich, dass die obige Formel eine Art allmähliche Formel ist, in der $ \ partielles E / \ partielles s_i $ in der mittleren Schicht durch $ \ partielles E / \ partielles s_j $ in der Ausgabeschicht berechnet wird. In ähnlicher Weise ist ersichtlich, dass der Fehler auf die unteren Schichten übertragen werden kann, indem $ \ partielles E / \ partielles s $ der letzten Schicht für eine beliebige Anzahl von NNs gefunden wird.
Schließlich,
Entschuldigung für den ziemlich schmutzigen Code, aber ich werde ihn unten einfügen. Der Schwellenwert (Bias) ist der Einfachheit halber für alle Neuronen festgelegt. Fügen Sie beim Erstellen von Code am Anfang des Eingabevektors ein Element mit dem Wert 1 hinzu, fügen Sie dem Gewichtsvektor ein Bias-Element hinzu und passen Sie die Parameter als Teil des Gewichts an.
python
# coding: utf-8
import numpy as np
Afrom numpy.random import randint
import sys
class NN:
def __init__(self):
self.alph = 0.04
self.mu = 0.01
self.theta = 0.1
self.w = []
self.output = []
self.output_sigm = []
self.T = 0
def create_data(self, input_n_row, input_n_col, layer_sizes):
self.x = randint(2, size=(input_n_row, input_n_col))
self.y = randint(2, size=(input_n_row, layer_sizes[-1]))
for i_layer, size in enumerate(layer_sizes):
if i_layer == 0:
self.w.append(np.random.randn(input_n_col, size))
self.output.append(np.zeros((input_n_row, size)))
self.output_sigm.append(np.zeros((input_n_row ,size)))
else:
self.w.append(np.random.randn(layer_sizes[i_layer-1], size))
self.output.append(np.zeros((input_n_row, size)))
self.output_sigm.append(np.zeros((input_n_row ,size)))
def fit(self, eps=10e-6):
error = sys.maxint
self.forward()
while error>eps:
self.update( self.backword() )
self.forward()
error = self.calculate_error()
self.T += 1
print "T=", self.T
print "error", error
def calculate_error(self):
return np.sum( np.power(self.y - self.output_sigm[-1], 2) )
def forward(self):
for i_layer in xrange(len(self.output)):
if i_layer == 0:
self.output[i_layer] = self.x.dot(self.w[i_layer])
self.output_sigm[i_layer] = self.sigmoid(self.output[i_layer])
else:
self.output[i_layer] = self.output_sigm[i_layer-1].dot(self.w[i_layer])
self.output_sigm[i_layer] = self.sigmoid(self.output[i_layer])
def backword(self):
result = []
for i_layer in range(len(self.w))[::-1]:
if i_layer==len(self.w)-1:
result.insert(0, self.diff(self.output_sigm[i_layer], self.y) )
else:
result.insert(0, self.diff_mult( self.output_sigm[i_layer], result[0].dot(self.w[i_layer+1].T)) )
return result
def update(self, diff):
for i_layer in range(len(self.w))[::-1]:
if i_layer==0:
for i_row in xrange(len(diff[i_layer])):
self.w[i_layer] -= self.get_incremental_update_value(
self.x[i_row].reshape(len(self.w[i_layer]),1),
diff[i_layer][i_row,:].reshape(1,self.w[i_layer].shape[1])
)
else:
for i_row in xrange(len(diff[i_layer])):
self.w[i_layer] -= self.get_incremental_update_value(
self.output_sigm[i_layer-1][i_row,:].reshape(len(self.w[i_layer]),1),
diff[i_layer][i_row,:].reshape(1,self.w[i_layer].shape[1])
)
def get_incremental_update_value(self, input_data, diff):
return np.kron(input_data, self.mu*diff)
def diff(self, y, t):
return self.alph * 2*(y - t) * self.dsigmoid(y)
def diff_mult(self, y, prp_value):
return self.alph * self.dsigmoid(y) * prp_value
def sigmoid(self, s, alph=0.01):
return 1/(1+np.exp(-self.alph*(s-self.theta)))
def dsigmoid(self, y):
return y * (1 - y)
if __name__=='__main__':
layer_sizes = (4,3)
input_layer_size = 3
input_data_size = 1000
nn = NN()
nn.create_data(input_data_size, input_layer_size, layer_sizes)
nn.fit()
Wir entschuldigen uns für die Unannehmlichkeiten, würden uns aber freuen, wenn Sie auf Fehler hinweisen könnten.
Recommended Posts