public RandomForest trim(int ntrees) {
        if (ntrees > models.length) {
            throw new IllegalArgumentException("The new model size is larger than the current size.");
        }
        
        if (ntrees <= 0) {
            throw new IllegalArgumentException("Invalid new model size: " + ntrees);
        }

        Arrays.sort(models, Comparator.comparingDouble(model -> -model.weight));

        // The OOB metrics are still the old one
        // as we don't access to the training data here.
        return new RandomForest(formula, k, Arrays.copyOf(models, ntrees), metrics, importance(models), classes);
    }
@Test
    public void testTrim() {
        System.out.println("trim");

        RandomForest model = RandomForest.fit(Segment.formula, Segment.train, 200, 16, SplitRule.GINI, 20, 100, 5, 1.0, null, Arrays.stream(seeds));
        System.out.println(model.metrics());
        assertEquals(200, model.size());

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

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

        RandomForest trimmed = model.trim(100);
        assertEquals(200, model.size());
        assertEquals(100, trimmed.size());

        double weight1 = Arrays.stream(model.models()).mapToDouble(m -> m.weight).min().getAsDouble();
        double weight2 = Arrays.stream(trimmed.models()).mapToDouble(m -> m.weight).min().getAsDouble();
        assertTrue(weight2 > weight1);

        prediction = trimmed.predict(Segment.test);
        error = Error.of(Segment.testy, prediction);

        System.out.println("Error after trim = " + error);
        assertEquals(32, error);
    }