[PYTHON] Eine Geschichte und ihre Implementierung, dass beliebige a1 * a2-Daten durch ein dreischichtiges neuronales ReLU-Netzwerk mit a1- und a2-Zwischenneuronen ohne Fehler dargestellt werden können.

Einführung

Dieser Artikel ist eine Implementierung des Dokuments "Expressive Anzahl von zwei oder mehr Hide Layer ReLU-Neuronalen Netzen".

Gliederung

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.

Ausführungsbeispiel

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.

Implementierung

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).

Veränderbare Parameter

Anzahl der Neuronen

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.

Daten zu geben

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.

Handel

# 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.

Wenn die Ausgabe m-dimensional ist

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.

Zusammenfassung

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

Eine Geschichte und ihre Implementierung, dass beliebige a1 * a2-Daten durch ein dreischichtiges neuronales ReLU-Netzwerk mit a1- und a2-Zwischenneuronen ohne Fehler dargestellt werden können.
Aufbau eines neuronalen Netzwerks, das XOR durch Z3 reproduziert
[Python] Zeichnen Sie mit Plotly Höhendaten auf eine sphärische Oberfläche und zeichnen Sie einen Globus, der rund und rund gedreht werden kann
Rufen Sie eine Liste der Kameraparameter ab, die mit cv2.VideoCapture festgelegt werden können, und machen Sie daraus einen Wörterbuchtyp
Implementierung eines zweischichtigen neuronalen Netzwerks 2
Implementieren Sie ein Modell mit Status und Verhalten (3) - Beispiel für die Implementierung durch den Dekorateur
Artikel, der eine Person sein kann, die den Mechanismus der API versteht und beherrscht (mit Python-Code)
Das Ergebnis war besser, als die Trainingsdaten des Mini-Batches als Hybrid aus fest und zufällig mit einem neuronalen Netzwerk erstellt wurden.
Implementierung eines 3-Schicht-Neuronalen Netzwerks (kein Lernen)
Formatieren Sie DataFrame-Daten mit Pytorch in ein Formular, das mit NN trainiert werden kann
Ich habe versucht, einen x86-Bootloader zu erstellen, der vmlinux mit Rust booten kann