/**
  * Trains a network against a given dataset
  *
  * @param input
  * @param expected_output
  * @return the number of iterations spent training the network
  * @throws SizeDifferenceException
  * @throws WrongSizeException
  */
 public int train(DataList[] inputs, DataList[] outputs, double target_error_rate)
     throws SizeDifferenceException, WrongSizeException {
   if (inputs.length != outputs.length) {
     throw new SizeDifferenceException("Must have the same number of training inputs and outputs");
   }
   // train until average error rate is below target error rate
   int iterations = 0;
   double average_error_rate = 1.0;
   do {
     iterations++;
     double error_sum = 0.0;
     for (int i = 0; i < inputs.length; i++) {
       DataList output = this.use(inputs[i]);
       error_sum += DataList.getErrorRate(output, outputs[i]);
       // train
       this.last().backpropagate(outputs[i]);
     }
     // calculate error rate
     average_error_rate = error_sum / inputs.length;
   } while (average_error_rate > target_error_rate);
   // return
   return iterations;
 }
 /**
  * Test a single dataset for correctness
  *
  * @param input
  * @param expected_output
  * @return a proportion, correct results to total results
  * @throws SizeDifferenceException
  * @throws WrongSizeException
  */
 public double test(DataList input, DataList expected_output)
     throws SizeDifferenceException, WrongSizeException {
   DataList out = this.use(input);
   return DataList.getErrorRate(out, expected_output);
 }