scikit-learn Onboarding LabChapter III — Concrete estimators: combining BaseEstimator with role mixins0/5Contents
Chapter III

Concrete estimators: combining BaseEstimator with role mixins

DecisionTreeClassifier shows the standard scikit-learn estimator recipe: inherit BaseEstimator (params, tags, repr) plus a role mixin like ClassifierMixin (score(), classifier tag) through BaseDecisionTree, then implement only the estimator-specific fit/predict logic. Input validation is delegated to sklearn.utils.validation helpers (validate_data, check_is_fitted) and the actual tree construction/inference is delegated to compiled Cython objects (Tree, DepthFirstTreeBuilder/BestFirstTreeBuilder). Learning this composition — mixin for role contract, BaseEstimator for plumbing, thin Python fit/predict wrapping a validated array and a compiled core — is the template for reading or writing any other estimator in the codebase.


How DecisionTreeClassifier is assembled
BaseEstimatorsklearn/base.py
ClassifierMixinsklearn/base.py
MultiOutputMixinsklearn/base.py
BaseDecisionTreesklearn/tree/_classes.py
DecisionTreeClassifiersklearn/tree/_classes.py
utils.validationsklearn/tree/_classes.py
Cython Tree / TreeBuildersklearn/tree/_classes.py
Figure I · Click a node to see what it does, where it lives in the code, and its labeled connections — the annotation opens beside it.
class BaseDecisionTree(MultiOutputMixin, BaseEstimator, metaclass=ABCMeta):    """Base class for decision trees.    Warning: This class should not be used directly.    Use derived classes instead.    """
sklearn/tree/_classes.py · lines 8994
Figure II · Note the MRO order: mixins come before BaseEstimator. The same pattern repeats one level down — class DecisionTreeClassifier(ClassifierMixin, BaseDecisionTree): — putting ClassifierMixin first so its score()/tag overrides take priority over the base class's defaults.
        check_is_fitted(self)        X = self._validate_X_predict(X, check_input)        proba = self.tree_.predict(X)        n_samples = X.shape[0]        # Classification        if is_classifier(self):            if self.n_outputs_ == 1:                return self.classes_.take(np.argmax(proba, axis=1), axis=0)
sklearn/tree/_classes.py · lines 520528
Figure III · predict() calls self.tree_.predict(X) — a compiled Cython Tree object built during fit() — and just decodes the raw probability rows back into original class labels via self.classes_. All the expensive work (traversing splits for every sample) happens in compiled code; the Python method is a thin wrapper around it.
checkpoint

Check your understanding

Answered in place — nothing is graded, everything is explained. 0 / 2 passed

Why is `DecisionTreeClassifier` declared as `class DecisionTreeClassifier(ClassifierMixin, BaseDecisionTree):` with the mixin listed first?

Where does the actual tree-splitting computation happen during DecisionTreeClassifier.fit()?