用二进制输入数据校正2输出感知器的权重结构

时间:2015-11-12 17:02:51

标签: java machine-learning neural-network perceptron

我试图用两个输出节点实现感知器算法,但我面临三个问题。

首先,我不确定如何评估我所做的事情,如何创建测试用例?

第二个也是更紧迫的问题是,我是否应该为每个输入模式创建一个权重数组,即如果我的输入数据如下所示:

 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
例如,我应该创建一组处理模式的权重:

 1 1 1 1 1

和一组处理模式的权重:

 1 1 1 1 0 

另一个:

 1 1 1 0 1  

等等。

我应该为每个输出神经元创建一个权重数组,在上面的例子中有两个。这就是我目前的实施情况,但我清楚地知道我所描述的内容更为准确 - 但我不能完全证明为什么会这样 - 也许有人可以解释这个我。

可能与前两个问题密切相关的第三个问题是算法收敛太快。

以下是两次执行的结果:

输出1

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

输出2

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

完整的实现如下:

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;

    }




}

这是我用来存储输入数据的类。

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

}

1 个答案:

答案 0 :(得分:1)

每个输出神经元只有一个权重集。否则,如果给出新点,你会如何计算最终分类?你会使用哪种重量?学习参数模型的重点是约束模型复杂度(这里 - 参数数量,权重)并用许多训练样本提供它,因此(统计学上)可以学习整个组的最佳训练样本。

网络可以快速收敛(尽管并不意味着它应该),因为问题是微不足道的。您实际上可以查看数据并告诉确切的权重&#34;手动&#34;。对于第一个神经元,这是[1 1 1 1 1]和偏差-2.5(或任何其他在-2和-3之间),对于第二个神经元,它是[0 1 0 0 1]并偏向-1.5(或任何之间 - 1和-2)。