2015-11-12 5 views
0

J'essaie d'implémenter l'algorithme perceptron avec deux nœuds de sortie, mais je suis confronté à trois problèmes. Le premier est, je ne suis pas sûr comment évaluer ce que j'ai fait, comment créer des cas de test?Corriger la structure des poids pour 2 perceptron de sortie avec des données d'entrée binaires

La deuxième et la question plus pressante est, dois-je créer un tableau de poids pour chaque motif d'entrée, qui est- si mes données d'entrée ressemble à ceci:

0 0 0 0 0 0 0 
0 0 0 0 1 0 0 
0 0 0 1 0 0 0 
0 0 0 1 1 0 0 
0 0 1 0 0 0 0 
0 0 1 0 1 0 0 
0 0 1 1 0 0 0 
0 0 1 1 1 1 0 
0 1 0 0 0 0 0 
0 1 0 0 1 0 1 
0 1 0 1 0 0 0 
0 1 0 1 1 1 1 
0 1 1 0 0 0 0 
0 1 1 0 1 1 1 
0 1 1 1 0 1 0 
0 1 1 1 1 1 1 
1 0 0 0 0 0 0 
1 0 0 0 1 0 0 
1 0 0 1 0 0 0 
1 0 0 1 1 1 0 
1 0 1 0 0 0 0 
1 0 1 0 1 1 0 
1 0 1 1 0 1 0 
1 0 1 1 1 1 0 
1 1 0 0 0 0 0 
1 1 0 0 1 1 1 
1 1 0 1 0 1 0 
1 1 0 1 1 1 1 
1 1 1 0 0 1 0 
1 1 1 0 1 1 1 
1 1 1 1 0 1 0 
1 1 1 1 1 1 1 

devrais-je créer, par exemple, un ensemble de poids qui porte sur le motif:

1 1 1 1 1 

et une série de poids qui porte sur le motif:

1 1 1 1 0 

un autre pour:

1 1 1 0 1 

et ainsi de suite.

ou

REALISER une matrice de coefficients de pondération pour chaque neurone de sortie, dans l'exemple ci-dessus, il y a deux. C'est ce que ma mise en œuvre actuelle a, mais j'ai un soupçon que ce que j'ai décrit est plus précis - mais je ne peux pas vraiment justifier pourquoi c'est le cas - peut-être que quelqu'un pourrait m'expliquer cela.

Le troisième problème, probablement lié aux deux premiers, est que l'algorithme converge beaucoup trop rapidement.

Voici le résultat de deux exécutions:

sortie 1

Iteration 1 : RMSE = 0.30618621784789724 
Iteration 2 : RMSE = 0.0 

sortie 2

Iteration 1 : RMSE = 0.1767766952966369 
Iteration 2 : RMSE = 0.0 

La mise en œuvre complète ressemble à ceci:

import java.io.BufferedReader; 
import java.io.FileReader; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 
import java.util.Random; 
import java.util.concurrent.TimeUnit; 

public class Main 
{ 
    static int MAX_ITER = 100; 
    static double LEARNING_RATE = 0.1; 
    static int theta = 0; 

    public static void main(String args[]) throws IOException, InterruptedException 
    { 

     ArrayList<Group> input_group_one = new ArrayList<>(); 

     ArrayList<Group> input_group_two = new ArrayList<>(); 


     /************** 
     * READ INPUT * 
     **************/ 
     BufferedReader reader = new BufferedReader(new FileReader("../PA-A-train.dat")); 

     //do I even need this? 
     int number_of_inputs = 0; 

     String line;//new variable 
     while ((line = reader.readLine()) != null) //read the line and compare 
     { 
      /********************************************************************* 
      * GET THE LINE, SPLIT ON THE TAB FOR LABEL VS. INPUT IDENTIFICATION * 
      *********************************************************************/ 
      String[] label_detector = line.split("\t"); //split 

      /***************************** 
      * GET THE INDIVIDUAL INPUTS * 
      *****************************/ 
      String inputs = label_detector[label_detector.length - 2]; 
      String[] splited_inputs = inputs.split("\\s+"); 
      List<String> input_list = Arrays.asList(splited_inputs); 

      splited_inputs = Arrays.stream(splited_inputs) //Remove null values 
        .filter(s -> (s != null && s.length() > 0)) 
        .toArray(String[]::new); 

      //for this training datum, how many features does it have 
      number_of_inputs = splited_inputs.length; //5  

      /************************************ 
      * GET THE LABEL (2nd LAYER OUTPUT) * 
      ************************************/ 
      String trueLabel = label_detector[label_detector.length - 1]; 
      //System.out.println("this is the corresponding label: " + trueLabel); 
      String[] splited_labels = trueLabel.split("\\s+"); 

      int number_of_output_neurons = splited_labels.length;   




      input_group_one.add(new Group(splited_inputs, splited_labels[0])); 

      input_group_two.add(new Group(splited_inputs, splited_labels[0])); 


     } 
     reader.close(); 

//  for (Group p : input_group_one) 
//   System.out.println("check it out: " + p.toString()); 
//  ArrayList<String> weights_one = new ArrayList<>(); 



     //PLUS ONE FOR BIAS 
     double[] weights_one = new double[ number_of_inputs + 1 ]; 
     double[] weights_two = new double[ number_of_inputs + 1 ]; 

     double localError, globalError; 
     int i, p, iteration, output; 

     //MAKE SURE YOU HAVE ONE FOR BIAS 
     for (int j = 0; j < weights_one.length ; j++) 
     { 
      weights_one[j] = randDub(-0.5, 0.5); 
     } 
     for (int j = 0; j < weights_two.length ; j++) 
     { 
      weights_two[j] = randDub(-0.5, 0.5); 
     } 


//  for (int j = 0; j < weights_one.length ; j++) 
//  { 
//   System.out.println("weights_one[" + j + "]: " + weights_one[j]); 
//   
//   System.out.println("weights_two[" + j + "]: " + weights_two[j]); 
//  } 



     iteration = 0; 
     do 
     { 
      iteration++; 
      globalError = 0; 

      //loop through all instances (complete one epoch) 
      for (p = 0; p < input_group_one.size(); p++) // !!!!! is input_group_one.size() right? 
      { 
       // calculate predicted class 
       output = calculateOutput(theta, weights_one, input_group_one); 

       // difference between predicted and actual class values 
       // DO THIS INTEGER THING UP FRONT! 
       localError = Integer.parseInt(input_group_one.get(iteration).value[0]) - output; 

       //update weights and bias 
       for (int weight_index = 0; weight_index < input_group_one.get(iteration).value.length ; weight_index++) 
       { 
        weights_one[weight_index] += LEARNING_RATE * localError * Integer.parseInt(input_group_one.get(iteration).value[weight_index]); 
       } 
       //BIAS, (-1 because it starts from zero) 
       weights_one[weights_one.length - 1] += LEARNING_RATE * localError; 


       //summation of squared error (error value for all instances) 
       globalError += (localError*localError); 
      } 

      /* Root Mean Squared Error */ 
      System.out.println("Iteration "+iteration+" : RMSE = "+Math.sqrt(globalError/input_group_one.size())); 
     } 
     while (globalError != 0 && iteration<=MAX_ITER); 







    } 



    public static double randDub(double min, double max) throws InterruptedException 
    { 

     Random rand = new Random(System.currentTimeMillis()); 

     double randomValue = min + (max - min) * rand.nextDouble(); 

     //DELAY FOR SEED CHANGE 
     TimeUnit.SECONDS.sleep(1); 

     return randomValue; 
    } 



    static int calculateOutput(int theta, double weights[], ArrayList<Group> input_group) 
    { 
     double sum = 0; 

     for (Group pattern : input_group) 
     { 
      for (int i = 0; i < pattern.value.length; i++) 
      { 
       //ORIGINALLY STORED AS STRING MUST CHANGE TO INT 
       sum += Integer.parseInt(pattern.value[i]) * weights[i]; 
      } 
      //BIAS 
      sum += weights[ pattern.value.length ]; 
     } 
     return (sum >= theta) ? 1 : 0; 

    } 




} 

C'est un clas s J'ai fait pour stocker les données d'entrée.

import java.util.ArrayList; 
import java.util.Arrays; 

class Group { 

    public String key; 
    public String[] value; 

    public String getKey() { 
     return key; 
    } 

    public String[] getValue() { 
     return value; 
    } 

    Group(String[] splited_inputs, String k) 
    { 
     this.key = k; 
     this.value = splited_inputs; 
    } 

    @Override 
    public String toString() 
    { 
     return this.key + " " + Arrays.toString(this.value); 
    } 
// public String toString() 
// { 
//  String result = this.key + "::"; 
// 
//  for (int i = 0; i < this.value.length; i++) 
//  { 
//   result += " " + this.value[i]; 
//  } 
// 
//  return result; 
// } 

} 

Répondre

1

Il y a seulement une ensemble de coefficients de pondération pour chaque neurone de sortie. Sinon, comment calculeriez-vous la classification finale en fonction du nouveau point? Quels poids utiliseriez-vous? Tout l'intérêt de l'apprentissage des modèles paramétriques est de contraindre la complexité du modèle (ici - nombre de paramètres, poids) et de l'alimenter avec de nombreux échantillons d'apprentissage afin (statistiquement) d'apprendre les meilleurs pour l'ensemble du groupe.

Le réseau peut converger rapidement (bien que cela ne signifie pas qu'il le devrait) car le problème est trivial. Vous pouvez réellement regarder les données et dire les poids exacts "à la main". Pour le premier neurone, il s'agit de [1 1 1 1 1] et de biais -2,5 (ou de tout autre entre -2 et -3) et pour le second de [0 1 0 0 1] et de biais -1,5 (ou de tout autre entre - 1 et -2).