private NBWeights trainWeightsCL(int[][] data, int[] labels, int numFeatures, int numClasses) {

    LogConditionalEqConstraintFunction objective =
        new LogConditionalEqConstraintFunction(
            numFeatures, numClasses, data, labels, prior, sigma, 0.0);
    Minimizer<DiffFunction> min = new QNMinimizer();
    double[] argmin = min.minimize(objective, 1e-4, objective.initial());
    double[][][] wts = objective.to3D(argmin);
    double[] priors = objective.priors(argmin);
    return new NBWeights(priors, wts);
  }
  public Classifier<L, F> trainClassifier(
      GeneralDataset<L, F> dataset, float[] dataWeights, LogPrior prior) {
    Minimizer<DiffFunction> minimizer = getMinimizer();
    if (dataset instanceof RVFDataset) ((RVFDataset<L, F>) dataset).ensureRealValues();
    LogConditionalObjectiveFunction<L, F> objective =
        new LogConditionalObjectiveFunction<L, F>(dataset, dataWeights, logPrior);

    double[] initial = objective.initial();
    double[] weights = minimizer.minimize(objective, TOL, initial);

    LinearClassifier<L, F> classifier =
        new LinearClassifier<L, F>(
            objective.to2D(weights), dataset.featureIndex(), dataset.labelIndex());
    return classifier;
  }
  public double[][] trainWeights(
      GeneralDataset<L, F> dataset,
      double[] initial,
      boolean bypassTuneSigma,
      Minimizer<DiffFunction> minimizer) {
    if (minimizer == null) minimizer = minimizerCreator.create();
    if (dataset instanceof RVFDataset) ((RVFDataset<L, F>) dataset).ensureRealValues();
    double[] interimWeights = null;
    if (!bypassTuneSigma) {
      if (tuneSigmaHeldOut) {
        interimWeights =
            heldOutSetSigma(
                dataset); // the optimum interim weights from held-out training data have already
                          // been found.
      } else if (tuneSigmaCV) {
        crossValidateSetSigma(
            dataset, folds); // TODO: assign optimum interim weights as part of this process.
      }
    }
    LogConditionalObjectiveFunction<L, F> objective =
        new LogConditionalObjectiveFunction<L, F>(dataset, logPrior);
    if (initial == null && interimWeights != null && !retrainFromScratchAfterSigmaTuning) {
      // System.err.println("## taking advantage of interim weights as starting point.");
      initial = interimWeights;
    }
    if (initial == null) {
      initial = objective.initial();
    }

    double[] weights = minimizer.minimize(objective, TOL, initial);
    return objective.to2D(weights);
  }
  /**
   * Adapt classifier (adjust the mean of Gaussian prior) under construction -pichuan
   *
   * @param origWeights the original weights trained from the training data
   * @param adaptDataset the Dataset used to adapt the trained weights
   * @return adapted weights
   */
  public double[][] adaptWeights(double[][] origWeights, GeneralDataset<L, F> adaptDataset) {
    Minimizer<DiffFunction> minimizer = getMinimizer();
    System.err.println("adaptWeights in LinearClassifierFactory. increase weight dim only");
    double[][] newWeights =
        new double[adaptDataset.featureIndex.size()][adaptDataset.labelIndex.size()];

    System.arraycopy(origWeights, 0, newWeights, 0, origWeights.length);

    AdaptedGaussianPriorObjectiveFunction<L, F> objective =
        new AdaptedGaussianPriorObjectiveFunction<L, F>(adaptDataset, logPrior, newWeights);

    double[] initial = objective.initial();

    double[] weights = minimizer.minimize(objective, TOL, initial);
    return objective.to2D(weights);

    // Question: maybe the adaptWeights can be done just in LinearClassifier ?? (pichuan)
  }
 public double[][] trainWeightsSemiSup(
     GeneralDataset<L, F> data,
     GeneralDataset<L, F> biasedData,
     double[][] confusionMatrix,
     double[] initial) {
   Minimizer<DiffFunction> minimizer = minimizerCreator.create();
   LogConditionalObjectiveFunction<L, F> objective =
       new LogConditionalObjectiveFunction<L, F>(data, new LogPrior(LogPrior.LogPriorType.NULL));
   BiasedLogConditionalObjectiveFunction biasedObjective =
       new BiasedLogConditionalObjectiveFunction(
           biasedData, confusionMatrix, new LogPrior(LogPrior.LogPriorType.NULL));
   SemiSupervisedLogConditionalObjectiveFunction semiSupObjective =
       new SemiSupervisedLogConditionalObjectiveFunction(objective, biasedObjective, logPrior);
   if (initial == null) {
     initial = objective.initial();
   }
   double[] weights = minimizer.minimize(semiSupObjective, TOL, initial);
   return objective.to2D(weights);
 }
 /**
  * Trains the linear classifier using Generalized Expectation criteria as described in
  * <tt>Generalized Expectation Criteria for Semi Supervised Learning of Conditional Random
  * Fields</tt>, Mann and McCallum, ACL 2008. The original algorithm is proposed for CRFs but has
  * been adopted to LinearClassifier (which is a simpler special case of a CRF). IMPORTANT: the
  * labeled features that are passed as an argument are assumed to be binary valued, although other
  * features are allowed to be real valued.
  */
 public LinearClassifier<L, F> trainSemiSupGE(
     GeneralDataset<L, F> labeledDataset,
     List<? extends Datum<L, F>> unlabeledDataList,
     List<F> GEFeatures,
     double convexComboCoeff) {
   Minimizer<DiffFunction> minimizer = minimizerCreator.create();
   LogConditionalObjectiveFunction<L, F> objective =
       new LogConditionalObjectiveFunction<L, F>(
           labeledDataset, new LogPrior(LogPrior.LogPriorType.NULL));
   GeneralizedExpectationObjectiveFunction<L, F> geObjective =
       new GeneralizedExpectationObjectiveFunction<L, F>(
           labeledDataset, unlabeledDataList, GEFeatures);
   SemiSupervisedLogConditionalObjectiveFunction semiSupObjective =
       new SemiSupervisedLogConditionalObjectiveFunction(
           objective, geObjective, null, convexComboCoeff);
   double[] initial = objective.initial();
   double[] weights = minimizer.minimize(semiSupObjective, TOL, initial);
   return new LinearClassifier<L, F>(
       objective.to2D(weights), labeledDataset.featureIndex(), labeledDataset.labelIndex());
 }
 private NBWeights trainWeightsUCL(int[][] data, int[] labels, int numFeatures, int numClasses) {
   int[] numValues = numberValues(data, numFeatures);
   int[] sumValues = new int[numFeatures]; // how many feature-values are before this feature
   for (int j = 1; j < numFeatures; j++) {
     sumValues[j] = sumValues[j - 1] + numValues[j - 1];
   }
   int[][] newdata = new int[data.length][numFeatures + 1];
   for (int i = 0; i < data.length; i++) {
     newdata[i][0] = 0;
     for (int j = 0; j < numFeatures; j++) {
       newdata[i][j + 1] = sumValues[j] + data[i][j] + 1;
     }
   }
   int totalFeatures = sumValues[numFeatures - 1] + numValues[numFeatures - 1] + 1;
   System.err.println("total feats " + totalFeatures);
   LogConditionalObjectiveFunction<L, F> objective =
       new LogConditionalObjectiveFunction<L, F>(
           totalFeatures, numClasses, newdata, labels, prior, sigma, 0.0);
   Minimizer<DiffFunction> min = new QNMinimizer();
   double[] argmin = min.minimize(objective, 1e-4, objective.initial());
   double[][] wts = objective.to2D(argmin);
   System.out.println("weights have dimension " + wts.length);
   return new NBWeights(wts, numValues);
 }
  public Classifier<L, F> trainClassifier(Iterable<Datum<L, F>> dataIterable) {
    Minimizer<DiffFunction> minimizer = getMinimizer();
    Index<F> featureIndex = Generics.newIndex();
    Index<L> labelIndex = Generics.newIndex();
    for (Datum<L, F> d : dataIterable) {
      labelIndex.add(d.label());
      featureIndex.addAll(d.asFeatures()); // If there are duplicates, it doesn't add them again.
    }
    System.err.println(
        String.format(
            "Training linear classifier with %d features and %d labels",
            featureIndex.size(), labelIndex.size()));

    LogConditionalObjectiveFunction<L, F> objective =
        new LogConditionalObjectiveFunction<L, F>(dataIterable, logPrior, featureIndex, labelIndex);
    objective.setPrior(new LogPrior(LogPrior.LogPriorType.QUADRATIC));

    double[] initial = objective.initial();
    double[] weights = minimizer.minimize(objective, TOL, initial);

    LinearClassifier<L, F> classifier =
        new LinearClassifier<L, F>(objective.to2D(weights), featureIndex, labelIndex);
    return classifier;
  }