EnsembleModel<Label> trainModel(List<Example<Label>> trainingData, TaskMonitor monitor)
			throws CancelledException {
		LabelFactory lf = new LabelFactory();
		ListDataSource<Label> trainingSource = new ListDataSource<>(trainingData, lf,
			new SimpleDataSourceProvenance(program.getDomainFile().getPathname(), lf));
		trainingSet = new MutableDataset<>(trainingSource);

		//want to select from sqrt(num features) features at each split
		float featureFraction = (float) (1.0f / Math.sqrt(trainingSet.getFeatureMap().size()));

		List<CARTClassificationTrainer> trainers = new ArrayList<>();
		for (int i = 0; i < NUM_TREES; ++i) {
			monitor.checkCancelled();
			//Integer.MAX_VALUE: unlimited depth
			trainers.add(new CARTClassificationTrainer(Integer.MAX_VALUE, featureFraction,
				ThreadLocalRandom.current().nextLong()));
		}

		GThreadPool threadPool = GThreadPool.getSharedThreadPool(RANDOM_FOREST_TRAINING_THREADPOOL);
		monitor.initialize(NUM_TREES);
		monitor.setMessage("Training random forest");

		ConcurrentQBuilder<CARTClassificationTrainer, TreeModel<Label>> builder =
			new ConcurrentQBuilder<>();
		ConcurrentQ<CARTClassificationTrainer, TreeModel<Label>> q =
			builder.setThreadPool(threadPool)
					.setCollectResults(true)
					.setMonitor(monitor)
					.build(new SingleTreeTrainer());
		q.add(trainers);
		EnsembleModel<Label> randomForest = null;
		try {
			long start = System.nanoTime();
			var results = q.waitForResults();
			long end = System.nanoTime();
			Msg.info(this,
				String.format("Training time: %g seconds", (end - start) / NANOSECONDS_PER_SECOND));
			List<Model<Label>> trees = new ArrayList<>();
			for (var r : results) {
				trees.add(r.getResult());
			}
			randomForest = WeightedEnsembleModel.createEnsembleFromExistingModels("rf", trees,
				new VotingCombiner());
		}
		catch (Exception e) {
			monitor.checkCancelled();
			Msg.error(this, "Exception while training model: " + e.getMessage());
		}
		return randomForest;
	}
Trains a model to recognize function entries.  Training is performed in parallel.
@param trainingData training vectors
@param monitor task monitor
@return model
@throws CancelledException if monitor is canceled
Ghidra/Extensions/MachineLearning/src/main/java/ghidra/machinelearning/functionfinding/RandomForestTrainingTask.java