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 grafische Benutzeroberfläche

    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.

    Netz

    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.
  • Lieder

    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.

    Jammen

    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.
  • Gewichtsstruktur

    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.
  • Training

    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.
  • Lernverfahren

    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.

  • Techniken in JNeuroJam

    Repräsentation von Musiknoten in JNeuroJam

    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.

    Standard Notenkodierung

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

    Simple Notenkodierung

    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.

    Noten-Klassifizierende Notenkodierung

    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.

    cdefgah
    Wert 1Wert 2Wert 3Wert 4Wert 5Wert 6Wert 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.)

    Voll-Klassifizierende Notenkodierung

    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 1Oktave 2Oktave 3
    Wert 1Wert 2Wert 3

    Die Tonlänge wird mit 4 Werten ebenfalls "1 von n" kodiert:

    Ganzer TaktHalber TaktViertel TaktAchtel Takt
    Wert 1Wert 2Wert 3Wert 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.

    Sequenzenlernen mit der Zeitfenstertechnik

    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.

    Das Training und die Fehlertypen

    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.

    Average Absolute Error (avg. ABSE)

    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.

    Average Sum of Squared Errors (avg. SSE)

    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
    

    Average Root Mean Square Error (avg. RMSE)

    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
    

    Maximum ABSE by a Single Output Neuron (max. Neuron ABSE)

    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.

    Das Jammen

    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:

    Max. Klassifikator

    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.

    Random Klassifikator

    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:
    Neuron1234567
    Wert0.10.030.0010.30.860.20.01
    Anteil an der Summe0.0660.0190.00060.19980.57290.13320.0066
    Bereich0-0.0660.066-0.0850.085-0.08560.0856-0.28540.2854-0.85830.8583-0.99150.9915-1.0
    Kodierte NoteCDEFGAH
  • 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.


    Referenzen

    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.


    Download

    jneurojam3_06_04_2005_bin.zip - Aktuelle JNeuroJam Version