public RandomForest prune(DataFrame test) {
        Model[] forest = Arrays.stream(models).parallel()
                .map(model -> new Model(model.tree.prune(test, formula, classes), model.metrics))
                .toArray(Model[]::new);

        // The tree weight and OOB metrics are still the old one
        // as we don't access to the training data here.
        return new RandomForest(formula, k, forest, metrics, importance(forest), classes);
    }
@Test
    public void testPrune() {
        System.out.println("prune");

        // Overfitting with very large maxNodes and small nodeSize
        RandomForest model = RandomForest.fit(USPS.formula, USPS.train, 200, 16, SplitRule.GINI, 20, 2000, 1, 1.0, null, Arrays.stream(seeds));

        double[] importance = model.importance();
        for (int i = 0; i < importance.length; i++) {
            System.out.format("%-15s %.4f%n", model.schema().name(i), importance[i]);
        }

        int[] prediction = model.predict(USPS.test);
        int error = Error.of(USPS.testy, prediction);

        System.out.println("Error = " + error);
        assertEquals(115, error);

        RandomForest lean = model.prune(USPS.test);

        importance = lean.importance();
        for (int i = 0; i < importance.length; i++) {
            System.out.format("%-15s %.4f%n", lean.schema().name(i), importance[i]);
        }

        // The old model should not be modified.
        prediction = model.predict(USPS.test);
        error = Error.of(USPS.testy, prediction);

        System.out.println("Error of old model after pruning = " + error);
        assertEquals(115, error);

        prediction = lean.predict(USPS.test);
        error = Error.of(USPS.testy, prediction);

        System.out.println("Error of pruned model after pruning = " + error);
        assertEquals(87, error);
    }