趋近智
虽然线性模型为许多监督学习任务提供了良好基础,但决策树提供了一种不同且通常更直观的预测方式。它们通过基于特征值创建决策的树状模型来运作,从而在叶节点得到预测结果。这些模型因其可解释性以及能够捕捉非线性关系的能力而受到欢迎。
决策树将特征空间划分为一系列矩形区域,然后在每个区域拟合一个简单模型(如常数)。要预测一个新的数据点,你从树的根部开始,根据数据点的特征值沿着分支向下,直到到达叶节点,其中包含预测结果。对于分类问题,这通常是该区域的多数类别;对于回归问题,通常是目标值的平均值。
决策树的主要优点之一是其透明度。树学习到的规则可以轻松可视化和理解。然而,单个决策树容易过拟合,特别是当它们很深时。这意味着它们可能过度学习训练数据,包括其中的噪声,并在新数据上表现不佳。
这是一个决策树结构的简化图示:
一个简单的决策树,说明特征如何被使用来做连续决策,从而得到类别预测。
Julia 通过 MLJ.jl 框架提供了使用决策树算法的途径,这些算法主要来自 DecisionTree.jl 包。
首先,你需要从相应的包中加载模型类型。MLJ 使用 @load 宏来完成此操作,这也有助于确保包含模型的包在你的环境中可用。
using MLJ
import RDatasets # 用于示例数据
# 加载决策树分类器模型
DecisionTreeClassifier = @load DecisionTreeClassifier pkg=DecisionTree
# 准备一些数据(使用鸢尾花数据集的例子)
iris = RDatasets.dataset("datasets", "iris")
X = select(iris, Not(:Species)) # 特征
y = iris.Species # 目标变量
# 初始化模型
tree_model = DecisionTreeClassifier()
模型初始化后,你可以使用机器学习器上的 fit! 方法对其进行训练,这会将模型与数据绑定:
# 创建一个机器学习器(模型 + 数据)
mach_tree = machine(tree_model, X, y)
# 拟合机器学习器
fit!(mach_tree)
拟合之后,你可以对新数据(或训练数据本身)进行预测:
predictions = predict(mach_tree, X)
# 对于分类器,predict_mode 会给出最可能的类别
predicted_classes = predict_mode(mach_tree, X)
决策树常用的超参数包括:
max_depth:树的最大深度。限制深度有助于避免过拟合。min_samples_split:拆分内部节点所需的最小样本数。min_samples_leaf:叶节点所需的最小样本数。pruning_purity_threshold (或 DecisionTree.jl 中的 post_prune 和 merge_purity_threshold):控制后剪枝的参数,以简化树并提高泛化能力。例如,DecisionTreeClassifier(post_prune=true, merge_purity_threshold=0.1) 将启用剪枝功能。调整这些超参数通常通过超参数调优完成,你将在“MLJ.jl 中的交叉验证和超参数调优”一节中了解更多。
虽然单个决策树具有可解释性,但它们容易过拟合是一个明显的缺点。集成方法通过结合多个决策树(或其它类型模型)的预测结果来解决这个问题,从而产生更准确的总体预测。
两种著名的基于决策树的集成技术是随机森林和梯度提升机。
核心思想是许多多样化、单独较弱的学习器可以组合形成一个强大的学习器。这种方法通常能显著提升预测性能,并与单一复杂模型相比,对新数据具有更好的泛化能力。
随机森林在训练时构建多棵决策树。对于分类问题,输出是大多数树选择的类别;对于回归问题,则是单个树预测结果的平均值。
随机森林中树的多样性主要来自两个方面:
这些机制有助于减少模型的方差,而不会大幅增加偏差。
在 MLJ.jl 中,你可以使用来自 DecisionTree.jl 的 RandomForestClassifier(或 RandomForestRegressor)。
# 加载随机森林分类器模型
RandomForestClassifier = @load RandomForestClassifier pkg=DecisionTree
# 初始化模型
# n_trees: 森林中的树的数量
# mtry_ratio: 每次拆分时考虑的特征比例 (mtry / n_features)
# 或者,mtry: 考虑的特征数量。如果 mtry < 0,则使用 mtry_ratio。
# 对于分类问题,mtry 的常见起始值是 sqrt(特征数量)。
# sampling_fraction: 用于训练每棵树的样本比例
rf_model = RandomForestClassifier(
n_trees=100,
sampling_fraction=0.7,
mtry_ratio=0.5
)
# 创建并拟合机器学习器
mach_rf = machine(rf_model, X, y)
fit!(mach_rf)
# 进行预测
rf_predictions = predict_mode(mach_rf, X)
随机森林通常比单个决策树更不容易过拟合,并且通常需要较少的超参数调优以获得良好的性能。
梯度提升机(GBMs)也构建决策树集成,但它们是按顺序进行的。每棵新树都尝试纠正之前训练过的树所犯的错误。梯度提升中的“梯度”是指使用梯度下降,通过迭代添加预测当前集成模型残差(回归)或伪残差(分类)的树来最小化损失函数。
GBMs 性能强大,经常在表格数据上提供当前最佳结果。流行的实现包括 XGBoost、LightGBM 和 CatBoost。Julia 有自己的高性能梯度提升库 EvoTrees.jl,它与 MLJ.jl 很好地结合。此外,也有 XGBoost 的封装器可供使用。
我们来看一个使用 EvoTrees.jl 中的 EvoTreesClassifier 的例子。
# 加载 EvoTrees 分类器模型
EvoTreesClassifier = @load EvoTreesClassifier pkg=EvoTrees
# 初始化模型
# nrounds: 提升轮数(树的数量)
# eta: 学习率(缩小每棵树的贡献)
# max_depth: 单个树的最大深度
evo_model = EvoTreesClassifier(
nrounds=100,
eta=0.1,
max_depth=6
)
# 创建并拟合机器学习器
mach_evo = machine(evo_model, X, y)
fit!(mach_evo)
# 进行预测
evo_predictions = predict_mode(mach_evo, X)
GBM 的重要超参数通常包括:
nrounds (或 n_estimators):要构建的树的数量。learning_rate (或 eta):控制每棵树的贡献。较小的学习率通常需要更多的树,但可以带来更好的泛化能力。max_depth:每棵单独树的最大深度,控制其复杂度。subsample:用于增长每棵树的训练数据比例(随机梯度提升)。colsample_bytree:每棵树考虑的特征比例。梯度提升模型非常有效,但与随机森林相比,可能需要更仔细地调整超参数以避免过拟合,特别是当树的数量很多或学习率很高时。
随机森林和梯度提升机与单个决策树一样,都符合 MLJ.jl 的工作流程,用于模型评估、交叉验证和超参数调优,这些内容将在后续章节中介绍。通过了解它们的工作原理以及如何在 Julia 中实现它们,你可以扩展你的工具集,以应对各种监督学习问题。
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造