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