共计 2531 个字符,预计需要花费 7 分钟才能阅读完成。
1. 小样本数据建模的痛点
当手头只有 100 组数据时,传统机器学习方法往往会遇到两个致命问题:

- 维度灾难:当特征数量接近样本量时,模型容易记住噪声而非规律。例如 100 样本×30 特征的数据,决策树可能生成毫无意义的复杂分叉
- 过拟合陷阱:在小数据上表现完美的模型,实际部署时准确率骤降。我曾用未剪枝的决策树在训练集达到 100% 准确率,测试集却不足 60%
2. 为什么选择决策树?
决策树天然适合小数据场景,原因有三:
- 白盒解释性:每个分裂节点都可追溯业务逻辑,避免黑箱模型的不可控风险
- 低计算开销:相比 SVM 或神经网络,决策树在百级数据量上训练仅需毫秒级时间
- 自动特征选择:通过特征重要性排序,可快速识别关键变量(后文会演示可视化方法)
但需警惕其局限性——默认参数下的决策树会不断分裂直到纯净节点,导致严重的过拟合。
3. 实战代码全流程
3.1 环境准备
# 环境要求:scikit-learn≥1.2.0, matplotlib≥3.5.0
import pandas as pd
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import classification_report
import matplotlib.pyplot as plt
3.2 数据预处理关键步骤
# 假设 df 是 100×15 的 DataFrame(14 个特征 + 1 个目标列)X = df.iloc[:, :-1]
y = df.iloc[:, -1]
# 必须标准化连续型特征!num_cols = ['age', 'income'] # 示例数值列
scaler = StandardScaler()
X[num_cols] = scaler.fit_transform(X[num_cols])
# 小数据建议提高测试集比例
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y)
3.3 模型训练与调优
# 基础模型(对比用)base_model = DecisionTreeClassifier(random_state=42)
base_model.fit(X_train, y_train)
# 网格搜索调参
param_grid = {'criterion': ['gini', 'entropy'],
'max_depth': [3, 5, 7, None],
'min_samples_split': [2, 5, 10]
}
grid_search = GridSearchCV(DecisionTreeClassifier(random_state=42),
param_grid,
cv=5,
scoring='f1_weighted'
)
grid_search.fit(X_train, y_train)
best_model = grid_search.best_estimator_
3.4 评估与可视化
# 性能对比
print("Base Model Report:")
print(classification_report(y_test, base_model.predict(X_test)))
print("Best Model Report:")
print(classification_report(y_test, best_model.predict(X_test)))
# 特征重要性
feat_importances = pd.Series(best_model.feature_importances_, index=X.columns)
feat_importances.nlargest(5).plot(kind='barh')
plt.title('Top 5 Important Features')
plt.show()
# 决策树结构(max_depth= 3 时清晰可解释)plt.figure(figsize=(12,8))
plot_tree(best_model, feature_names=X.columns, class_names=y.unique(), filled=True)
plt.show()
4. 关键参数解析
- criterion 选择:
- Gini 系数:计算稍快,适合大多数场景
- 信息熵:对类别分布更敏感,适合不平衡数据
经验公式:当类别数 >5 时优先用 entropy
- max_depth:
- 从 3 开始尝试,每增加 1 层深度需确保验证集指标提升≥2%
-
可通过
tree_.max_depth查看实际深度 -
min_samples_split:
- 小数据建议设为 5 -10,避免产生无统计意义的节点
- 与业务结合:例如医疗诊断需更高分裂阈值
5. 进阶优化策略
5.1 后剪枝(Cost Complexity Pruning)
path = best_model.cost_complexity_pruning_path(X_train, y_train)
ccp_alphas = path.ccp_alphas
pruned_models = []
for ccp_alpha in ccp_alphas:
model = DecisionTreeClassifier(random_state=42, ccp_alpha=ccp_alpha)
model.fit(X_train, y_train)
pruned_models.append(model)
5.2 类别不平衡处理
当正负样本比例超过 1:3 时:
- 调整 class_weight 参数
- 上采样少数类(慎用 SMOTE,小数据易引入噪声)
- 改用平衡准确率(balanced_accuracy_score)评估
6. 延伸思考
- 当某个特征在训练集表现极好但业务上不应作为决策依据时(如 ” 用户 ID”),如何在模型中强制排除?
- 如果 100 组数据中包含 20% 的缺失值,哪种填充策略对决策树影响最小?
- 如何设计实验验证当前模型是否已经达到小样本条件下的性能上限?
期待大家在评论区分享自己的实战心得!
正文完
发表至: 未分类
近两天内
