Machine Learning Academy · 강의

결정 트리 시각화와 해석

sklearn의 plot_tree로 트리를 내보내고 렌더링하며, 결정 규칙을 읽고, 이해관계자 보고서를 위한 특성 중요도를 추출합니다.

레슨 4/413개 단계

결정 트리 시각화와 해석은(는) CoddyKit의 무료 Machine Learning Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Machine Learning Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Machine Learning Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

Why Tree Visualisation Matters

Decision trees are often called white-box models because their decision logic is fully transparent. Visualising a trained tree lets you: verify the model is making decisions based on sensible features, explain predictions to non-technical stakeholders, identify potential data quality issues (e.g., a feature that should not be important appearing at the root), and debug unexpected behaviour. Visualisation turns the tree's mathematical structure into a human-readable flowchart that domain experts can validate against their knowledge.

from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

X, y = load_iris(return_X_y=True)
feature_names = load_iris().feature_names
class_names   = load_iris().target_names

tree = DecisionTreeClassifier(max_depth=3, random_state=42)
tree.fit(X, y)

plt.figure(figsize=(14, 6))
plot_tree(tree,
          feature_names=feature_names,
          class_names=class_names,
          filled=True,      # Color by majority class
          rounded=True,     # Rounded boxes
          fontsize=10)
plt.title('Iris Decision Tree (depth=3)')
plt.show()

Reading a Node in plot_tree Output

Each node in the plot_tree output shows four pieces of information: (1) The split condition (e.g., petal length <= 2.45), (2) The Gini impurity of the node, (3) The number of samples that reached this node during training, and (4) The class distribution as a list of sample counts per class. Leaf nodes show all four but no split condition — the majority class is the prediction. Node colour intensity indicates purity: darker = more samples of the dominant class.

# Interpreting node output from plot_tree:
#
# petal length (cm) <= 2.45     <- split condition
# gini = 0.667                  <- impurity before split
# samples = 150                 <- training samples reaching node
# value = [50, 50, 50]          <- samples per class [setosa, versicolor, virginica]
# class = setosa                <- majority class (prediction if leaf)

print('Gini 0.667 = equal 3-class split (maximum 3-class impurity)')
print('samples=150 at root = all training samples')
print('value=[50,50,50] = perfectly balanced classes')

Exporting Tree as Text with export_text

For logging, reports, or environments without graphical display, export_text() produces a text-based representation of the tree. Each level of indentation represents one split level. The pipe character shows branches, and leaf lines show the predicted class. This format is useful for embedding decision rules in documentation, saving to log files, or displaying in command-line environments. It also allows comparing tree structures numerically across different hyperparameter configurations.

from sklearn.tree import DecisionTreeClassifier, export_text
from sklearn.datasets import load_iris

X, y = load_iris(return_X_y=True)
tree = DecisionTreeClassifier(max_depth=3, random_state=42)
tree.fit(X, y)

text_repr = export_text(
    tree,
    feature_names=list(load_iris().feature_names)
)
print(text_repr)

Exporting to Graphviz DOT Format

export_graphviz() generates a DOT language file that can be rendered as a high-quality SVG or PNG using Graphviz. This is ideal for presentation-quality tree diagrams and for large trees that need scrolling to view. The DOT file can also be converted to a PDF or embedded in reports. In Jupyter, use graphviz.Source(dot_data) to render inline. This approach gives full control over font size, colour scheme, and layout — important when the tree is shared with business stakeholders.

from sklearn.tree import export_graphviz
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
import graphviz

X, y = load_iris(return_X_y=True)
tree = DecisionTreeClassifier(max_depth=3, random_state=42)
tree.fit(X, y)

dot_data = export_graphviz(
    tree,
    out_file=None,
    feature_names=load_iris().feature_names,
    class_names=load_iris().target_names,
    filled=True, rounded=True,
    special_characters=True
)
# graph = graphviz.Source(dot_data)  # Renders in Jupyter
# graph.render('iris_tree', format='png')  # Save as PNG

Feature Importances: What Drove the Model?

After training, tree.feature_importances_ reveals the relative contribution of each input feature to the model's predictions. Features used at the root and upper levels typically have high importance because their splits affect all training samples. Features used only in deep leaves have low importance. Plotting feature importances as a bar chart is a standard step in any tree-based analysis — it confirms that the model relies on sensible, domain-relevant features rather than spurious correlates that happen to work on training data.

from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
import pandas as pd
import matplotlib.pyplot as plt

X, y = load_breast_cancer(return_X_y=True)
features = load_breast_cancer().feature_names

tree = DecisionTreeClassifier(max_depth=5, random_state=42)
tree.fit(X, y)

imp = pd.Series(tree.feature_importances_, index=features).sort_values(ascending=False)

imp.head(10).plot(kind='barh')
plt.title('Top 10 Feature Importances')
plt.xlabel('Importance')
plt.gca().invert_yaxis()
plt.show()

print('Top feature:', imp.index[0], '(importance:', imp.iloc[0].round(3), ')')

Tracing a Single Prediction

The decision_path() method returns a sparse indicator matrix showing which nodes each sample visits. Combined with tree.tree_, you can reconstruct the exact sequence of decisions for any prediction. This is the foundation of automated explanation systems: for each prediction, you can generate a human-readable list of rules like 'petal length was 1.4 cm (≤2.45), so went left; ended at leaf predicting setosa.' This level of transparency is required in regulated domains where every decision must be auditable.

from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
import numpy as np

X, y = load_iris(return_X_y=True)
features = load_iris().feature_names
tree = DecisionTreeClassifier(max_depth=3, random_state=42)
tree.fit(X, y)

# Trace the path for sample 0
node_indicator = tree.decision_path(X[[0]])
nodes_visited = node_indicator.indices

T = tree.tree_
for node in nodes_visited[:-1]:  # All except leaf
    feature = features[T.feature[node]]
    threshold = T.threshold[node]
    val = X[0, T.feature[node]]
    direction = 'left (<= )' if val <= threshold else 'right (> )'
    print(f'Node {node}: {feature} = {val:.2f}, threshold={threshold:.2f} -> {direction}')

Interpreting Split Conditions for Stakeholders

When communicating tree decisions to non-technical stakeholders, convert the mathematical split conditions into plain-language statements. Instead of 'petal length (cm) <= 2.45: gini=0.0, samples=50', say 'If the petal is shorter than 2.45 cm, the flower is almost certainly a Setosa.' Frame each branch in terms of the business meaning of the feature. Decision trees are uniquely suited to stakeholder communication among ML models because every decision corresponds to a testable, interpretable business rule.

# Human-readable rule extraction from a trained tree
from sklearn.tree import _tree

def extract_rules(tree, feature_names, class_names):
    T = tree.tree_
    rules = []
    
    def recurse(node, path):
        if T.feature[node] != _tree.TREE_UNDEFINED:
            feat = feature_names[T.feature[node]]
            thresh = T.threshold[node]
            recurse(T.children_left[node],  path + [f'{feat} <= {thresh:.2f}'])
            recurse(T.children_right[node], path + [f'{feat} > {thresh:.2f}'])
        else:
            majority_class = class_names[T.value[node].argmax()]
            rules.append(' AND '.join(path) + f' => {majority_class}')
    
    recurse(0, [])
    return rules

Partial Dependence Plots for Individual Features

While feature importances show which features matter most, Partial Dependence Plots (PDP) show how a feature influences the prediction. A PDP marginalises over all other features and plots the model's predicted output as a function of one (or two) features. For decision trees, PDPs produce step-function shapes reflecting the axis-aligned split thresholds. Scikit-learn's PartialDependenceDisplay generates these plots directly from a fitted tree, making it easy to explain individual feature effects to domain experts.

from sklearn.inspection import PartialDependenceDisplay
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

X, y = load_iris(return_X_y=True)
features = load_iris().feature_names

tree = DecisionTreeClassifier(max_depth=4, random_state=42)
tree.fit(X, y)

# PDP for the two most important features
fig, ax = plt.subplots(figsize=(10, 4))
PartialDependenceDisplay.from_estimator(
    tree, X, features=[2, 3],  # petal length and petal width
    feature_names=features, ax=ax
)
plt.tight_layout()
plt.show()

Comparing Tree Structures Across Hyperparameters

Visualising how the tree structure changes with depth helps build intuition. A depth-1 tree (stump) has one split and two leaves — the most important single feature. A depth-2 tree refines both branches with a second level of questions. Comparing trees at depth 1, 3, and 5 on the same dataset shows how the model builds increasingly complex decision logic. If the depth-5 tree uses the same features as the depth-3 tree at its top levels, those features are genuinely important. If new, obscure features appear at depth 5, they are likely capturing noise.

from sklearn.tree import DecisionTreeClassifier, export_text
from sklearn.datasets import load_iris

X, y = load_iris(return_X_y=True)
feat_names = list(load_iris().feature_names)

for depth in [1, 3, 5]:
    tree = DecisionTreeClassifier(max_depth=depth, random_state=42)
    tree.fit(X, y)
    print(f'\n--- max_depth={depth}, leaves={tree.get_n_leaves()} ---')
    print(export_text(tree, feature_names=feat_names)[:300])

Using Trees to Generate Business Rules

One of the most valuable uses of decision trees in industry is generating explicit business rules that can be implemented in rule engines, spreadsheets, or legacy systems that cannot run ML models. Each path from root to leaf is a complete IF-THEN rule. These rules can be translated into SQL WHERE clauses, Python dictionaries, or credit-scoring scorecards. By carefully controlling tree depth and minimum sample constraints, you can generate a small, high-accuracy rule set that a business analyst can manually review, approve, and maintain.

# Generate SQL-like rules from a trained decision tree
from sklearn.tree import _tree

def tree_to_sql(tree, feature_names, class_names):
    T = tree.tree_
    rules = []
    
    def traverse(node, conditions):
        if T.feature[node] != _tree.TREE_UNDEFINED:
            fname = feature_names[T.feature[node]]
            thresh = T.threshold[node]
            traverse(T.children_left[node],
                     conditions + [f'{fname} <= {thresh:.3f}'])
            traverse(T.children_right[node],
                     conditions + [f'{fname} > {thresh:.3f}'])
        else:
            pred = class_names[T.value[node].argmax()]
            where = ' AND '.join(conditions)
            rules.append(f'WHEN {where} THEN {pred!r}')
    
    traverse(0, [])
    return 'CASE\n  ' + '\n  '.join(rules) + '\nEND',

Saving Tree Visualisations to Files

Saving tree visualisations to files makes them shareable in reports, presentations, and model documentation. With plot_tree and matplotlib, save as PNG or SVG using plt.savefig(). With Graphviz, render to PDF directly. For interactive exploration in Jupyter notebooks, inline SVG provides the clearest output because it is infinitely scalable — useful for deep trees that would be blurry as a fixed-resolution PNG. For stakeholder deliverables, always export at high DPI (300+) or as vector SVG format so the text in nodes remains crisp when zoomed.

from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

X, y = load_iris(return_X_y=True)
tree = DecisionTreeClassifier(max_depth=3, random_state=42)
tree.fit(X, y)

# Save as high-DPI PNG for reports
fig, ax = plt.subplots(figsize=(16, 8))
plot_tree(tree, feature_names=load_iris().feature_names,
          class_names=load_iris().target_names,
          filled=True, rounded=True, ax=ax, fontsize=10)
fig.savefig('iris_decision_tree.png', dpi=200, bbox_inches='tight')
fig.savefig('iris_decision_tree.svg', format='svg', bbox_inches='tight')
print('Saved PNG and SVG tree visualisations')

Quick Check

Test your understanding of Machine Learning with Python concepts from this lesson.

Lesson Recap

In this lesson you learned: how to visualise decision trees using plot_tree, export_text, and export_graphviz, how to read node information (split condition, Gini, samples, value), and how to extract feature importances and decision paths for stakeholder communication. Next up we explore Naive Bayes — a probabilistic classifier that applies Bayes' theorem to make predictions.

무료로 시작

AI 튜터와 함께 Python을(를) 배우세요 — 무료

브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.

코스
30
레슨
120

자주 묻는 질문

“결정 트리 시각화와 해석” 강의는 무료인가요?

네 — “결정 트리 시각화와 해석” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Machine Learning Academy 강의 전체를 잠금 해제할 수 있습니다. Machine Learning Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“결정 트리 시각화와 해석”에서 뭘 배우나요?

sklearn의 plot_tree로 트리를 내보내고 렌더링하며, 결정 규칙을 읽고, 이해관계자 보고서를 위한 특성 중요도를 추출합니다. 브라우저에서 직접 실행하는 실습 코드로 Machine Learning Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Machine Learning Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Machine Learning Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“결정 트리 시각화와 해석” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Machine Learning Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Machine Learning Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 트리 만들기: 분할, 노드, 잎
  2. 지니 불순도와 정보 이득
  3. 과적합 방지를 위한 트리 깊이 제어
  4. 결정 트리 시각화와 해석
← Machine Learning Academy(으)로 돌아가기