/**
   * computes the cost function which is to be minimized.
   *
   * @param examples training data
   * @return cost
   */
  public double computeCost(ArrayList<Instance> examples) {
    int m = examples.size();

    double cost = 0.0;
    for (Instance example : examples) {
      double prediction = computeHypothesis(example.getAllInputs());
      int label = example.getLabel();
      cost += label * Math.log(prediction) + (1.0 - label) * Math.log(1.0 - prediction);
    }
    return -cost / m;
  }
  protected void _trainIteration(ArrayList<Instance> examples, double rate) {
    double biasGradient = 0.0;
    double[] gradients = new double[weights.length];

    for (Instance example : examples) {

      double error = example.getLabel() - computeHypothesis(example.getAllInputs());
      biasGradient += (error);
      for (int i = 0; i < gradients.length; i++) {
        gradients[i] += (error) * example.getInput(i);
      }
    }
    for (int i = 0; i < weights.length; i++) {
      gradients[i] = gradients[i] / examples.size();
    }

    biasWeight += rate * biasGradient / examples.size();
    for (int i = 0; i < weights.length; i++) {
      weights[i] += rate * gradients[i] / examples.size();
    }
  }