public void extractFeatures(List regions) throws FeatureExtractorException {
    // Construct a feature set.
    FeatureSet feature_set = fs.newInstance();

    // Extract spectrum features.
    feature_set.setDataPoints((List<Word>) regions);
    try {
      PartitionUtils
          .assignStratifiedFoldNum((List<Word>) regions, FOLD_ASSIGNMENT_FEATURE, num_folds,
              feature_set.getClassAttribute());
    } catch (AuToBIException e) {
      throw new FeatureExtractorException(e.getMessage());
    }

    // Train n-fold cross validated prediction features.
    for (int fold_num = 0; fold_num < num_folds; ++fold_num) {
      AuToBIClassifier classifier = new WekaClassifier(new J48());

      FeatureSet training_fs = fs.newInstance();

      List<Word> training_regions = new ArrayList<Word>();
      List<Word> testing_regions = new ArrayList<Word>();
      try {
        PartitionUtils
            .splitData((List<Word>) regions, training_regions, testing_regions, fold_num, FOLD_ASSIGNMENT_FEATURE);
      } catch (AuToBIException e) {
        // This should never happen.  If there is a problem with splitData it would have thrown
        // an exception during the fold assignment method assignStratifiedFoldNum
        throw new FeatureExtractorException(e.getMessage());
      }
      training_fs.setDataPoints(training_regions);
      training_fs.constructFeatures();
      try {
        classifier.train(training_fs);
      } catch (Exception e) {
        throw new FeatureExtractorException(e.getMessage());
      }

      for (Word w : testing_regions) {
        try {
          Distribution result = classifier.distributionForInstance(w);

          w.setAttribute("nominal_bark_" + low + "_" + high + "__prediction", result.getKeyWithMaximumValue());
          w.setAttribute("bark_" + low + "_" + high + "__prediction_confidence",
              result.get(result.getKeyWithMaximumValue()));
          w.setAttribute("bark_" + low + "_" + high + "__prediction_confidence_accented", result.get(ACCENTED_VALUE));
        } catch (Exception e) {
          throw new FeatureExtractorException(e.getMessage());
        }
      }
    }
  }