DecisionTree 二分类 ,指的是用决策树(Decision Tree) 解决二分类问题(如 0/1、是/否、流失/不流失)。
下面我从概念、原理、代码实现、典型场景几个方面来讲。
一、什么是决策树?
决策树是一种基于树形结构的分类/回归模型。它通过一系列"如果...那么..."的规则,把样本逐步划分到不同的叶子节点,每个叶子节点对应一个预测结果。
直观理解
想象你在判断一个人是否会买某款产品:
text
年龄 > 30?
├── 是:收入 > 10000?
│ ├── 是:会买 ✓
│ └── 否:不会买 ✗
└── 否:性别 = 男?
├── 是:会买 ✓
└── 否:不会买 ✗
这就是一棵决策树。
二、决策树的核心思想
决策树通过递归划分 数据,每次选择一个最优特征 和最优切分点 ,把数据分成两部分,使得划分后的子集纯度最高。
划分标准
| 指标 | 公式 | 说明 |
|---|---|---|
| 信息增益(ID3) | 熵 - 条件熵 | 划分后熵减少最多 |
| 信息增益率(C4.5) | 信息增益 / 特征熵 | 修正信息增益偏向多值特征的问题 |
| 基尼系数(CART) | 1 - Σp² | 划分后基尼不纯度最小 |
sklearn 默认用 CART + 基尼系数。
关键概念
| 概念 | 说明 |
|---|---|
| 根节点 | 树的起点,包含所有样本 |
| 内部节点 | 一个判断条件(如 年龄 > 30) |
| 叶子节点 | 最终的分类结果 |
| 深度 | 从根到叶的最长路径 |
| 剪枝 | 防止过拟合,去掉不必要的分支 |
三、代码实现
1. 基本用法
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, roc_auc_score, classification_report
# 生成二分类数据
X, y = make_classification(
n_samples=1000, n_features=20, n_informative=10,
n_redundant=5, weights=[0.9, 0.1],
random_state=42
)
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# 训练决策树
clf = DecisionTreeClassifier(random_state=42)
clf.fit(X_train, y_train)
# 预测
y_pred = clf.predict(X_test)
y_pred_prob = clf.predict_proba(X_test)[:, 1]
# 评估
print("准确率:", accuracy_score(y_test, y_pred))
print("AUC:", roc_auc_score(y_test, y_pred_prob))
print("\n分类报告:")
print(classification_report(y_test, y_pred))
2. 重要参数
clf = DecisionTreeClassifier(
criterion='gini', # 划分标准:'gini' 或 'entropy'
max_depth=5, # 树的最大深度
min_samples_split=10, # 内部节点再划分所需的最小样本数
min_samples_leaf=5, # 叶子节点最少样本数
max_features='sqrt', # 每次划分考虑的最大特征数
class_weight='balanced', # 类别不平衡时自动加权
random_state=42
)
| 参数 | 含义 | 作用 |
|---|---|---|
criterion |
划分标准 | 'gini'(默认)或 'entropy' |
max_depth |
树最大深度 | 限制深度,防过拟合 |
min_samples_split |
内部节点最小样本数 | 小于此值不再划分 |
min_samples_leaf |
叶子节点最小样本数 | 防止叶子样本太少 |
max_features |
每次划分考虑的特征数 | 'sqrt'、'log2'、整数、None |
max_leaf_nodes |
最大叶子数 | 限制树的规模 |
min_impurity_decrease |
最小不纯度减少 | 小于此值不划分 |
class_weight |
类别权重 | 'balanced' 自动处理不平衡 |
ccp_alpha |
代价复杂度剪枝 | 后剪枝,防过拟合 |
random_state |
随机种子 | 保证可复现 |
3. 处理类别不平衡
# 方法1:class_weight='balanced'
clf = DecisionTreeClassifier(class_weight='balanced', random_state=42)
# 方法2:手动指定权重
clf = DecisionTreeClassifier(class_weight={0: 1, 1: 9}, random_state=42)
# 方法3:采样(SMOTE 等)
# 见前面"SMOTE过采样"章节
class_weight='balanced' 会自动按类别频率的反比设置权重。
4. 防止过拟合
决策树不加限制时容易过拟合(可以一直划分到每个叶子只有一个样本)。常用方法:
# 方法1:限制深度
clf = DecisionTreeClassifier(max_depth=5, random_state=42)
# 方法2:限制叶子样本数
clf = DecisionTreeClassifier(min_samples_leaf=10, random_state=42)
# 方法3:限制叶子节点数
clf = DecisionTreeClassifier(max_leaf_nodes=20, random_state=42)
# 方法4:后剪枝(代价复杂度剪枝)
clf = DecisionTreeClassifier(ccp_alpha=0.01, random_state=42)
5. 可视化决策树
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
plt.figure(figsize=(20, 10))
plot_tree(
clf,
feature_names=[f'f{i}' for i in range(X.shape[1])],
class_names=['负类', '正类'],
filled=True,
rounded=True,
fontsize=10
)
plt.show()
6. 特征重要性
import pandas as pd
# 特征重要性
importance = pd.DataFrame({
'feature': [f'f{i}' for i in range(X.shape[1])],
'importance': clf.feature_importances_
}).sort_values('importance', ascending=False)
print(importance)
输出示例:
feature importance
2 f2 0.3521
7 f7 0.2145
0 f0 0.1234
...
含义:重要性越高,该特征对分类的贡献越大。
7. 交叉验证
from sklearn.model_selection import cross_val_score
scores = cross_val_score(clf, X, y, cv=5, scoring='roc_auc')
print("5折交叉验证 AUC:", scores.mean())
8. 在 Pipeline 中使用
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.tree import DecisionTreeClassifier
pipe = Pipeline([
('scaler', StandardScaler()), # 决策树不需要标准化,这里仅为演示
('clf', DecisionTreeClassifier(max_depth=5, random_state=42))
])
pipe.fit(X_train, y_train)
print("Pipeline 准确率:", pipe.score(X_test, y_test))
注意 :决策树不需要标准化,因为它是基于分裂点的,对特征尺度不敏感。
9. 网格搜索调参
from sklearn.model_selection import GridSearchCV
param_grid = {
'max_depth': [3, 5, 7, 10],
'min_samples_split': [2, 5, 10],
'min_samples_leaf': [1, 2, 5],
'criterion': ['gini', 'entropy']
}
grid = GridSearchCV(
DecisionTreeClassifier(random_state=42),
param_grid,
cv=5,
scoring='roc_auc',
n_jobs=-1
)
grid.fit(X_train, y_train)
print("最优参数:", grid.best_params_)
print("最优 AUC:", grid.best_score_)
四、决策树的优缺点
优点
-
可解释性强:可以画出树,规则清晰,业务容易理解。
-
不需要标准化:基于分裂点,对特征尺度不敏感。
-
能处理混合类型:数值、类别都可以。
-
能处理非线性:自动捕捉非线性关系。
-
不需要特征工程:自动做特征选择。
-
训练快:相比 DNN,训练速度快。
-
能输出特征重要性:方便特征筛选。
缺点
-
容易过拟合:不加限制时,可以一直划分到每个叶子一个样本。
-
不稳定:数据微小变化可能导致树结构大幅变化。
-
偏向多值特征:信息增益偏向取值多的特征(C4.5 用增益率修正)。
-
不擅长处理线性关系:需要用多个分裂逼近线性边界。
-
对类别不平衡敏感 :需要用
class_weight或采样。 -
单棵树效果有限:通常不如随机森林、XGBoost。
五、决策树 vs 其他模型
| 维度 | 决策树 | 逻辑回归 | 随机森林 | XGBoost |
|---|---|---|---|---|
| 可解释性 | 强 | 强 | 中 | 中 |
| 非线性 | 强 | 弱 | 强 | 强 |
| 过拟合风险 | 高 | 低 | 低 | 低 |
| 训练速度 | 快 | 快 | 中 | 中 |
| 效果 | 中 | 中 | 好 | 最好 |
| 需要标准化 | 否 | 是 | 否 | 否 |
| 特征重要性 | 有 | 无 | 有 | 有 |
实践建议:
-
需要可解释性 → 决策树、逻辑回归。
-
追求效果 → 随机森林、XGBoost、LightGBM。
-
决策树通常作为集成模型的基学习器。
六、典型应用场景
| 场景 | 说明 |
|---|---|
| 风控 | 信用评分、欺诈检测 |
| 医疗 | 疾病诊断规则 |
| 营销 | 用户流失预测、转化预测 |
| 推荐 | 是否点击、是否购买 |
| 工业 | 故障诊断 |
| 规则提取 | 从数据中提取业务规则 |
七、关键提醒
-
必须限制深度 :不加限制会过拟合,用
max_depth、min_samples_leaf等。 -
不需要标准化:决策树对特征尺度不敏感。
-
处理类别不平衡 :用
class_weight='balanced'或采样。 -
随机种子要固定 :
random_state=42保证可复现。 -
注意特征重要性偏差:决策树偏向多值特征,可用 permutation importance 修正。
-
单棵树效果有限:实际应用中多用随机森林、XGBoost。
-
可以输出概率 :
predict_proba返回每个类别的概率。 -
可视化很直观 :
plot_tree可以画出树结构,方便业务解释。
八、决策树的重要属性
| 属性 | 说明 |
|---|---|
tree_ |
底层树结构 |
feature_importances_ |
特征重要性 |
classes_ |
类别标签 |
n_classes_ |
类别数 |
max_depth |
实际最大深度 |
n_leaves_ |
叶子节点数 |
n_features_in_ |
输入特征数 |
九、决策树的重要方法
| 方法 | 说明 |
|---|---|
fit(X, y) |
训练 |
predict(X) |
预测类别 |
predict_proba(X) |
预测概率 |
predict_log_proba(X) |
预测对数概率 |
score(X, y) |
准确率 |
apply(X) |
返回每个样本所在的叶子节点索引 |
decision_path(X) |
返回决策路径 |
十、总结
DecisionTree 二分类 = 用决策树解决二分类问题。
-
核心思想:递归划分,每次选最优特征和切分点,让子集纯度最高。
-
划分标准:基尼系数(默认)、信息增益、信息增益率。
-
sklearn 实现 :
DecisionTreeClassifier。 -
关键参数 :
max_depth、min_samples_split、min_samples_leaf、class_weight。 -
核心价值:可解释性强、不需要标准化、自动特征选择、能输出特征重要性。
-
主要代价:容易过拟合、不稳定、单棵树效果有限。
-
关键原则:限制深度、处理不平衡、固定随机种子、注意特征重要性偏差。
它和前面讲的 DNN 二分类、逻辑回归二分类、XGBoost 二分类一样,都是二分类算法,区别在于决策树可解释性最强、最容易理解 ,但单棵树效果有限 ,实际应用中通常作为随机森林、GBDT、XGBoost 的基学习器。