Neuronales Netzwerk

minzee

Bekanntes Mitglied
Hi :)

Ich hatte heute mit jemanden zusammengesessen, um unser erstes neuronales Netzwerk zu programmieren. Das scheint doch ziemlich komplex zu sein. In einer allerersten ungetesteten Version sind wir zu dem folgenden Ergebnis gekommen:

Java:
class Neuron
{
   private double o;
   private Neuron[] neurons;
   private double[] weights;
   private Func propagationFunc;
   private Func activationFunc;
   private Func outputFunc;

   /**
    * Input-Neuron
    */
   public Neuron(Func propagationFunc, Func activationFunc, Func outputFunc)
   {
      this.propagationFunc = propagationFunc;
      this.activationFunc = activationFunc;
      this.outputFunc = outputFunc;
   }
   /**
    * Output-Neuron
    * @param Neuron[] neurons Eingehende Neuronen
    * @param double[] weights Gewichte der eigehenden Verbindungen
    */
   public Neuron(Neuron[] neurons, double[] weights, Func propagationFunc, Func activationFunc, Func outputFunc)
   {
      this.neurons = neurons;
      this.weights = weights;
      this.propagationFunc = propagationFunc;
      this.activationFunc = activationFunc;
      this.outputFunc = outputFunc;
   }
   /**
    * Wert für ein Input-Neuron.
    * @param double value
    */
   public void in(double value)
   {
      this.o = value;
   }
   /**
    * Ausgabe des Neurons.
    * @return double
    */
   public double out()
   {
      if(neurons != null)
      {
         // Propagierungsfunktion => net
         double net = 0.0;
         for(int i = 0; i < neurons.length; ++i)
         {
            net += weights[i] * neurons[i].out();
         }
         if(propagationFunc != null)
         {
            net = propagationFunc.calc(net);
         }
         
         // Aktivierungsfunktion => a
         double a = (activationFunc != null)
            ?  activationFunc.calc(net)
            :  net;
         
         // Outputfunktion => o
         double o = (outputFunc != null)
            ?  outputFunc.calc(a)
            :  a;
      }
      return o;
   }
}
class Main
{
   public static void main(String[] args)
   {
      double[] values = {1.0, 0.0, 1.0};
      double[] weights = {0.6, 0.6, 0.6};
      
      double threshold = 0.5;
      double value = 1.0;
      Func f = new ThresholdValueFunc(threshold, value); // 1
      
      // Schicht 0:
      Neuron n0 = new Neuron(f, null, null);
      Neuron n1 = new Neuron(f, null, null);
      
      // Schicht 1:
      Neuron[] level0 = {n0, n1};
      Neuron n2 = new Neuron(level0, new double[]{0.02, 0.12}, f, null, null);
      Neuron n3 = new Neuron(level0, new double[]{0.03, 0.13}, f, null, null);
      
      // Schicht 2:
      Neuron n4 = new Neuron(new Neuron[]{n0, n1, n2, n3}, new double[]{0.04, 0.14, 0.24, 0.34}, f, null, null);
      
      n0.in(1.0);
      n1.in(1.0);
      System.out.println(n4.out());
   }
}
ThresholdValueFunc und andere mögliche Func-Klassen gibts hier:
Java:
interface Func
{
   public double calc(double value);
}
class ThresholdValueFunc implements Func
{
   private double threshold;
   private double thresholdValue;
   
   /**
    * @param double value Der Wert, der ausgegeben wird, wenn calc einen Wert > threshold berechnet.
    */
   public ThresholdValueFunc(double threshold, double thresholdValue)
   {
      this.threshold = threshold;
      this.thresholdValue = thresholdValue;
   }
   /**
    * Gleiche Anzahl Elemente!
    * @return double
    */
   public double calc(double value)
   {
      if(value > threshold)
      {
         return thresholdValue;
      }
      return 0.0;
   }
}
class ThresholdValuesFunc implements Func
{
   private double threshold;
   private double upperThresholdValue;
   private double lowerThresholdValue;
   
   /**
    * @param double value Der Wert, der ausgegeben wird, wenn calc einen Wert > threshold berechnet.
    */
   public ThresholdValuesFunc(double threshold, double upperThresholdValue, double lowerThresholdValue)
   {
      this.threshold = threshold;
      this.upperThresholdValue = upperThresholdValue;
      this.lowerThresholdValue = lowerThresholdValue;
   }
   /**
    * Gleiche Anzahl Elemente!
    * @return double
    */
   public double calc(double value)
   {
      if(value > threshold)
      {
         return upperThresholdValue;
      }
      return lowerThresholdValue;
   }
}
class SignumFunc implements Func
{
   private double threshold;
   
   public SignumFunc(double threshold)
   {
      this.threshold = threshold;
   }
   /**
    * @return double
    */
   public double calc(double value)
   {
      if(value > threshold)
      {
         return 1.0;
      }
      return -1.0;
   }
}
class LinearFunc implements Func
{
   private double upperThreshold;
   private double lowerThreshold;
   private double upperThresholdValue;
   private double lowerThresholdValue;
   
   /**
    * Garantiert, dass es keine Sprünge in der Kurve gibt.
    */
   public LinearFunc(double upperThreshold, double lowerThreshold)
   {
      this.upperThresholdValue = this.upperThreshold = upperThreshold;
      this.lowerThresholdValue = this.lowerThreshold = lowerThreshold;
   }
   /**
    * Sprünge in der Kurve möglich.
    */
   public LinearFunc(double upperThreshold, double lowerThreshold, double upperThresholdValue, double lowerThresholdValue)
   {
      this.upperThreshold = upperThreshold;
      this.lowerThreshold = lowerThreshold;
      this.upperThresholdValue = upperThresholdValue;
      this.lowerThresholdValue = lowerThresholdValue;
   }
   /**
    * @return double
    */
   public double calc(double value)
   {
      if(value >= upperThreshold)
      {
         return upperThresholdValue;
      }
      if(value <= lowerThreshold)
      {
         return lowerThresholdValue;
      }
      return value;
   }
}
class SigmoidFunc implements Func
{
   private double delta;
   
   public SigmoidFunc(double delta)
   {
      this.delta = delta;
   }
   /**
    * @return double
    */
   public double calc(double value)
   {
      return 1.0 / (1.0 + Math.exp(-value) / delta); // e^(-sum)
   }
}
class TanHFunc implements Func
{
   /**
    * @return double
    */
   public double calc(double value)
   {
      return Math.tanh(value);
   }
}
Wir haben zuvor noch nie ein objektorientiert programmiertes neuronales Netzwerk gesehen. Darum würde mich interssieren, ob wir auf dem richtigen Weg sind. Ist die Programmierung soweit in Ordnung?
 

minzee

Bekanntes Mitglied
Sehr ruhig in diesem Thema. Hattet ihr noch nie mit neuronalen Netzen zu tun? Oder habe ich das nur irgendwie schlecht hier reingepostet?

Hier auch unser Versuch, einem Neuron das Lernen beizubringen:
Java:
class Neuron
{
   private double o;
   private Neuron[] neurons;
   private double[] weights;
   private Func propagationFunc;
   private Func activationFunc;
   private Func outputFunc;

   /**
    * Input-Neuron
    */
   public Neuron(Func propagationFunc, Func activationFunc, Func outputFunc)
   {
      this.propagationFunc = propagationFunc;
      this.activationFunc = activationFunc;
      this.outputFunc = outputFunc;
   }
   /**
    * Output-Neuron
    * @param Neuron[] neurons Eingehende Neuronen
    * @param double[] weights Gewichte der eigehenden Verbindungen
    */
   public Neuron(Neuron[] neurons, double[] weights, Func propagationFunc, Func activationFunc, Func outputFunc)
   {
      this.neurons = neurons;
      this.weights = weights;
      this.propagationFunc = propagationFunc;
      this.activationFunc = activationFunc;
      this.outputFunc = outputFunc;
   }
   /**
    * Wert für ein Input-Neuron.
    * @param double value
    */
   public void in(double value)
   {
      this.o = value;
   }
   /**
    * Ausgabe des Neurons.
    * @return double
    */
   public double out()
   {
      if(neurons != null)
      {
         // Propagierungsfunktion => net
         double net = 0.0;
         for(int i = 0; i < neurons.length; ++i)
         {
            net += weights[i] * neurons[i].out();
         }
         if(propagationFunc != null)
         {
            net = propagationFunc.calc(net);
         }
         
         // Aktivierungsfunktion => a
         double a = (activationFunc != null)
            ?  activationFunc.calc(net)
            :  net;
         
         // Outputfunktion => o
         double o = (outputFunc != null)
            ?  outputFunc.calc(a)
            :  a;
      }
      return o;
   }
   /**
    * Versucht die Gewichte so einzustellen, dass die Ausgabe bei allen möglichen Eingängen immer den Mustern entspricht.
    * Anzahl Elemente von patterns muss mit patternOs übereinstimmen.
    * @param int nMax maximale Anzahl an Lern-Durchläufen
    * @param double eta Lernrate
    * @param double[][] patterns Muster-Eingänge
    * @param double[] patternOs erwartete Muster-Ausgänge
    */
   public void learn(int nMax, double eta, double[][] patterns, double[] patternOs)
   {      
      int l = patterns[0].length;
      Random r = new Random();
      for(int i = 0; i < nMax; ++i)
      {
         // Wie im Buch wird hier per Zufall ein Muster ausgesucht:
         int k = r.nextInt(patternOs.length); // [0, length)
         double target = patternOs[k]; // Sollwert
         
         // Propagierungsfunktion => net
         double net = 0.0;
         for(int j = 0; j < l; ++j)
         {
            net += weights[j] * patterns[k][j];
         }
         if(propagationFunc != null)
         {
            net = propagationFunc.calc(net);
         }
         
         // Aktivierungsfunktion => a
         double a = (activationFunc != null)
            ?  activationFunc.calc(net)
            :  net;
         
         // Outputfunktion => o
         double o = (outputFunc != null)
            ?  outputFunc.calc(a)
            :  a;
            
         // Sollwert mit Istwert vergleichen:
         if(target != o)
         {
            // Abweichung:
            double delta = target - o;
            
            // Gewichte aller aktiven Eingänge anpassen:
            for(int j = 0; j < l; ++j)
            {
               if(patterns[k][j] > 0.0) // wenn ein aktiver Eingang
               {
                  weights[j] += weights[j] * eta * delta; // Gewicht zu einem bestimmten Eingang anpassen
               }
            }
         }

         // zum Testen:
         System.out.print("i = " + i + ", k = " + k + ": ");
         for(int x = 0; x < weights.length; ++x)
         {
            System.out.print(weights[x] + " ");
         }
         System.out.println();
      }
   }
}
class Main
{
   public static void main(String[] args)
   {      
      double threshold = 0.5;
      double value = 1.0;
      Func f = new ThresholdValueFunc(threshold, value);
           
      // Schicht 0:
      Neuron n0 = new Neuron(f, null, null);
      Neuron n1 = new Neuron(f, null, null);
      Neuron n2 = new Neuron(f, null, null);
      
      // Schicht 1:
      Neuron n3 = new Neuron(new Neuron[]{n0, n1, n2}, new double[]{0.6, 0.6, 0.6}, f, null, null);
      
      int nMax = 20;
      double eta = 0.5;
      double[][] patterns =
      {
         // 0    1    2
         {0.0, 0.0, 0.0},
         {1.0, 0.0, 0.0},
         {0.0, 1.0, 0.0},
         {1.0, 1.0, 0.0},
         {0.0, 0.0, 1.0},
         {1.0, 0.0, 1.0},
         {0.0, 1.0, 1.0},
         {1.0, 1.0, 1.0}
      };
      double[] patternOs = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
      n3.learn(nMax, eta, patterns, patternOs);
   }
}
Würden uns über Rückmeldung freuen, ob das korrekt ist.
 
Zuletzt bearbeitet:

arilou

Bekanntes Mitglied
Vielleicht solltest du darüber nachdenken
  • dass das hier ein Anfänger-Forum ist; diesem Status entwächst du wohl so langsam (denke ich).
  • dass dies ein Java-Forum ist; fachliche Fragen zu Mathematik, Informatik, Fußball oder Steuerrecht solltest du vielleicht in einem entsprechenden Fachforum stellen. (Auch wenn sie manchmal ~ durch "Zufall" ~ hier ebenfalls beantwortet werden können.)
 

minzee

Bekanntes Mitglied
Ich kenn mich hier im Forum noch nicht aus. Aber mittlerweile habe ich die Vermutung, dass solche Themen in "Codeschnipsel u. Projekte" besser aufgehoben sind.

Ich glaube übrigens, dass die Neuron-Klasse nicht stimmt. Ich vermute, hier muss viel stärker zwischen Input- und Output-Neuronen unterschieden werden. Total fehlt mir der Durchblick bei Neuronen in Zwischenschichten. Keine Ahnung, ob man sie zu Input-, Output- oder ganz anderen Neuronen zuordnen kann bzw. muss. Könnt ihr mir dabei weiterhelfen?
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Threads Neuronales Netz - Perzeptron Java Basics - Anfänger-Themen 8
K Neuronales Netz in Java ... die zweite Java Basics - Anfänger-Themen 3
K Neuronales Netz in Java und Probleme beim Konfigurieren Java Basics - Anfänger-Themen 2
J Datei aus Netzwerk auslesen Java Basics - Anfänger-Themen 9
T Access mit Java verbinden im netzwerk Java Basics - Anfänger-Themen 3
S Input/Output Vom Netzwerk kopieren Java Basics - Anfänger-Themen 6
B Unique ID für Device im internen Netzwerk Java Basics - Anfänger-Themen 19
fLooojava Daten im selben Netzwerk an IP Java Basics - Anfänger-Themen 1
M Semantisches Problem HashMap/Netzwerk Java Basics - Anfänger-Themen 4
H Entwicklung am selben Projekt im Netzwerk Java Basics - Anfänger-Themen 9
T Erkennen ob ein Pfad lokal oder im Netzwerk ist Java Basics - Anfänger-Themen 13
B Erste Schritte Dateien ueber Netzwerk kopieren Java Basics - Anfänger-Themen 2
P Probleme bei senden eines Strings übers Netzwerk Java Basics - Anfänger-Themen 4
P Strings via Netzwerk übermitteln Java Basics - Anfänger-Themen 8
K Router über Netzwerk Booten lassen Java Basics - Anfänger-Themen 8
G Netzwerk unterbrechen Java Basics - Anfänger-Themen 10
S Netzwerk nach ip adressen scannen Java Basics - Anfänger-Themen 7
M In Router einloggen und PCs im Netzwerk erkennen Java Basics - Anfänger-Themen 18
U Netzwerk Chatprogramm Quellcode funktioniert nicht Java Basics - Anfänger-Themen 6
Nic.o getProperties - übers Netzwerk Java Basics - Anfänger-Themen 2
0 Objekte übers Netzwerk schicken? Bibliothek? Java Basics - Anfänger-Themen 2
D Java Tutorial zur Netzwerk / Datenbankprogrammierung gesucht Java Basics - Anfänger-Themen 2
F Bild per Netzwerk übertragen Java Basics - Anfänger-Themen 3
I Schiffe versenken, Netzwerk, swing, Thread Java Basics - Anfänger-Themen 5
G Netzwerk: RMI Objekt-Referenzen Java Basics - Anfänger-Themen 2
A Netzwerk Programmieren Java Basics - Anfänger-Themen 2
H Netzwerk-Thread Java Basics - Anfänger-Themen 7
H ObjectOutputStream Netzwerk writeObject Java Basics - Anfänger-Themen 6
G Strings übers Netzwerk verschicken Java Basics - Anfänger-Themen 2
Z Netzwerk graphisch Darstellen Java Basics - Anfänger-Themen 5
L Dateien im Netzwerk bearbeiten (UNC-Pfade und gemappte Laufw Java Basics - Anfänger-Themen 5
J Audio capturen und über's Netzwerk streamen? Java Basics - Anfänger-Themen 2
C BufferedReader und BufferedWriter im Netzwerk Java Basics - Anfänger-Themen 6
M E-Mail im Netzwerk über Microsoft Exchange Server versenden? Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben