JNeuroJam 
JNeuroJam ist ein Programm zur Demonstration der assoziativen Speicherfähigkeit eines
künstlichen neuronalen Netzes (KNN)
(speziell eines Feedforward Netzes) anhand von einfachen Musikstücken. JNeuroJam kann einfache Lieder
"auswendig" lernen, diese wiedergeben und simuliert eine einfache Art des Improvisierens auf den gelernten Musikstücken.
Index
Die grafische Benutzeroberfläche
Karteireiter Netz
Karteireiter Lieder
Karteireiter Jammen
Karteireiter Gewichtsstruktur
Karteireiter Training
Karteireiter Lernverfahren
Techniken in JNeuroJam
Repräsentation von Musiknoten in JNeuroJam
Standard Notenkodierung
Simple Notenkodierung
Noten-Klassifizierende Notenkodierung
Voll-Klassifizierende Notenkodierung
Sequenzenlernen mit der Zeitfenstertechnik
Das Training und die Fehlertypen
Average Absolute Error (avg. ABSE)
Average Sum of Squared Errors (avg. SSE)
Average Root Mean Square Error (avg. RMSE)
Maximum ABSE by a Single Output Neuron (max. Neuron ABSE)
Das Jammen
Max. Klassifikator
Random Klassifikator
Referenzen
Download
Die Benutzungsoberfläche von JNeuroJam 3 ist auf 7 Ansichten aufgeteilt, die jeweils über einen Karteireiter
oben ausgewählt werden können. Im folgenden werden die verschiedenen Ansichten erläutert.
Unter der Ansicht "Netz" kann das zu trainierende Netz in seiner Struktur definiert werden. Dies wird
über die Ein- sowie Ausgabekodierung und die Anzahl der verdeckten Neuronen gemacht.
Netz laden: Ein vorher gespeichertes Netz kann hiermit aus einer Datei geladen werden.
Zu beachten ist, dass das zu ladende Netz dieselbe Eingangs- / Ausgangsgröße hat wie im
Feld "Eingabeneuronen" / "Ausgabeneuronen" auf der rechten Seite angegeben ist.
Diese Funktion ist in der Appletversion nicht verfügbar.
Netz speichern: Das aktuelle Netz wird in einer beliebigen Datei gespeichert.
Diese Funktion ist in der Appletversion nicht verfügbar.
Initialisiere Kantengewichte: Hiermit werden die Kantengewichte des Netzes wieder
auf zufällige Werte initialisiert.
Inputpattern Kodierung: Auswahl der Notenkodierung für das Inputpattern.
Je nach Notenkodierung ist es nötig, verschiedene Anzahlen an Eingangsneuronen zu
haben, die automatisch erzeugt werden. Zur Auswahl stehen die Notenkodierungen Simple,
Noten-Klassifikation und Volle Klassifikation.
Outputpattern Kodierung: Auswahl der Notenkodierung für das Outputpattern.
Je nach Notenkodierung ist es nötig, verschiedene Anzahlen an Ausgangsneuronen zu haben,
die automatisch erzeugt werden. Zur Auswahl stehen die Notenkodierungen Simple,
Noten-Klassifikation und Volle Klassifikation.
Lernfenstergröße: Anzahl der Noten aus dem Lied, die dem Netz gleichzeitig
als Ausschnitt repräsentiert werden sollen. Aus der gewählten Inputpattern Kodierung
und der Lernfenstergröße ergibt sich die Größe der Eingabeschicht.
Hiddenlayergrößen: Anzahl der Neuronen für die verborgenen Schichten des Netzes.
Die Größen der Schichten sind durch Kommas zu trennen. Es sind beliebig viele verborgene Schichten möglich.
Unter dem Karteireiter "Lieder" kann man Liederdateien laden, entfernen, erstellen und die aktuellen Lerndaten speichern.
Die Lade- und Speicherfunktionalitäten sind in der Appletversion deaktiviert.
Lieder können über den einfachen Texteditor auf der rechten Seite erstellt werden. Hierzu
muss lediglich über den Button "Leeres Lied" ein neues Lied erstellt und anschließend aus der Liste
der verfügbaren Lieder ausgewählt werden.
Unter dem Karteireiter "Jammen" kann das trainierte Netz mit Anfangsnoten gefüttert
werden, damit es den Rest selbst reproduziert. Hier kann man die tatsächliche
Fähigkeit des Netzes überprüfen.
Linke Fensterhälfte: Hier wird das Lied ausgewählt, dessen Anfang dem
Netz präsentiert werden soll. Danach reproduziert das Netz selber die nächsten Noten.
Netzausgabe Interpret: Hier wird festgelegt, wie die Ausgabe des Netzes
als Note zu interpretieren ist. Der Netzausgabe Interpret ist abhängig von
der unter Netz benutzten Outputpattern Kodierung. Für die Outputpattern Kodierungen
Noten-Klassifikator und Voll-Klassifikator sind die bereits erwähnten Interpreten möglich:
Max. Klassifikator und Random Klassifikator.
Netz abspielen: Hier wird das Netz aktiviert und spielt entsprechend dem im linken
Teil des Fensters ausgewählten Liedes.
Unter dem Karteireiter "Gewichtsstruktur" kann man sich eine grafische Repräsentation der
Netzgewichte anschauen. Mit der Maus kann ein Kantengewicht fokussiert werden, worauf hin
genauere Informationen über die Kante (ausgehendes Neuron, eingehendes Neuron, Gewichtswert) erscheinen.
Die Farben der Felder repräsentieren den Wert des Gewichtes:
Weiss: Das Gewicht hat den Wert 0 und ist somit eine nicht vorhandene Kante.
Grün: Positive Kantengewichte. Je leuchtender das Grün ist, desto höher ist der Gewichtswert.
Rot: Negative Kantengewichte: Je leuchtender das Rot ist, desto größer ist der negative Gewichtswert.
Unter dem Karteireiter "Training" kann das Training des Netzes gesteuert und der Netzfehler grafisch verfolgt werden.
Netzfehlertyp: Auswahl des zu verfolgenden Netzfehlertyps. Der Netzfehlertyp repräsentiert
die Abweichung der Netzausgabe zu den gegebenen Lerndaten. Als Netzfehlertypen stehen zur Verfügung:
avg. ABSE: Der durchschnittliche absolute Fehlerbetrag.
avg. SSE: Der durchschnittliche quadratische Fehlerbetrag.
avg. RMSE: Der Durchschnitt der Quadratwurzeln der quadratischen Fehlerbeträge.
max. Neuron ABSE: Der absolute Fehlerbetrag des Neurons mit dem größten absoluten Fehlerbetrag.
Zu traininerende Lernschritte: Anzahl der Lernschritte, nach denen das Training
automatisch gestoppt wird. Es wird gelernt, bis entweder die zu trainierende Anzahl an
Lernschritten durchgeführt wurde, oder der angegebene maximale Fehlerwert erreicht wird.
Max. Fehlertyp: Der Grenzwert des gewählten Fehlertyps, bei dem das Training
automatisch gestoppt wird. Es wird gelernt, bis entweder die zu trainierende Anzahl an
Lernschritten durchgeführt wurde, oder der angegebene maximale Fehlerwert erreicht wird.
Lerndatensatz zufällig aussuchen: Wir dieses Feld aktiviert, so wird die
Reihenfolge der zu lernenden Trainingsdatensätze zufällig ausgesucht.
Start training: Hiermit wird das Training gestartet.
Fehler Graf: Eine grafische Repräsentation des ausgewählten Fehlertyps.
Unter dem Karteireiter "Lernverfahren" kann das Lernverfahren für das Training des
Netzes ausgesucht und konfiguriert werden. Für weitere Details zu den Lernverfahren
empfiehlt sich die Literatur "Advanced Supervides Lerning in Multi-layer Perceptrons -
From Backpropagation to Adaptive Learning Algorithms" von Martin Riedmiller oder das
neuronale Netze Skript von Prof. Dr. Westenberger.
Training Algorithmus: Hier kann zwischen den verfügbaren Lernverfahren ausgesucht
werden. Je nach Lernverfahren stehen verschiedene Parameter zur Verfügung.
Backprop + Momentum: Das klassische (Offline) Backpropagation Verfahren mit Momentumterm.
QuickProp: Das schnelle Quick-Propagation Verfahren ohne Weightdecay oder Momentumterm.
QuickProp basiert auf dem Newtonschen Gradientenabstiegsverfahren.
RProp: Das schnelle Resilnt-Propagation Verfahren ohne Weightdecay.
RProp kombiniert das SuperSAB und das QuickProp Verfahren.
RProp + Weight decay: Das Resilient-Propagation Verfahren mit Weightdecay.
SuperSAB: Das SuperSAB Verfahren ohne Weightdecay oder Momentumterm.
Das SuperSAB Verfahren benutzt für jedes Gewicht eine individuelle variable Lernrate.
Parameter zurücksetzen: Hiermit werden die Parameter des Lernverfahrens auf die
Standardwerte zurückgesetzt.
Um Notenfolgen in ein KNN einzuspeisen wird eine Kodierung der möglichen Eingaben benötigt.
Grundsätzlich sind die hier benutzten drei wichtigsten Attribute einer zu spielenden Note ihre Tonhöhe (c, d, e, f, g, a, h),
die Oktave der Tonhöhe (hier 1. bis 3. Oktave) sowie die Länge (Tondauer) der Note, angegeben in 1 (ganzer Takt),
1/2 (halber Takt), 1/4 (viertel Takt) und 1/8 (achtel Takt).
Das von JNeuroJam benutzte Format für Liederdateien enthält genau solche Informationen, kodiert in einfache
Notendarstellungen, die sich aus Tonhöhe, Oktave und Tonlänge zusammensetzt.
So steht der Text c14 für das c der ersten Oktave mit einer viertel Tonlänge.
Da KNN als Eingabe Zahlen erwarten, müssen diese drei Informationen auch in Zahlenwerte
transformiert werden (Kodierung). Hierfür gibt es mehrere Möglichkeiten, die im folgenden erörtert werden.
Wird ein Lied aus einer Datei geladen, so wird diese aus dem Textformat zuerst in die
Standard Notenkodierung umgewandelt. Die Standard Notenkodierung dient als Zwischenformat
für alle anderen Formate, da ein KNN verschiedene Eingabe- und Ausgabekodierungen haben kann.
Erst durch diese Kodierung kann die Ausgabe des KNN vom Ausgabeformat über das Standardformat
wieder als Eingabeformat kodiert werden, um dem KNN erneut als Eingabe präsentiert zu werden.
So kann das KNN sich selbst mit Daten versorgen.
Ohne Standardkodierung müsste für jede Kodierung eine Umwandlung in alle anderen Kodierungen geschrieben werden.
Bei der Standard Notenkodierung wird jedem Attribut eine Zahl zugewiesen,
wodurch sich für jede Note ein Zahlentripel ergibt.
Die Tonhöhe wird auf die Werte von 0 bis 6 (c=0, d=1, ...), die Oktave auf die Werte 0-2
(1.Oktave = 0), sowie die Tonlänge auf die Werte 0 bis 3 (ganzer Takt = 0, halber Takt = 1, ...)
kodiert. Die Notenfolge c14 e12 g21 wird somit zum Muster 0 0 2 2 0 1 4 1 0 kodiert.
Die Standard Notenkodierung wird intern für alle Datensätze benutzt. Bei bedarf werden andere
Kodierungen aus dieser Kodierung umgewandelt.
Als Eingabe für ein neuronales Netz ist diese Kodierung jedoch nicht sehr gut geeignet,
da der Wertebereich der Eingabeneuronen üblicherweise zwischen -1 und +1 bzw.
zwischen 0 und +1 liegt. In diesem Bereich sind die Eingabeneuronen "sensibler".
Die Simple Notenkodierung benutzt für die Kodierung einer Note jeweils drei Werte,
ähnlich der Standardkodierung. Lediglich der Wertebereich ist verschieden.
Die Tonhöhe wird auf die Werte von 0.1 bis 0.7 (c=0.1, d=0.2, ...), die Oktave auf die
Werte von 0.1 bis 0.3 (1.Oktave = 0.1) sowie die Tonlänge auf die Werte 0.0 bis 0.3
(ganzer Takt = 0.0, halber Takt = 0.1, ...) kodiert. Die Notenfolge c14 e12 g21 wird somit
zu den Lerndatensätzen 0.1 0.1 0.2 0.3 0.1 0.1 0.5 0.2 0.0 kodiert.
Die Simple Notenkodierung entspricht eher dem sensiblen Bereich der Eingabeneuronen. Dennoch ist
diese Kodierung nicht besonders gut.
Man beachte, dass ein größerer Wert für einen stärkeren Reiz steht. So wird durch diese Kodierung bereits suggeriert,
dass die Note e mit 0.3 relevanter, da intensiver, ist als die Note c mit dem Reizpotential 0.1.
Außerdem sollten redundantere Kodierungen dem Netz helfen, unempfindlicher gegen auftretende Fehlinterpretationen
zu werden. Macht das Netz eine fehlerhafte Interpretation einer Eingabe mit einen eigentlich kleinen
Fehler von z.B. 0.1, so liegt der tatsächliche Fehler bereits bei einer ganzen Tonhöhe,
und das nur Aufgrund der Kodierung.
Die Noten-Klassifizierende Notenkodierung benutzt für die Kodierung einer Note bereits 9 Werte, von denen 7
die Tonhöhe und jeweils eine die Oktave und die Tonlänge repräsentieren.
Die Tonhöhe wird durch 7 Werte repräsentiert, wobei jeder Wert einer der 7 möglichen Tonhöhen entspricht.
Es wird jeweils nur einer der Werte auf +1 gesetzt, alle anderen auf 0. Diejenige Tonhöhe, für die
der Wert +1 gesetzt wurde, wird als Tonhöhe interpretiert.
c | d | e | f | g | a | h |
Wert 1 | Wert 2 | Wert 3 | Wert 4 | Wert 5 | Wert 6 | Wert 7 |
Im Prinzip ist dies eine binäre Kodierung für die Tonhöhe. Solche Kodierungen werden,
da nur eines von mehreren Werten etwas signalisiert, auch als "1 von n"-Klassifikationen bezeichnet.
Die Tonhöhe c wird entsprechend zu 1.0 0.0 0.0 0.0 0.0 0.0 0.0 und die Tonhöhe d zu
0.0 1.0 0.0 0.0 0.0 0.0 0.0 kodiert. Diese Kodierung wird auch dem Prinzip, dass jede
Eigenschaft gleich wichtig ist, gerecht.
Die Oktave und die Tonlänge werden genauso wie bei der Simple Notenkodierung kodiert.
Die Notenfolge c14 e12 g21 wird somit zu den Lerndatensätzen
1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.1 0.2
0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.1 0.1
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.2 0.0
kodiert.
Die Aufteilung der Tonhöhe in jeweils eigene Werte verbessert das Lernverhalten in der Art,
dass bei der Tonhöhe selbst gröbere Fehler zu keinem tatsächlichen Fehler führen.
So können sogar die Werte 0.9 0.3 0.1 0.2 0.1 0.1 0.2 für die Tonhöhe korrekt als ein c
interpretiert werden. (Vorausgesetzt, man interpretiert diese Werte so, dass der höchste Wert ausschlaggebend ist.)
Was der Kodierung der Tonhöhe hilft, wird bei der Voll-Klassifizierenden Notenkodierung auch
auf die Oktave und die Tonlänge angewendet. Eine Note wird somit durch 14 Werte repräsentiert,
von denen die ersten 7 der Tonhöhe entsprechen, genauso wie bei der Noten-Klassifizierenden
Notenkodierung. Die Oktave wird durch 3 Werte kodiert, die ebenfalls "1 von n" kodiert werden:
Oktave 1 | Oktave 2 | Oktave 3 |
Wert 1 | Wert 2 | Wert 3 |
Die Tonlänge wird mit 4 Werten ebenfalls "1 von n" kodiert:
Ganzer Takt | Halber Takt | Viertel Takt | Achtel Takt |
Wert 1 | Wert 2 | Wert 3 | Wert 4 |
Die Notenfolge c14 e12 g21 wird somit zum Muster
1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0
0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0 0.0
kodiert.
Zwar führt diese Kodierung zu einer recht großen Datenmenge (pro Note sind das 14 Werte),
dafür aber lernt das KNN in weniger Lernzyklen und ist auch bei der Wiedergabe viel robuster.
Da das KNN nicht nur einzelne Noten, sondern eine zeitliche Folge lernen soll, wird das zu lernende Lied
derart aufgeteilt, dass eine Eingabe in das KNN die darauf folgende Note reproduziert. Im
Folgenden ein Auszug aus der Praktikumsaufgabe zum gleichen Thema von Prof. Dr. Westenberger:
"Musik ist ein dynamischer Zeitprozess. Wir werden für den Lernprozess die Zeitfenstertechnik verwenden,
ein typisches Verfahren, um Zeitprozesse lernbar zu machen. Es gibt dazu auch alternative neuronale
Ansätze, z.B. Jordan- oder Elman-Netze, auf die wir im Rahmen dieses Praktikums nicht eingehen können.
Eine Sequenz S = s0 , s1 , s2 , s3 ... si aus der Menge W ist eine endliche oder unendliche Folge von Symbolen
aus einer Symbolmenge W. Beim Sequenzen-Lernen ist eine Funktion f zu erlernen, die alle Symbole der
Sequenz W in Abhängigkeit der zuvor aufgetretenen Symbole bestimmt. Im praktischen Fall
müssen wir uns auf eine endliche Teilsequenz, den sogenannten Kontext, beschränken:
si = f ( si-1 , si-2 , ....s3i-k).
Die Teilsequenz ( si-1 , si-2 , ....s3i-k) heisst linker Kontext von si mit der Kontextlänge k.
Im allgemeinen können Wiederholungen von Teilsequenzen in einer Sequenz kommen. Zum Beispiel tritt
in der Sequenz M I S S I S S I P I die Teilsequenz ISSI zweimal auf. Mit einer Kontextlänge 4
lässt sich hier also keine eindeutige Funktion f bestimmen, weil einmal ein S und beim zweiten Mal ein P folgt..
In der Musikinformatik wird die Symbolmenge aus den Tönen zumeist einer Tonart gebildet.
Sequenzen sind hier also Tonsequenzen, die in der Regel ein Lied bilden. Im Zusammenhang mit der
Zeitreihenprognose wird dieses Vorgehen auch als Zeitfenstertechnik bezeichnet.
[...]
Die praktische Aufbereitung der Lerndaten stellen wir am Beispiel der Kontextlänge 5 vor.
Es werden die Töne der C-Tonleiter {C, D, E, F, G, A, H} für die Codierung verwenden.
Der erste Datensatz würde also c14 d14 e14 f14 g14 auf a14 abbilden, also die Töne 1, 2, 3, 4, 5
der ersten Oktave auf den Ton a (6.Ton) der ersten Oktave."
Damit lernt das KNN aus einem Anfang die folgende Note zu prognostizieren.
Wird nun die prognostizierte Note an den bereits gegebenen Anfang angehangen, so kann die
nächste Note vom Netz reproduziert werden, wodurch sich eine Art "Perpetuum Mobile" ergibt.
Ein KNN versucht ein bestimmtes Fehlermaß zu minimieren, welches sich aus der Differenz der
Ist und Soll-Ausgabe des Netzes ergibt. Es gibt weitere Fehlermaße, die aus dieser Differenz
ermittelt werden können und den aktuellen Lernstatus des Netzes besser wiedergeben als das interne
Fehlermaß. Im folgenden werden die bekanntesten und auch in der mscJNeuralNet-API unterstützten Fehlermaße vorgestellt.
Der durchschnittliche absolute Fehlerbetrag des Netzes wird wie folgt berechnet:
Durchschnitt der absoluten Summen aller Lerndatensätze = 0
Für alle Lerndatensätze
Summe Absoluter Fehler aktueller Lerndatensatz = 0
Für alle Ausgabeneuronen
// Fehler für ein Neuron und einen Lerndatensatz
Absoluter Fehler aktuelles Neuron =
Math.abs(Soll Wert aktuelles Neuron - Ist Wert aktuelles Neuron)
// Summe der Fehler für einen Lerndatensatz
Summe Absoluter Fehler aktueller Lerndatensatz +=
absoluter Fehler aktuelles Neuron;
Durchschnitt der absoluten Summen aller Lerndatensätze +=
Summe Absoluter Fehler aktueller Lerndatensatz
Durchschnitt der absoluten Summen aller Lerndatensätze /=
Anzahl Lerndatensätze
Der avg. ABSE ist also der Durchschnitt der Abstände aller Originalmuster zu den vom Netz reproduzierten Mustern.
Durchschnitt der Fehlerquadratsummen aller Lerndatensätze. Bei der avg. SSE
Berechnung wird nicht der normale Abstand zwischen Originalmuster zu den vom Netz reproduzierten
Mustern gebildet, sondern der quadratische Abstand (nach Gauss' Methode der kleinsten Quadrate).
Er wird wie folgt berechnet:
Durchschnitt der quadratischen Fehler aller Lerndatensätze = 0
Für alle Lerndatensätze
Summe der quadratischen Fehler aktueller Lerndatensatz = 0
Für alle Ausgabeneuronen
// Fehler für ein Neuron und einen Lerndatensatz
Quadratischer Fehler aktuelles Neuron =
Math.pow(Soll Wert aktuelles Neuron - Ist Wert aktuelles Neuron, 2.0);
// Summe der Fehler für einen Lerndatensatz
Summe der quadratischen Fehler aktueller Lerndatensatz +=
Quadratischer Fehler aktuelles Neuron;
Durchschnitt der quadratischen Fehler aller Lerndatensätze +=
Summe der quadratischen Fehler aktueller Lerndatensatz
Durchschnitt der quadratischen Fehler aller Lerndatensätze /=
Anzahl Lerndatensätze
Durchschnitt der Quadratwurzeln der quadratischen Fehler aller Lerndatensätze.
Wie bei der SSE Berechnung wird hier das Quadrat der Abstände benutzt, am Ende
jedoch die Quadratwurzel gezogen. Der RMSE wird auch mittlere quadratische Abweichung genannt.
Er wird berechnet als:
Durchschnitt der Quadratwurzeln der quadratischen Fehler aller Lerndatensätze = 0
Für alle Lerndatensätze
Summe der quadratischen Fehler aktueller Lerndatensatz = 0
Quadratwurzel der quadratischen Fehler aktueller Lerndatensatz = 0
Für alle Ausgabeneuronen
// Fehler für ein Neuron und einen Lerndatensatz
Quadratischer Fehler aktuelles Neuron =
Math.pow(Soll Wert aktuelles Neuron - Ist Wert aktuelles Neuron, 2.0);
// Summe der Fehler für einen Lerndatensatz
Summe der quadratischen Fehler aktueller Lerndatensatz +=
Quadratischer Fehler aktuelles Neuron;
Quadratwurzel der quadratischen Fehler aktueller Lerndatensatz =
Math.sqrt(
Summe der quadratischen Fehler aktueller Lerndatensatz /
Anzahl der Ausgabeneuronen)
Durchschnitt der Quadratwurzeln der quadratischen Fehler aller Lerndatensätze /= Anzahl Lerndatensätze
Maximaler absoluter Fehlerbetrag eines einzelnen Ausgabeneurons. Hiermit kann festgestellt werden,
welches Neuron den größten absoluten Fehlerbetrag für ein Lerndatensatz erzeugt.
Es wird berechnet als:
Maximaler absoluter Fehlerbetrag eines Neurons = -1
Index des Neurons mit max. Fehlerbetrag = 0
Index des Lerndatensatzes mit max. Fehlerbetrag = 0;
Für alle Lerndatensätze
Für alle Ausgabeneuronen
// Fehler für ein Neuron und einen Lerndatensatz
Absoluter Fehler aktuelles Neuron =
Math.abs(Soll Wert aktuelles Neuron - Ist Wert aktuelles Neuron)
// Grösster Fehler für ein einzelnes Neuron
wenn (Absoluter Fehler aktuelles Neuron >
Maximaler absoluter Fehlerbetrag eines Neurons)
dann
Maximaler absoluter Fehlerbetrag eines Neurons =
Absoluter Fehler aktuelles Neuron
Index des Neurons mit max. Fehlerbetrag =
Index aktuelles Neuron
Index des Lerndatensatzes mit max. Fehlerbetrag =
Index aktueller Lerndatensatz
Der Fehlertyp kann je nach Notenkodierung verschieden interpretiert werden. Benutzt man z.B. die
Simple Notenkodierung, so liegt zwischen zwei verschiedenen Notenwerten wie C (0.1) und D (0.2)
ein Unterschied von 0.1. Geht man davon aus, dass das Netz 0.14 als 0.1 und 0.18 als 0.2 interpretiert
(Runden), so hat man eine Fehlertoleranz von 0.05. Dass heißt: falls das Netz bei einer Tonhöhe eine Abweichung
von mehr als 0.05 hat, so ist dieser Ton noch nicht korrekt gelernt.
Betrachtet man nun ein Fehlermaß wie das avg. ABSE, so wird der Fehler eines einzelnen Lerndatensatzes durch die
Bildung des Durchschnitts etwas verwischt. Hat man beim Trainieren einen avg. ABSE Wert von 0.04, so ist
dies der Durchschnitt mehrerer Lerndatensätze. So könnte ein Datensatz mit 0.01 korrekt gelernt worden sein,
während ein weiterer Datensatz mit 0..07 nicht korrekt erlernt worden ist. Der Durchschnitt wäre dann immer
noch 0.04 und würde suggerieren, dass alles korrekt gelernt wurde.
Daher ist es für jNeuroJam sinnvoll, den max. Neuron ABSE zu betrachten. Dies ist der größte absolute Fehlerbetrag
eines einzigen Neurons. Hierbei wird also nicht die durchschnittliche Performanz auf mehrerer Lerndatensätze
gebildet, sondern ein einziger Abstand, nämlich der größte betrachtet. Liegt dieser bei 0.06, so hat das Netz
mindestens eine Note noch nicht richtig gelernt.
Deutlicher wird die Funktionsweise des max. Neuron ABSE, wenn man eine klassifizierende Kodierung benutzt.
Hier wird bei einem max. Neuron ABSE von 1 sofort ersichtlich, dass das Netz nicht ausgelernt hat.
In solchen Fällen lohnt es sich, die erste (und evtl. auch die zweite) verborgene Schicht um Neuronen zu erweitern,
da das Stagnieren des Lernvorganges meist auf eine zu kleine Netzarchitektur zurückgeführt werden kann.
Wurden Lieder durch das KNN gelernt, so kann man dem KNN einige Anfangsnoten eines gelernten Liedes
(oder auch eines nicht gelernten Liedes) vorlegen, woraufhin das KNN die darauf folgenden Noten
selbst improvisieren soll.
Im Prinzip wird dem KNN der erste Kontext gegeben. Hat das KNN ein Lied gut gelernt
(kleiner Netzfehlerwert für die Lerndaten), so sollte das KNN die nächste Note korrekt prognostizieren.
Danach wird die erste Note des Kontextes entfernt und diejenige Note, die das Netz ausgegeben hat,
hinten dran gehangen. Für diesen Schritt muss die Netzausgabe aus der Ausgabekodierung wieder in die
Standardkodierung umgewandelt werden. Von hier aus wird die Note wieder in die Eingabekodierung umgewandelt.
Da das KNN für verschiedene Eingaben unscharfe Ausgaben erzeugen kann, bei denen z.B. für die Tonhöhe
statt 0.2 oder 0.3 eine 0.213 ausgegeben wird, kann ein Netzausgabe-Interpret die Ausgabe des Netzes noch einmal
interpretieren. Der Netzausgabe Interpret ist abhängig von der benutzten Ausgabekodierung, da das
KNN eine Ausgabe in dieser Kodierung liefert. Für die Ausgabekodierungen Noten-Klassifikator und
Voll-Klassifikator sind jeweils zwei Interpreten möglich:
Der Max. Klassifikator entscheidet sich bei einer fuzzy Ausgabe des KNN für die "1 aus n"
kodierten Eigenschaften für denjenigen Wert, der am nächsten bei 1 liegt.
Alle anderen Werte werden als 0 gewertet.
So wird die Netzausgabe 0.8 0.2 0.1 0.2 0.3 0.1 0.2 für eine Note
als 1.0 0.0 0.0 0.0 0.0 0.0 0.0 und somit als Note c interpretiert.
Der Random Klassifikator interpretiert jeden Wert der Ausgabe als die Wahrscheinlichkeit, dass
es sich um die richtige Note handelt.
So hat der höchste Wert proportional die höchste Wahrscheinlichkeit.
Konkreter sieht die Ermittlung der richtigen Note für die Ausgabe
0.1 0.03 0.001 0.3 0.86 0.2 0.01 wie folgt aus:
1. Summe aller Ausgabeneuronen für die Note bilden.
Im Beispiel wäre das Outsum := 0.1 + 0.03 + 0.001 + 0.3 + 0.86 + 0.2 + 0.01 = 1.501 .
2. Anteil jeder Ausgabe an der Summe ermitteln.
Im Beispiel: Anteil_Output[i] = Output[i] / Outsum
Die Summe aller Anteile ergibt 1. Die Anteilswerte sind somit ein relativer Anteil (0-1).
3. Jedes der 7 Neuronen erhält einen Bereich zwischen 0 und 1 entsprechend dem Anteil:
Neuron | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Wert | 0.1 | 0.03 | 0.001 | 0.3 | 0.86 | 0.2 | 0.01 |
Anteil an der Summe | 0.066 | 0.019 | 0.0006 | 0.1998 | 0.5729 | 0.1332 | 0.0066 |
Bereich | 0-0.066 | 0.066-0.085 | 0.085-0.0856 | 0.0856-0.2854 | 0.2854-0.8583 | 0.8583-0.9915 | 0.9915-1.0 |
Kodierte Note | C | D | E | F | G | A | H |
4. Eine Zufallszahl im Bereich 0-1 generieren.
Rnd := random(0 bis 1); (z.B. 0.4)
5. Ermitteln, im Bereich welcher Note sich die Zufallszahl befindet.
Im Beispiel: Neuron 5 und damit die Note G.
Eine solche Interpretation über eine Zufallszahl und einer proportionalen Wahrscheinlichkeit führen die
Random Klassifikatoren durch. Daher stammt das Random in der Bezeichnung.
D. E. Rumelhart, G. Hinton, R. Williams
"Learning internal representations by error propagation" (1986)
Erste Beschreibung des Backpropagation Lernverfahrens für mehrschichtige Perceptronen.
Scott E. Fahlman
"An Empirical Study of Learning Speed in Back-Propagation Networks" (1988)
Erste Beschreibung des Quick Propagation Lernverfahrens.
T. Tollenaere
"Supersab: Fast adaptive backpropagation with good scaling properties" (1990)
Erste Beschreibung des SuperSAB Lernverfahrens.
L. F. A. Wessels and E. Barnard
"Avoiding False Local Minima by Proper Initialization of Connections" IEEE Trans. Neur. Netw. 3, 899 (1992)
Arbeit über die Initialisierung von Kantengewichten.
Martin Riedmiller
"Rprop - Description and Implementation Details" University Of Karlsruhe (1994)
Beschreibung und Implementierungsdetails des Resilient Propagation Lernverfahrens.
Martin Riedmiller
"Advanced Supervised Learning in Multi-layer Perceptrons - From Backpropagation to Adaptive Learning Algorithms" University Of Karlsruhe (1994)
Eine Übersich über die bekanntesten Lernverfahren mit besonderem Augenmerk auf adaptive Verfahren.
E. Gamma, R. Helm, R: Johnson & J. Vlissides
"Design Patterns: Elements of Reusable Object-Oriented Software." Addison Wesley (1995)
Grundwerk der Muster- und Objekt-Orientierten Softwareentwurfs.
Prof. Dr. H. Westenberger
Skript "Neuronale Netze 99V011"
Begleitskript zu den Vorlesungen von Prof. Dr. H. Westenberger.
QuickProp - Description and Implementation of the Algorithm
http://www.cs.ncl.ac.uk/modules/1998-99/csc325/projects/quickprop/implemen.htm (2004)
Eine detaillierte Beschreibung für die Implementierung des Quick Propagation Verfahrens.
jneurojam3_06_04_2005_bin.zip - Aktuelle JNeuroJam Version
|