@Override
  public void learn(DataSet cdata, Model m) {
    this.m = m;
    if (m == null) {
      logger.error("learner doesn't have a model");
      return;
    }

    LogisticRegression lr = (LogisticRegression) m;

    LRParameter para = (LRParameter) (m.para);
    boolean changed = true;
    for (int idx_iter = 0; changed && idx_iter < MAX_ITER_NUM; idx_iter++) {
      changed = false;
      int F = lr.featureFactory.allFeatures.size();
      for (int idx_inst = 0; idx_inst < cdata.getInstances().size(); idx_inst++) {
        // positive = 1, negative = 0
        int pred = -1;
        if (((LogisticRegression) m).voted) {
          ((LogisticRegression) m).voted = false;
          pred =
              lr.labelFactory.index((lr.infer)
                  .findBestLabel(cdata.getInstances().get(idx_inst), lr).label);
          ((LogisticRegression) m).voted = true;
        } else {
          pred =
              lr.labelFactory.index((lr.infer)
                  .findBestLabel(cdata.getInstances().get(idx_inst), lr).label);
        }

        int truth = lr.labelFactory.index(cdata.getInstances().get(idx_inst).label);

        Instance x = cdata.getInstances().get(idx_inst);

        if (pred != truth) {
          changed = true;
          for (int idx_fea = 0; idx_fea < x.length(); idx_fea++) {
            para.lambda[pred * F + x.getIndex(idx_fea)] -= STEP * x.getValue(idx_fea);
            para.lambda[truth * F + x.getIndex(idx_fea)] += STEP * x.getValue(idx_fea);
          }
        }

      }
    }
  }