protected static void predict(String[] args) {
    if (args.length != 3) {
      System.out.println(
          "Please specify the path for the test data as the second argument "
              + "and the path to save the predictions as the third argument.");
    } else {
      final String testDataFilename = args[1];

      try {
        // Parse the sparse testing data.
        final Map.Entry<List<SparseLineAST>, Integer> instancesToMaxFeatureIndex =
            SparseLineAST.parseSparseEncodingFromInputFilename(
                testDataFilename, new SparseLineAST.NumericValidator());
        final List<SparseLineAST> instances = instancesToMaxFeatureIndex.getKey();
        final int maxFeatureIndex = instancesToMaxFeatureIndex.getValue();

        // Initialize the classifier from the file data.
        DiscretizingNaiveBayesClassifier classifier = new DiscretizingNaiveBayesClassifier();
        classifier.initializeFromFileData(loadTrainedModelFileData());

        // Make predictions.
        // int numCorrectPredictions = 0;	// TODO: Remove debug code.
        List<Integer> predictedClassIndices = new ArrayList<Integer>(instances.size());
        for (SparseLineAST instance : instances) {
          final int predictedClassIndex = classifier.getPrediction(instance);
          predictedClassIndices.add(predictedClassIndex);

          /*
          // TODO: Remove debug code.
          final int correctClassIndex = Integer.parseInt(instance.getOutput());
          if (predictedClassIndex == correctClassIndex) {
          	numCorrectPredictions += 1;
          }
          //*/
        }

        /*
        // TODO: Remove debug code.
        System.out.println(String.format("%d of %d predicted correctly (%f).",
        		numCorrectPredictions, predictedClassIndices.size(),
        		numCorrectPredictions / (double) predictedClassIndices.size()));
        //*/

        // Save the predictions to file.
        final String predictionsFilename = args[2];
        savePredictions(predictionsFilename, predictedClassIndices);
      } catch (RuntimeException x) {
        System.out.println(x.getMessage());
      }
    }
  }
  protected static void generate(String[] args) {
    if (args.length != 3) {
      System.out.println(
          "Please specify the number of instances as the second argument "
              + "and the path to save the instances as the third argument.");
    } else {
      final int numInstances = Integer.parseInt(args[1]);
      final String dataFilename = args[2];

      // Initialize the classifier from the file data.
      DiscretizingNaiveBayesClassifier classifier = new DiscretizingNaiveBayesClassifier();
      classifier.initializeFromFileData(loadTrainedModelFileData());

      SparseLineAST.saveSparseEncoding(
          dataFilename, classifier.generateLabeledInstances(numInstances));
    }
  }
  protected static void randomLearn(String[] args) {
    if (args.length != 3) {
      System.out.println(
          "Please specify the number of classes as the second argument "
              + "and the number of features as the third argument.");
    } else {
      final int numClassIndices = Integer.parseInt(args[1]);
      final int maxFeatureIndex = Integer.parseInt(args[2]);

      // Initialize the classifier to random parameters.
      DiscretizingNaiveBayesClassifier classifier = new DiscretizingNaiveBayesClassifier();
      classifier.initializeRandomly(
          DiscretizingNaiveBayesClassifier.makeClassIndexSet(numClassIndices),
          maxFeatureIndex,
          new DiscretizingNaiveBayesClassifier.SimpleBinaryDiscretizer());

      // Save the trained model.
      saveTrainedModelFileData(classifier.toFileData());
    }
  }
  protected static void semiSupervisedLearn(String[] args) {
    if (args.length < 2) {
      System.out.println(
          "Please specify the path for the training data as the second argument. "
              + "(Optionally, you can give the number of EM iterations as the third argument.)");
    } else {
      final String trainingDataFilename = args[1];

      int maxNumIterations;
      if (args.length == 3) {
        maxNumIterations = Integer.parseInt(args[2]);
      } else {
        maxNumIterations = Integer.MAX_VALUE;
      }

      try {
        // Parse the sparse training data.
        final Map.Entry<List<SparseLineAST>, Integer> instancesToMaxFeatureIndex =
            SparseLineAST.parseSparseEncodingFromInputFilename(
                trainingDataFilename,
                new SparseLineAST.SemiSupervisedTrainingValidator(
                    new SparseLineAST.NumericValidator()));
        final List<SparseLineAST> instances = instancesToMaxFeatureIndex.getKey();
        final int maxFeatureIndex = instancesToMaxFeatureIndex.getValue();

        // Initialize and train the classifier on the training data.
        DiscretizingNaiveBayesClassifier classifier =
            DiscretizingNaiveBayesClassifierEMTrainer.train(
                getKForSmoothing().getSecond(),
                instances,
                maxFeatureIndex,
                new DiscretizingNaiveBayesClassifier.SimpleBinaryDiscretizer(),
                maxNumIterations);

        // Save the trained model.
        saveTrainedModelFileData(classifier.toFileData());
      } catch (RuntimeException x) {
        System.out.println(x.getMessage());
      }
    }
  }
  protected static void learn(String[] args) {
    if (args.length != 2) {
      System.out.println("Please specify the path for the training data as the second argument.");
    } else {
      final String trainingDataFilename = args[1];

      try {
        // Parse the sparse training data.
        // Note: "u" outputs for training instances are accepted; they'll just be ignored.
        final Map.Entry<List<SparseLineAST>, Integer> instancesToMaxFeatureIndex =
            SparseLineAST.parseSparseEncodingFromInputFilename(
                trainingDataFilename,
                new SparseLineAST.SemiSupervisedTrainingValidator(
                    new SparseLineAST.NumericValidator()));
        final List<SparseLineAST> instances = instancesToMaxFeatureIndex.getKey();
        final int maxFeatureIndex = instancesToMaxFeatureIndex.getValue();

        // Ignore unlabeled instances.
        final List<SparseLineAST> labeledInstances = SparseLineAST.getLabeledInstances(instances);

        // Initialize and train the classifier on the training data.
        DiscretizingNaiveBayesClassifier classifier = new DiscretizingNaiveBayesClassifier();
        classifier.initialize(getKForSmoothing().getSecond());
        classifier.train(
            labeledInstances,
            maxFeatureIndex,
            new DiscretizingNaiveBayesClassifier.SimpleBinaryDiscretizer());

        // Save the trained model.
        saveTrainedModelFileData(classifier.toFileData());
      } catch (RuntimeException x) {
        System.out.println(x.getMessage());
        for (StackTraceElement element : x.getStackTrace()) {
          System.out.println(element);
        }
      }
    }
  }