在当今的深度学习领域,
集成学习(Ensemble Learning)
是一种广受欢迎的方法,通过组合多个模型的优势来提升整体性能。
为了简化集成学习模型的构建和应用,
Ensemble-PyTorch
提供了一种便捷且高效的解决方案。
unset
unset
什么是Ensemble-PyTorch?
unset
unset
$ pip install torchensemble
Ensemble-PyTorch
的设计目标是便携且依赖少,这使得它成为一个灵活且易于使用的工具。该库的主要功能包括:
-
简单易用:通过简洁的 API,用户可以轻松构建各种集成学习模型,如 Bagging、Boosting 和 Stack。
-
高度兼容:该库与 PyTorch 无缝集成,允许用户利用 PyTorch 的强大功能和丰富的生态系统。
-
灵活性强:支持用户自定义基础模型,满足不同的实验需求。
-
性能优化:内置多种优化策略,提高模型的训练和推理效率。
unset
unset
Ensemble-PyTorch案例
unset
unset
定义你的基础估计器
Ensemble-PyTorch 使用不同的集成方法来提高性能,一个关键的输入参数是你的深度学习模型,作为基础估计器。与 PyTorch 相同,你的模型类应继承自
torch.nn.Module
,并至少实现两个方法:
-
__init__()
: 实例化模型的子模块并将其分配为成员变量。
-
forward()
: 定义模型的数据前向传播过程。
例如,下面的代码片段定义了一个结构为
Input(784) - 128 - 128 - Output(10)
的多层感知机(MLP):
import
torch.nn as nn
from torch.nn import functional as F
class MLP(nn.Module):
def __init__(self):
super(MLP, self).__init__()
self.linear1 = nn.Linear(784, 128)
self.linear2 = nn.Linear(128, 128)
self.linear3 = nn.Linear(128, 10)
def forward(self, data):
data = data.view(data.size(0), -1) # flatten
output = F.relu(self.linear1(data))
output = F.relu(self.linear2(output))
output = self.linear3(output)
return output
设置日志记录器
Ensemble-PyTorch 使用全局日志记录器来跟踪和打印中间日志信息。以下代码片段展示了如何设置日志记录器:
from torchensemble.utils.logging import set_logger
logger = set_logger('classification_mnist_mlp')
有了这个日志记录器,所有的日志信息将打印到命令行并保存到指定的文本文件
classification_mnist_mlp
中。此外,通过传递
use_tb_logger=True
到
set_logger()
方法中,你可以使用 TensorBoard 来更好地可视化训练和评估过程。
tensorboard --logdir=logs/
选择集成模型
在定义基础估计器后,我们可以使用 Ensemble-PyTorch 提供的集成模型进行包装。不同的模型有非常相似的 API,以
VotingClassifier
为例:
from torchensemble import VotingClassifier
model = VotingClassifier(
estimator=MLP,
n_estimators=10,
cuda=True,
)
参数说明:
-
estimator
: 你的模型类,用于实例化集成中的基础估计器。
-
n_estimators
: 集成中基础估计器的数量。
-
cuda
: 指定是否使用 GPU 进行训练和评估。
设置损失函数
下一步是设置目标函数。由于我们的集成模型是一个分类器,我们将使用交叉熵损失:
criterion = nn.CrossEntropyLoss()
model.set_criterion(criterion)
unset
unset
设置优化器
unset
unset
在声明集成模型后,训练之前的另一步是设置优化器。假设我们将使用学习率为
1e-3
和权重衰减为
5e-4
的 Adam 优化器来训练集成模型,可以通过调用
set_optimizer
方法实现:
model.set_optimizer('Adam', # 参数优化器
lr=1e-3, # 优化器的学习率
weight_decay=5e-4) # 优化器的权重衰减
所有在优化器名称(即
Adam
)之后的参数都应该是关键字参数形式。它们将传递给
torch.optim.Optimizer
以实例化内部参数优化器。
同样支持为集成设置学习率调度器,请参考 API Reference 中的
set_scheduler()
。
训练和评估
给定已设置优化器的集成模型,Ensemble-PyTorch 在训练和评估阶段提供了类似 Scikit-Learn 的 API:
# 训练
model.fit(train_loader=train_loader, # 训练数据
epochs=100) # 训练的轮数
# 评估
accuracy = model.predict(test_loader)
在上述代码片段中,
train_loader
和
test_loader
是包含数据的 PyTorch
DataLoader
对象。此外,
epochs
指定训练轮数。由于
VotingClassifier
用于分类,因此
predict()
将返回
test_loader
上的分类准确率。
注意,
test_loader
也可以传递给
fit()
,在这种情况下,集成将其视为验证数据,并在每个训练轮次后评估集成模型。
保存和重新加载
通过在
fit()
中设置
save_model
为
True
和
save_dir
为一个目录,模型参数将自动保存到路径
save_dir
(默认情况下,将保存在运行脚本的同一文件夹中)。之后,你可以使用以下代码片段加载保存的集成模型。
from torchensemble.utils import io
io.load(new_ensemble, save_dir) # 重新加载
unset
unset
Ensemble-PyTorch集成方法
unset
unset
融合(Fusion)
融合方法的输出是所有基础估计器输出的平均值。形式上,给定样本
,融合方法的输出为
。
在训练阶段,所有融合方法中的基础估计器通过小批量梯度下降联合训练。对于一个数据批次
,融合方法的训练损失为
。然后,可以通过 PyTorch 的自动微分系统和梯度下降联合更新所有基础估计器的参数。下图展示了融合方法的数据流:
投票和 Bagging
投票和 Bagging 是常用的集成方法。基本上,投票和 Bagging 独立地训练
个基础估计器,最终预测取所有基础估计器预测的平均值。
与投票相比,Bagging 进一步在每个数据批次上使用有放回的抽样。注意,在训练神经网络时通常不使用子抽样,因为神经网络通常在更多训练数据下表现更好。
梯度提升
梯度提升按顺序训练所有基础估计器,因为基础估计器
的学习目标与之前拟合的基础估计器
的输出相关。
给定梯度提升中的
个基础估计器,整个集成模型在样本上的输出为
,其中
是预定义的标量,取值范围为
,在梯度提升中称为缩减率或学习率。
第 m 个基础估计器的训练过程如下:
-
确定每个样本的学习目标
:给定真实值
和之前基础估计器的累积输出:
,学习目标定义为
。因此,学习目标就是训练损失
关于之前基础估计器累积输出
的负梯度;
-
-
更新累积输出
:
,然后进入 (m+1)-th 基础估计器的训练过程。
对于均方误差的回归,
。对于交叉熵损失的分类,
,其中
是类别标签
的独热编码向量。
快照集成
与上述所有方法不同,快照集成通过强制单个基础估计器收敛到不同的局部极小值来生成集成。在每个极小值处,保存此估计器的参数(即快照),作为集成中的基础估计器。快照集成的输出也是所有快照预测的平均值。
为了获得性能良好的快照,快照集成使用
循环退火学习率调度
来训练基础估计器。
对抗训练
在每个基础估计器
的训练阶段,首先使用快速梯度符号法(FGSM)为当前数据批次中的每个样本
生成一个对抗样本
。然后,优化基础估计器的参数以最小化训练损失
,其中
是基础估计器
在对抗样本
上的输出。显然,这种训练损失鼓励每个基础估计器在原始样本和对抗样本上都表现良好。
快速几何集成
受深度神经网络损失表面的几何见解启发,快速几何集成(FGE)是一种高效的集成方法,它使用定制的学习率调度器生成基础估计器,类似于快照集成。
与
36000+
来自竞赛爱好者一起交流~