Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

To the best of my knowledge I've implemented a functional version of the perceptron algorithm, but as my knowledge is not so developed as of yet I'm wondering if I've done it correctly or not.

What concerns me is the very fast time in which the program terminates, I don't think it's considering all of my input examples.

Output:

NEURON ONE

Iteration 1, : RMSE = 0.39528470752104744
Iteration 2, : RMSE = 0.0

Decision boundary equation:

-0.478344531071606 * 0 + 0.4090517326097084 * 0 + 0.2215615717134649 * 0 + 0.13198023164216754 * 1 + -0.09354255942630574 * 0 + -0.18312389949760313 = 0


NEURON TWO

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

Decision boundary equation:

-0.4255775561058488 * 0 + 0.48484110382285384 * 0 + -0.24068168724561945 * 0 + -0.3302630124157556 * 1 + 0.18224682668800093 * 0 + 0.0697326572403591 = 0

The input looks as follows. It seems to me that all of my inputs datums are not being considered. Is that so?

Input:

 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

Maybe someone with some experience in this could examine my code/ data structures and see if I've done this right.

Also- is there a way I can generate random inputs with a very definite label, viz correct class, and test out the accuracy, viz predicted label, on them? This two neuron output structure is a bit confusing to me.

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 ];

        //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]);
//      }

        System.out.println("NEURON ONE");
        System.out.println();
        Computation( input_group_one, weights_one );
        System.out.println();

        System.out.println("NEURON TWO");
        System.out.println();
        Computation( input_group_one, weights_two );

    }



    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;

    }


    public static void Computation( ArrayList<Group> input_group, double[] weights )
    {
        double localError, globalError;
        int i, p, iteration, output;
        iteration = 0;
        do 
        {
            iteration++;
            globalError = 0;

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

                // difference between predicted and actual class values
                localError = Integer.parseInt( input_group.get(iteration).value[0] ) - output;

                //update weights and bias
                for (int weight_index = 0; weight_index < input_group.get(iteration).value.length ; weight_index++) 
                {
                    weights[weight_index] +=  LEARNING_RATE * localError * Integer.parseInt( input_group.get(iteration).value[weight_index] );
                }
                //BIAS, (-1 because it starts from zero)
                weights[weights.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.size()));

        } 
        while (globalError != 0 && iteration<=MAX_ITER);

        System.out.println();
        System.out.println("Decision boundary equation:");
        System.out.println();

        //PRINT EQUATION
        for (int weight_index = 0; weight_index < input_group.get(iteration).value.length ; weight_index++) 
        {
            System.out.print(weights[weight_index] + " * " + Integer.parseInt( input_group.get(iteration).value[weight_index] ) + " + " );
        }
        //BIAS 
        System.out.print( weights[weights.length - 1] + " = 0" );
        System.out.println();
        System.out.println();


    }



}

Input container class:

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;
//  }

}
share|improve this question

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.