Download SNIPE 0.9
Folgende Dateien stehen zur Auswahl:
Bei manchen Browsern kann es passieren, dass Downloads nicht geladen werden. In diesem Fall auf den Link rechtsklicken und „speichern unter“ auswählen!
SNIPE ist eine ausführlich dokumentierte JAVA-Bibliothek, welche ein schnelles, feature-reiches und einfach benutzbares Framework für Neuronale Netze implementiert. Für nichtkommerzielle Einsatzgebiete ist es kostenlos verfügbar. Wer plant, es kommerziell einzusetzen, möge bitte mit mir in Kontakt treten.
SNIPE ist ursprünglich für den Einsatz in Hochleistungssimulationen konzipiert, in denen sehr viele, auch große Netze gleichzeitig trainiert und ausgeführt werden. Vor kurzem habe ich mich nun entschieden, SNIPE als professionelle Referenzimplementierung zu meinem Manuskript "Ein kleiner Überblick über Neuronale Netze" online zu stellen, die sehr viele der dort behandelten Aspekte abdeckt, aber angesichts des ursprünglichen Design-Ziels effizienter arbeitet als die meisten anderen Implementierungen.
Der Lesbarkeit zuliebe sind ein paar der oben beschriebenen Laufzeiten leicht zu hoch angesetzt – wer möchte, kann sich im JavaDoc von core.NeuralNetwork einen genaueren Überblick verschaffen.
SNIPE ist kein Klicki-Bunti-Werkzeug mit schöner graphischer Oberfläche, um sich Netzwerke zusammenzuklicken – davon gibt es ja auch schon genug. Es ist ein JAVA-Framework, das einen Entwickler oder Studenten Neuronale Netze auf einfache, aber professionelle Weise einsetzen lässt. Nicht mehr, und nicht weniger.
Wenn ihr mir Feedback zu SNIPE gebt, seid sicher, dass ich mich freue, und es auf die eine oder andere Weise in die jeweils nächste Edition mit einfließt. Also: Wenn ihr irgendwelche Beschwerden, Fehlerberichtigungen, Vorschläge oder einfach Lob
habt, her damit – entweder per Mail an mich, oder in den Diskussionsteil am Fuß dieser Seite.
Klicken Sie auf einen Nachrichtentitel , um mehr zu erfahren.
2011-10-16: Snipe-Version 0.9 erschienen
2010-11-14: Snipe-Version 0.82
2010-05-11: SNIPE-Version 0.81
2010-03-28: SNIPE - Scalable and Generalized Neural Information Processing Engine
SNIPE besteht aus vier Hauptpaketen, welche jeweils mehrere Klassen enthalten. Alle Paketnamen beginnen mit com.dkriesel.snipe., wobei alle qualifizierten Klassennamen den Paketnamen als Präfix innehaben. Pakete und Klassen, die hier vorgestellt werden, sind grob nach Wichtigkeit geordnet: Wir fangen mit den grundlegendsten Klassen und Paketen an und arbeiten uns weiter in die Tiefen vor.
Dieses Paket enthält die beiden Kernklassen von SNIPE: NeuralNetworkDescriptor (wird benutzt um grobe Netzeigenschaften vorzugeben) und NeuralNetwork (das eigentliche Neuronale Netz, in dem alle Feinheiten definiert werden können, und was mit Hilfe von NeuralNetworkDescriptor-Instanzen erzeugt wird). Die Dokumentation beider Klassen enthält viel grundlegende Information über den Umgang mit SNIPE.
Enthält Klassen, die Trainingsdaten für Neuronale Netze speichern, sowie verschiedene Methoden der Trainingsfehlermessung.
Dieses Paket enthält verschiedene Neuronenverhalten (das sind verallgemeinerte Aktivierungsfunktionen), sowie ein Interface, um eigene zu implementieren. Ich stelle hier nur die wichtigsten Klassen vor.
Enthält ein paar kleine Zusatzwerkzeuge für SNIPE.
Hier ist etwas reich kommentierter Beispielcode, viel Spaß damit! Wenn man ihn in Dateien steckt, deren Namen zum jeweiligen Code-Titel korrespondiert, sind die Beispiele zum JavaDoc konsistent!
Dieses Snippet bietet eine Einführung in die vier am häufigsten benutzten Klassen in SNIPE: NeuralNetworkDescriptor, NeuralNetwork, TrainingSampleLesson und ErrorMeasurement. Es zeigt, wie man NeuralNetwork-Instanzen mittels NeuralNetworkDescriptor-Instanzen erzeugt, wie man eine vorgefertigte TrainingSampleLesson erzeugt und verwendet, und wie man Backpropagation mit verschiedenen Lernraten benutzt. Weiterhin wird gezeigt, wie man Werte durch ein Neuronales Netz propagiert und Fehler misst.
com/dkriesel/snipe/examples/MultilayerPerceptron838ProblemBackprop.java
package com.dkriesel.snipe.examples; import java.text.DecimalFormat; import com.dkriesel.snipe.core.NeuralNetwork; import com.dkriesel.snipe.core.NeuralNetworkDescriptor; import com.dkriesel.snipe.neuronbehavior.TangensHyperbolicusAnguita; import com.dkriesel.snipe.training.ErrorMeasurement; import com.dkriesel.snipe.training.TrainingSampleLesson; /** * Very simple example program that trains an 8-3-8 multilayer perceptron * encoder problem with backpropagation of error. * * @author David Kriesel / dkriesel.com * */ public class MultilayerPerceptron838ProblemBackprop { /** * Executes the example. * * @param args * no args are parsed. */ public static void main(String[] args) { /* * Create and configure a descriptor for feed forward networks without * shortcut connections and with fastprop, an identity activity * functions in the input layer and tangens hyperbolicus functions in * hidden and output layers. To learn about fastprop, have a look into * the NeuralNetworkDescriptor documentation. */ NeuralNetworkDescriptor desc = new NeuralNetworkDescriptor(8, 3, 8); desc.setSettingsTopologyFeedForward(); /* * If you want, remove the comment slashes from the following two lines * to use a tuned tangens hyperbolicus approximation that is computed * faster and provides better learning sometimes. */ // desc.setNeuronBehaviorHiddenNeurons(new TangensHyperbolicusAnguita()); // desc.setNeuronBehaviorOutputNeurons(new TangensHyperbolicusAnguita()); /* * Create neural network using the descriptor (we could as well generate * thousands of similar networks at this point of time). The network * will be automatically added all allowed synapses according to the * default settings in the descriptor. */ NeuralNetwork net = new NeuralNetwork(desc); /* * Prepare Training Data: 8-Dimensional encoder problem with 1 as * positive and -1 as negative value */ TrainingSampleLesson lesson = TrainingSampleLesson .getEncoderSampleLesson(8, 1, -1); /* * Train that sucker with backprop in three phases with different * learning rates. In between, display progress, and measure overall * time. */ long startTime = System.currentTimeMillis(); System.out.println("Root Mean Square Error before training:\t" + ErrorMeasurement.getErrorRootMeanSquareSum(net, lesson)); net.trainBackpropagationOfError(lesson, 250000, 0.2); System.out.println("Root Mean Square Error after phase 1:\t" + ErrorMeasurement.getErrorRootMeanSquareSum(net, lesson)); net.trainBackpropagationOfError(lesson, 250000, 0.05); System.out.println("Root Mean Square Error after phase 2:\t" + ErrorMeasurement.getErrorRootMeanSquareSum(net, lesson)); net.trainBackpropagationOfError(lesson, 250000, 0.01); System.out.println("Root Mean Square Error after phase 3:\t" + ErrorMeasurement.getErrorRootMeanSquareSum(net, lesson)); long endTime = System.currentTimeMillis(); long time = endTime - startTime; /* * Print out what the network learned (in a formatted way) and the time * it took. */ DecimalFormat df = new DecimalFormat("#.#"); System.out.println("\nNetwork output:"); for (int i = 0; i < lesson.countSamples(); i++) { double[] output = net.propagate(lesson.getInputs()[i]); for (int j = 0; j < output.length; j++) { System.out.print(df.format(output[j]) + "\t"); } System.out.println(""); } System.out.println("\nTime taken: " + time + "ms"); } }
Dieses Beispiel editiert die interne Struktur einer großen Population Neuronaler Netze. Am Ende wird GraphViz DOT-Code für ein Netzwerk ausgegeben. Unter dem Code-Snippet sieht man die Ergebnisse von GraphViz-Ausgaben in Bildern, so dass man die Topologieveränderungen ab Schritt 2 mitverfolgen kann. In den Bildern sind normalerweise 2 BIAS-Neurone, weil pro Schicht eins angegeben wird, damit die Bilder besser layoutet werden können. Das zweite habe ich hier jeweils aus dem Bild herausgeschnitten.
com/dkriesel/snipe/examples/HandCraftNetwork.java
package com.dkriesel.snipe.examples; import com.dkriesel.snipe.core.NeuralNetwork; import com.dkriesel.snipe.core.NeuralNetworkDescriptor; import com.dkriesel.snipe.util.GraphVizEncoder; /** * Simple example program that shows how to hand-craft even large numbers of * networks. * * @author David Kriesel / dkriesel.com * */ public class HandCraftNetwork { /** * Executes the example. * * @param args * no args are parsed. */ public static void main(String[] args) { /* * Create a NeuralNetworkDescriptor outlining Networks with two input * neurons, one hidden neuron and two output neurons. Tell the networks * not to automatically initialize synapses that are allowed. Tell them * to choose synaptic weight values out of [-0.1;0.1] when initializing * synapse weights randomly. */ NeuralNetworkDescriptor desc = new NeuralNetworkDescriptor(2, 1, 2); desc.setInitializeAllowedSynapses(false); desc.setSynapseInitialRange(0.1); /* * Create ten thousand of those networks. */ NeuralNetwork[] net = desc.createNeuralNetworks(10000); /* * for-loop that customizes each of the networks */ for (int i = 0; i < net.length; i++) { /* * Step 0: We now have 10000 neural networks with 2 input neurons * (numbered 1,2), one hidden neuron (3) and two output neurons (4 * and 5). There are no synapses yet. The input layer is numbered 0, * the hidden layer 1 and the output layer is numbered 2. We will * see that the NeuralNetwork class maintains the ascending * numbering of neurons and layers. */ /* * Step 1: Now, in each network create three additional hidden * neurons. The hidden layer now contains neurons with indices 3, 4, * 5 and 6, while the indices of the output neurons have been * increased. */ net[i].createNeuronInLayer(1); net[i].createNeuronInLayer(1); int thirdOne = net[i].createNeuronInLayer(1); /* * Step 2: Create a synapse from the BIAS to the hidden neuron just * added. */ net[i].setSynapse(0, thirdOne, 2.0); /* * Step 3: Remove the hidden neuron that was added last. This * decreases all following neuron indices and removes the incident * synapse we added as well. */ net[i].removeNeuron(thirdOne); /* * Step 4: Now, create a full connection set from hidden to output * layer. Connections will be initialized with weight values out of * [-0.1;0.1], as we defined in the descriptor. */ net[i].createSynapsesFromLayerToLayer(1, 2); /* * Step 5: Add three forward connections from input layer to hidden * layer. */ net[i].setSynapse(1, 3, 5.0); net[i].setSynapse(1, 4, 2.0); net[i].setSynapse(2, 5, 3.0); /* * Step 6: Add two forward shortcuts from input layer to output * layer. */ net[i].setSynapse(1, 6, 4.0); net[i].setSynapse(2, 7, 5.0); /* * Step 7: Add two self-connections in hidden layer. */ net[i].setSynapse(3, 3, 6.0); net[i].setSynapse(5, 5, 7.0); /* * Step 8: Add two lateral connections between the two output * neurons. Now, we're done. */ net[i].setSynapse(6, 7, 8.0); net[i].setSynapse(7, 6, 9.0); } /* * Print out GraphViz Code of one network. Weight labels of weak * synapses (namely, the ones that were initialized with weight * absolutes smaller or equal to 0.1) are suppressed. Those synapses are * printed lighter as well. */ GraphVizEncoder graph = new GraphVizEncoder(); String code = graph.getGraphVizCode(net[0], "NeuralNetwork"); System.out.println(code); } }
Diese Software wird „wie besehen“ und ohne Gewähr, weder ausdrücklich noch implizit, einschließlich aber nicht beschränkt auf die gesetzliche Gewährleistung der Gebrauchstauglichkeit und Eignung für einen bestimmen Zweck bereitgestellt. In keinem Fall, auch wenn sie von der Möglichkeit solcher Schäden unterrichtet wurden, haften der Urheberrechtsinhaber oder andere Personen, die das Programm wie oben erlaubt verändern bzw. Weitergeben für unmittelbare, indirekte, zugehörige, besondere, exemplarische Schäden oder Folgeschäden (einschließlich aber nicht beschränkt auf solche, die im Zusammenhang mit der Beschaffung von Ersatzwaren oder -dienstleistungen, einem Nutzungsausfall, Datenverlust, entgangenem Gewinn oder einer Arbeitsunterbrechung auftreten), die im Rahmen der Verwendung dieser Software entstehen. Dies gilt ungeachtet der Ursache und der Grundlage des Haftungsanspruchs, d. H. Aufgrund eines Vertrages, einer verschuldensunabhängigen Haftung oder eines zivilrechtlichen Delikts (z. B. Fahrlässigkeit).
SNIPE und seine Dokumentation sind unter der Creative Commons Attribution-No Derivative Works 3.0 Unported License lizensiert, bis auf einige wenige Kleinteile, die anderen Lizenzen bzw. Copyright unterstehen (das ist dann im JavaDoc auch so vermerkt). Natürlich berührt die Lizenz nicht den Source Code von SNIPE, der (zunächst) nicht veröffentlicht wird.
~~DISCUSSION~~