Implementação de XOR nos 3 principais frameworks JAVA
Autor: Unknown | Publicado: 2010-11-06T14:56:00-02:00

Existem 3 principais frameworks em Java para o desenvolvimento de redes neurais, são eles:

Neuroph
Encog
Joone
Vamos implementar uma rede de camadas múltiplas (MLP) para a solução do problema (clássico em RNA) de reconhecimento&nbsp;da operação lógica XOR, podemos comparar os três frameworks e tirar algumas conclusões.&nbsp;Uma operação XOR representa um OU exclusivo, ou seja, só é verdadeiro quando as entradas são diferentes entre si (ou uma entrada ou outra é verdadeira, nunca ambas):



Abaixo mostro as implementações de cada framework comentadas&nbsp;

Implementação usando Encog


O Encog possui uma grande variedade de técnicas de treinamento da rede, aqui será usado o a técnica LMA mas você poderia usar outras técnicas clássicas como Backpropagation ou Resilient Propagation (RPROP):




Implementação usando Neuroph 

Aqui será utilizada a ténica Backpropagation, não é uma técnica tão avançada quanto a Levenberg-Marquardt que pode ser usada no Encog.

/**CRIAÇÃO DA REDE*/

//A rede será um Perceptron de Múltiplas Camadas, com 2 neurônios de entrada, 1
//na saída e uma camada intermediária com 3 neurônios e a função de ativação
//é o tangente hiperbólico
MultiLayerPerceptron network =
 new MultiLayerPerceptron(TransferFunctionType.TANH, 2, 3, 1);

/**TESTES*/

//Cria-se a estrutura para treinamento supervisionado
TrainingSet trainingSet = new TrainingSet(2, 1);
trainingSet.addElement(new SupervisedTrainingElement
  (new double[]{0, 0}, new double[]{0}));
trainingSet.addElement(new SupervisedTrainingElement
  (new double[]{0, 1}, new double[]{1}));
trainingSet.addElement(new SupervisedTrainingElement
  (new double[]{1, 0}, new double[]{1}));
trainingSet.addElement(new SupervisedTrainingElement
  (new double[]{1, 1}, new double[]{0}));

//A técnica de treinamento é uma variação Neuroph para o Backpropagation
DynamicBackPropagation train = new DynamicBackPropagation();
train.setNeuralNetwork(network);
network.setLearningRule(train);

//Realiza os testes propriamente ditos
int epoch = 1;
do
{
  train.doOneLearningIteration(trainingSet);
  System.out.println("Epoch " + epoch + ", error=" + train.getTotalNetworkError());
  epoch++;

  } while(train.getTotalNetworkError()&gt;0.01);
  Once we are done, we display the trained network’s results.
  System.out.println("Neural Network Results:");
  for(TrainingElement element : trainingSet.trainingElements()) {
    network.setInput(element.getInput());
    network.calculate();
    Vector output = network.getOutput();
    SupervisedTrainingElement ste = (SupervisedTrainingElement)element;

  System.out.println(element.getInput().get(0) + ","
     + element.getInput().get(0)
     + ", actual=" + output.get(0) + ",ideal=" + ste.getDesiredOutput().get(0));

Implementação usando Joone&nbsp;

Joone é o framework mais antigo dentre os anteriores, o projeto começou em 2001 enquanto os outros dois começaram em 2008. A técnica de treinamento utilizada será o Backpropagation.

public static double XOR_INPUT[][] = { { 0.0, 0.0 }, { 1.0, 0.0 },
{ 0.0, 1.0 }, { 1.0, 1.0 } };
public static double XOR_IDEAL[][] = { { 0.0 }, { 1.0 }, { 1.0 }, { 0.0 } };

/**CRIAÇÃO*/

//É preciso criar cada camada individualmente, a camada de entrada será linear
LinearLayer input = new LinearLayer();
SigmoidLayer hidden = new SigmoidLayer();
SigmoidLayer output = new SigmoidLayer();

//Nomes para as camadas
input.setLayerName("input");
hidden.setLayerName("hidden");
output.setLayerName("output");

//Quantidade de neurônios para cada camada
input.setRows(2);
hidden.setRows(3);
output.setRows(1);

//É preciso criar sinapses para ligar as camadas e depois nomeá-las
FullSynapse synapse_IH = new FullSynapse(); 
FullSynapse synapse_HO = new FullSynapse();
synapse_IH.setName("IH");
synapse_HO.setName("HO");

//Adiciona as sinapses nas camadas
input.addOutputSynapse(synapse_IH);
hidden.addInputSynapse(synapse_IH);
hidden.addOutputSynapse(synapse_HO);
output.addInputSynapse(synapse_HO);

/**TESTES*/

//É preciso criar um Memory Sinapse para alimentar os arrays do XOR
MemoryInputSynapse  inputStream = new MemoryInputSynapse();

//Especifica-se o array a ser usado em cada camada
inputStream.setInputArray(XOR_INPUT);
inputStream.setAdvancedColumnSelector("1,2");

//Adiciona o objeto à sinapse
input.addInputSynapse(inputStream);

//Cria uma sinapse de treinamento para a rede
TeachingSynapse trainer = new TeachingSynapse();
MemoryInputSynapse samples = new MemoryInputSynapse();

//Especifica a saída ideal
samples.setInputArray(XOR_IDEAL);
samples.setAdvancedColumnSelector("1");
trainer.setDesired(samples);

//Conecta a sinapse de treinamento
output.addOutputSynapse(trainer);

//Cria uma rede neural para toda a estrutura
this.nnet = new NeuralNet();

//Adiciona as camadas à rede
nnet.addLayer(input, NeuralNet.INPUT_LAYER);
nnet.addLayer(hidden, NeuralNet.HIDDEN_LAYER);
nnet.addLayer(output, NeuralNet.OUTPUT_LAYER);

//Cria um monitor para fazer o treinamento
this.monitor = nnet.getMonitor();
monitor.setTrainingPatterns(4); // Quantidade de linhas existentes na entrada
monitor.setTotCicles(1000); // Ciclos de treinamento
monitor.setLearningRate(0.7);
monitor.setMomentum(0.3);
monitor.setLearning(true); // Configura a rede para treinamento
monitor.setSingleThreadMode(true);  //Modo Single Thread
monitor.addNeuralNetListener(this);
}

Resultados

Em geral, Encog gasta em torno de 60 iterações, Neuroph algumas centenas e o Joone facilmente chega a 5000 iterações sem apresentar resultados. Ao fazer o teste com cada um deles, nota-se que o Joone não é mais uma boa escolha em comparação com os outros dois frameworks, acontece que ele possui muitos bugs e não possui mais suporte, estas foram as principais razões que fizeram Jeff Heaton a iniciar seu próprio projeto de framework em Java: o Encog. O Encog é o framework mais completo, possui técnicas mais avançadas de treinamento em relação ao Neuroph&nbsp; e é mais bem documentado.


Fontes e Links diversos:

Texto e código adaptados de Comparing Neural Networks in Neuroph, Encog and JOONE
Técnica de LevenbergMarquardt: Método de Levenberg-Marquardt
Introdução ao Encog: An Introduction to Encog Neural Networks for Java