Dieser Artikel ist eine Implementierung des Dokuments "Expressive Anzahl von zwei oder mehr Hide Layer ReLU-Neuronalen Netzen".
Stellen Sie sich ein zweischichtiges neuronales Zwischenschichtnetzwerk vor, in dem die Aktivierungsfunktion die ReLU-Funktion ist, die Eingabe n-dimensional und die Ausgabe eindimensional ist. Wenn die Anzahl der intermediären Neuronen a1 und a2 in der Reihenfolge von der Eingabeseite ist, gibt es einen neuronalen Netzwerkparameter, der diese Daten mit einem Fehler von 0 für beliebige a1 * a2-Eingabe- / Ausgabedaten ausdrückt. Hier bedeutet "Ausdrücken von Eingabe- / Ausgabedaten mit einem Fehler von Null", dass, wenn jede Eingabedaten an das neuronale Netzwerk übergeben werden, ein Wert zurückgegeben wird, der den entsprechenden Ausgabedaten entspricht. Zusammenfassend lässt sich sagen, ** wenn die Trainingsdaten beim maschinellen Lernen a1 * a2 oder weniger sind, gibt es immer ein Konvergenzziel für das Lernen **. (Nur die Existenz des Konvergenzziels zu sagen, bedeutet jedoch nicht, dass das Lernen tatsächlich konvergiert.) Wenn beispielsweise 10.000 eindimensionale Trainingsdaten ausgegeben werden, können alle Daten mit 0 Fehlern im neuronalen ReLU-Netzwerk mit 100 Zwischenneuronen und 100 Zwischenschichten und 2 Schichten ausgedrückt werden. Diese Tatsache hängt nicht von der Eingabedimension der Daten ab, sodass es keine Rolle spielt, wie groß die Eingabedimension ist. (Wenn die Ausgabe nicht eindimensional ist, wird sie später beschrieben.) Der Beweis befindet sich im Originalpapier, daher werde ich ihn weglassen, aber in diesem Artikel werde ich ein Programm vorstellen, das tatsächlich eine Reihe von Parametern anzeigt, die das Konvergenzziel darstellen. Ich werde. Sehen Sie sich zunächst das Ausführungsbeispiel an.
Dies ist ein Beispiel für ein neuronales ReLU-Netzwerk mit 5 Dimensionen für die Eingabe, 3 und 3 Zwischenneuronen in der Reihenfolge von der Eingabeseite und 1 Dimension für die Ausgabe und Ausgabeparametern, die 3 * 3 = 9 Daten darstellen.
$python3 NNH2.py
( 5 , 3 , 3 , 1 ) ReLU neural network
the number of data = 9
input =
[[93 59 58 20 80 57 35 21 38]
[ 4 91 47 69 98 85 68 2 15]
[14 60 31 86 37 12 23 69 42]
[ 4 14 52 98 72 60 67 51 90]
[27 12 6 32 76 63 49 41 28]]
output =
[ 1 81 17 65 25 33 45 77 10]
parameters
1st layer
W1 =
[[Fraction(823849691, 1) Fraction(4336051, 1) Fraction(28907, 1)
Fraction(149, 1) Fraction(1, 1)]
[Fraction(823849691, 1) Fraction(4336051, 1) Fraction(28907, 1)
Fraction(149, 1) Fraction(1, 1)]
[Fraction(823849691, 1) Fraction(4336051, 1) Fraction(28907, 1)
Fraction(149, 1) Fraction(1, 1)]]
b1 =
[[Fraction(-16778681974, 1)]
[Fraction(-60502822101, 2)]
[Fraction(-48495714637, 1)]]
2nd layer
W2 =
[[Fraction(148, 1) Fraction(-9237952317912, 35473138591)
Fraction(4049615396998340012232, 18010928872046123981)]
[Fraction(15800556778618364518367199397870934943209115691793, 1077111270972508432064314372084032376028236629)
Fraction(-11216317162890245084133171070123933902029519034081603343913003835232890, 434989745706342223538442515057047029191074444247675999926788518821)
Fraction(2686834406446276617746833568279126654074919365089537293846487174104542, 224870468718735937295513181927691380500164378143178284849730556247)]
[Fraction(843610077776665412761527367413211990104912799146270139270113712675305808525969059554219936165800, 154068217051841137536218687813904006692418581384372306328955832146429671252437697)
Fraction(-57625119985396507975392986118005960657818304694554844951150042194684795633743261029837087833785575305876950, 5262027877233168541064334417747189692030849998640803800770876843784630220816492104662661549)
Fraction(100319159657643248312549073786161213853603634088990731217920689495343417295177190966187025547162361565044553868359914, 11390289225651438251169009216834446835092039706616191741035899343815780751119047453235035761689895223)]]
b2 =
[[Fraction(-99, 1)]
[Fraction(-31282288621675736677206673372946695670689268182842, 4042938352270697695885621047346217759)]
[Fraction(-912723226773529956403403228639959057460803178243124784475781762180477870767754518136094, 13495462068042154164632946308945540668991317744154109409049607)]]
3rd layer
W3 =
[[ 1 -1 1]]
b3 =
[[16]]
check
MP(x) = [Fraction(1, 1), Fraction(81, 1), Fraction(17, 1), Fraction(65, 1), Fraction(25, 1), Fraction(33, 1), Fraction(45, 1), Fraction(77, 1), Fraction(10, 1)]
output= [ 1 81 17 65 25 33 45 77 10]
MP(x) - output = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Wenn Sie in der Reihenfolge erklären, Zunächst können alle 3 * 3 = 9 Eingabe- / Ausgabedaten ausgedrückt werden. Geben Sie die Daten also wie folgt an.
input =
[[93 59 58 20 80 57 35 21 38]
[ 4 91 47 69 98 85 68 2 15]
[14 60 31 86 37 12 23 69 42]
[ 4 14 52 98 72 60 67 51 90]
[27 12 6 32 76 63 49 41 28]]
output =
[ 1 81 17 65 25 33 45 77 10]
Dies bedeutet Daten, so dass die Ausgabe, die der Eingabe "[[93] [4] [14] [4] [27]]" entspricht, "[1]" ist, und solche Eingabe- / Ausgabedaten sind Neun stehen in einer Reihe. In diesem Beispiel werden die Daten als Zufallszahl angegeben, es können jedoch auch konkrete Daten angegeben werden.
Für die gegebenen Daten sind der Gewichtswert und der Vorspannungswert jeder Schicht, die die Parameter des neuronalen Netzwerks sind, das sie ausdrückt, die erste Schicht "W1", "b1", die zweite Schicht "W2", "b2", 3. Es wird als Layer W3
und b3
ausgegeben. (Bruch (n, m)
repräsentiert eine rationale Zahl $ \ frac {n} {m} $.)
1st layer
W1 =
[[Fraction(823849691, 1) Fraction(4336051, 1) Fraction(28907, 1)
Fraction(149, 1) Fraction(1, 1)]
[Fraction(823849691, 1) Fraction(4336051, 1) Fraction(28907, 1)
Fraction(149, 1) Fraction(1, 1)]
[Fraction(823849691, 1) Fraction(4336051, 1) Fraction(28907, 1)
Fraction(149, 1) Fraction(1, 1)]]
b1 =
[[Fraction(-16778681974, 1)]
[Fraction(-60502822101, 2)]
[Fraction(-48495714637, 1)]]
...
Der Nenner und der Zähler des Parameters werden als sehr groß berechnet, aber die Ausgabe des neuronalen Netzwerks für jede der neun Eingaben ist jeweils sauber teilbar
MP(x) = [Fraction(1, 1), Fraction(81, 1), Fraction(17, 1), Fraction(65, 1), Fraction(25, 1), Fraction(33, 1), Fraction(45, 1), Fraction(77, 1), Fraction(10, 1)]
Es wird sein. Vergleichen des tatsächlichen Fehlers mit der Ausgabe der Originaldaten,
MP(x) - output = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
Und Sie können sehen, dass der Fehler 0 ist. (Zur besseren Lesbarkeit in den Typ "float" konvertiert.) Dieses Ergebnis hängt nicht von den Eingabe- / Ausgabedaten, der Eingabedimension oder der Anzahl der Zwischenneuronen ab, und der Fehler sollte bei jedem Wert 0 sein.
Der Algorithmus ist der Beweis für Teorem 3 des Originalpapiers und "Ausdrucksfähigkeit des neuronalen Netzwerks basierend auf der Anzahl der ausdrucksfähigen Daten" Ich bezog mich auf den Beweis von Satz 3 von J102-D & num = 6 & abst =). Insbesondere handelt es sich um ein Programm, das eine Lösung der simultanen Gleichungen berechnet, die während des Beweises erhalten wurden. Es ist jedoch ziemlich kompliziert, da eine gegenseitige rekursive Graduierungsformel mit zwei Variablen angezeigt wird. Wenn Sie also die Details wissen möchten Originalarbeithier ist. Klicken Sie hier, um den Python-Implementierungscode anzuzeigen (https://github.com/nekonistyle/Python).
python
# constants
idim = 5 # the number of input neurons
a1 = 3 # the number of 1st hidden neurons
a2 = 3 # the number of 2nd hidden neurons
N = a1 * a2 # the number of data (do not change)
"idim" ist die Eingabedimension und "a1" und "a2" sind die Anzahl der Zwischenneuronen in der ersten bzw. zweiten Schicht.
N = a1 * a2
ist die Anzahl der Daten und sollte nicht geändert werden.
idata = randomidata(idim,idataRange) # input data must be unique
odata = randomodata(odataRange)
"idata" sind die Eingabedaten und müssen eine "idim" × "N" -Matrix sein und der gleiche Spaltenvektor existiert nicht. "odata" sind die Ausgabedaten und müssen ein "N" -Dimensionsvektor sein. In diesem Beispiel ist der Datenbereich begrenzt, um Zufallszahlen zu erhalten, aber in der Realität ist es auch nicht erforderlich, ihn zu begrenzen, und Parameter können mit beliebigen Werten berechnet werden.
# select division operator ('Fraction' or '/')
divop = fractions.Fraction
# divop = lambda x,y: x / y
Da nur vier Regeln zur Berechnung der Parameter verwendet werden, wird der Commerce-Divop durch die rationale Zahlenoperation "Fraction" definiert, kann jedoch in die unbewegliche Dezimalzahloperation "/" geändert werden. Es kann jedoch durch eine sehr große Zahl geteilt werden, und wenn es "/" ist, kann der Fehler groß sein, seien Sie also vorsichtig.
Aus Satz 4 des Originalpapiers können, wenn die Ausgabe m-dimensional ist, $ a_1 (a_2 \ Operatorname {div} m) + a_2 \ Operatorname {mod} m $ Daten ausgedrückt werden. (Obwohl es nicht implementiert ist, kann es auf die gleiche Weise hergestellt werden, indem die Parameter umgeleitet werden, wenn die Ausgabe eindimensional ist.) Das heißt, wenn die Zwischenneuronen in der zweiten Schicht zu Vielfachen der Ausgangsdimension gemacht werden [Anzahl der Trainingsdaten] x [Ausgabedimension] ≤ [Anzahl der Zwischenneuronen in der ersten Schicht] x [Anzahl der Zwischenneuronen in der zweiten Schicht] Da es ausgedrückt werden kann, wenn es beispielsweise erfüllt, wenn die Trainingsdaten 10.000 und die Ausgabe 10 Dimensionen sind, können alle Daten durch ein neuronales Netzwerk mit 400 Zwischenneuronen und 250 Zwischenneuronen ausgedrückt werden.
Ich erklärte ein Programm, das eine Reihe von Parametern ausgibt, die die gegebenen Daten von a1 * a2 im neuronalen ReLU-Netzwerk der Schichten der mittleren Schicht 2 ausdrücken, wobei die Anzahl der Zwischenneuronen a1 und a2 beträgt. Die von diesem Programm ausgegebenen Parameter scheinen sehr große absolute Werte zu haben, aber es wird angenommen, dass ein solches Ergebnis aufgrund der Parameterberechnungsformel erhalten wurde, die für alle verzerrten Daten ausgedrückt werden kann. Glücklicherweise sind die Parameter, die bestimmte Daten darstellen, im Allgemeinen nicht eindeutig, sodass einige Daten durch Parameter mit kleineren absoluten Werten dargestellt werden können.
Recommended Posts