Ich habe meinen Kopf gegen diese Mauer für so etwas wie eine Ewigkeit geschlagen, und ich kann einfach nicht scheinen, meinen Kopf darum zu wickeln. Ich versuche, einen Autoencoder zu implementieren, der nur numpy und Matrixmultiplikation verwendet. Keine theano oder keras Tricks erlaubt.Stuck Implementierung von einfachen neuronalen Netzwerk
Ich werde das Problem und all seine Details beschreiben. Es ist anfangs etwas komplex, da es viele Variablen gibt, aber es ist wirklich ziemlich einfach.
Was wir wissen
1) X
ist ein m
von n
Matrix, die unsere Eingaben ist. Die Eingaben sind Zeilen dieser Matrix. Jede Eingabe ist ein n
dimensionaler Zeilenvektor, und wir haben m
von ihnen.
2) Die Anzahl der Neuronen in unserer (einzelnen) versteckten Schicht, die k
ist.
3) Die Aktivierungsfunktion unserer Neuronen (sigmoid, wird als g(x)
bezeichnet) und sein Derivat g'(x)
Was wir wissen und wollen nicht
Insgesamt war unser Ziel zu finden ist finden 6 Matrizen: w1
die n
von k
ist, b1
die m
von k
ist, w2
die k
von n
, b2 ist die m
ist durch n
, w3
das ist n
von n
und b3
, die m
von n
ist.
Sie werden zufällig initialisiert und wir finden die beste Lösung mit Gradientenabstieg.
Der Prozess
Der gesamte Prozess so etwas wie dieses
Zuerst haben wir z1 = Xw1+b1
berechnen aussieht. Es ist m
von k
und ist der Eingang zu unserer versteckten Schicht. Wir berechnen dann h1 = g(z1)
, was einfach die Sigmoidfunktion auf alle Elemente von z1
anwendet. natürlich ist es auch m
von k
und ist die Ausgabe unserer versteckten Schicht.
Wir berechnen dann z2 = h1w2+b2
, die m
von n
ist und ist der Eingang in die Ausgangsschicht unseres neuronalen Netzes. Dann berechnen wir h2 = g(z2)
, was wiederum natürlich auch m
von n
ist und der Ausgang unseres neuronalen Netzes ist.
Schließlich nehmen wir diese Ausgabe und führen einige lineare Operator auf es: Xhat = h2w3+b3
, die auch m
von n
ist und ist unser Endergebnis.
Wo ich stecken bin
Die Kostenfunktion I minimieren wollen, ist der mittlere Fehler im Quadrat. Ich setzte es bereits in numpy Code
def cost(x, xhat):
return (1.0/(2 * m)) * np.trace(np.dot(x-xhat,(x-xhat).T))
Das Problem ist die Derivate der Kosten in Bezug auf w1,b1,w2,b2,w3,b3
zu finden. Lassen Sie uns die Kosten S
nennen.
Nachdem ich mich abzuleiten und mich numerisch Überprüfung habe ich die folgenden Tatsachen festgestellt:
1) dSdxhat = (1/m) * np.dot(xhat-x)
2) dSdw3 = np.dot(h2.T,dSdxhat)
3) dSdb3 = dSdxhat
4) dSdh2 = np.dot(dSdxhat, w3.T)
Aber ich kann nicht für das Leben von mir dSdz2 herausfinden. Es ist eine Backsteinmauer.
Von Chain-Regel sollte es sein, dass dSdz2 = dSdh2 * dh2dz2 aber die Dimensionen nicht übereinstimmen.
Was ist die Formel, um die Ableitung von S in Bezug auf z2 zu berechnen?
Bearbeiten - Dies ist mein Code für den gesamten Feed-Forward-Betrieb des Autoencoders.
import numpy as np
def g(x): #sigmoid activation functions
return 1/(1+np.exp(-x)) #same shape as x!
def gGradient(x): #gradient of sigmoid
return g(x)*(1-g(x)) #same shape as x!
def cost(x, xhat): #mean squared error between x the data and xhat the output of the machine
return (1.0/(2 * m)) * np.trace(np.dot(x-xhat,(x-xhat).T))
#Just small random numbers so we can test that it's working small scale
m = 5 #num of examples
n = 2 #num of features in each example
k = 2 #num of neurons in the hidden layer of the autoencoder
x = np.random.rand(m, n) #the data, shape (m, n)
w1 = np.random.rand(n, k) #weights from input layer to hidden layer, shape (n, k)
b1 = np.random.rand(m, k) #bias term from input layer to hidden layer (m, k)
z1 = np.dot(x,w1)+b1 #output of the input layer, shape (m, k)
h1 = g(z1) #input of hidden layer, shape (m, k)
w2 = np.random.rand(k, n) #weights from hidden layer to output layer of the autoencoder, shape (k, n)
b2 = np.random.rand(m, n) #bias term from hidden layer to output layer of autoencoder, shape (m, n)
z2 = np.dot(h1, w2)+b2 #output of the hidden layer, shape (m, n)
h2 = g(z2) #Output of the entire autoencoder. The output layer of the autoencoder. shape (m, n)
w3 = np.random.rand(n, n) #weights from output layer of autoencoder to entire output of the machine, shape (n, n)
b3 = np.random.rand(m, n) #bias term from output layer of autoencoder to entire output of the machine, shape (m, n)
xhat = np.dot(h2, w3)+b3 #the output of the machine, which hopefully resembles the original data x, shape (m, n)
Sind Sie sicher, dass Ihre Dimensionen nicht ausgerichtet sind, nur weil Sie die Bias-Einheiten zu Ihrer Liste von h2-Einheiten hinzugefügt haben? Das Derivat scheint mir gut zu sein. – Paul
Nun, der Unterschied in den Formen ist größer als 1, also kann es nicht der Verzerrungsterm sein. Und ich berücksichtige auch den Bias-Begriff in meinen Derivaten. –
Apropos deine Voreingenommenheitsbegriffe - normalerweise würdest du eine konstante Voreingenommenheit anwenden (und den Wert davon lernen), und nicht eine andere bei jeder Iteration (dh sie sollten die Form (k,) und (n,) haben). Es gibt nicht viel, was du verallgemeinern kannst, wenn es sich für jede Eingabe ändert. Etwas anderes, das mich verwirrt, ist, dass du eindeutig zwei versteckte Ebenen hast, aber sag, dass du nur eine hast. Ich denke, es wäre hilfreich, wenn du den Code für die vollständige Implementierung - dann können wir sehen, was andere Shenanigans Sie tun. – Paul