Skip to content

监督模型

选择使用哪个模型以及在这些模型中设置哪些参数是特定于特定数据集的。在 PyTorch Tabular 中,一个模型有三个组成部分:

  1. 嵌入层(Embedding Layer) - 这是模型中处理分类和连续特征并将其转换为单一张量的部分。
  2. 主干(Backbone) - 这是模型的实际架构。它接收嵌入层的输出,并在其上进行表示学习。输出再次是一个单一张量,即从表示学习中学习到的特征。
  3. 头部(Head) - 这是模型中接收主干输出并进行最终分类/回归的部分。头部的输出是最终的预测结果。

我们可以通过使用特定于模型的配置类来选择嵌入层、主干和头部及其参数。

通用配置

虽然每个模型都有单独的配置类,但它们在 ModelConfig 类中共享一些核心参数。

  • task: str: 这定义了我们是为 regression(回归)、classification(分类)任务运行模型,还是作为 backbone(主干)模型。backbone 任务用于自监督模型和混合密度模型。

头部配置

  • head: Optional[str]: 模型使用的头部。应为 pytorch_tabular.models.common.heads 中定义的头部之一。默认为 LinearHead
  • head_config: Optional[Dict]: 以字典形式定义头部的配置。如果留空,将初始化为默认的线性头部。

嵌入配置

  • embedding_dims: Optional[List]: 每个分类列的嵌入维度,以元组列表形式表示(基数,嵌入维度)。如果留空,将根据分类列的基数推断,使用规则 min(50, (x + 1) // 2)
  • embedding_dropout: float: 应用于分类嵌入的 dropout。默认为 0.0。
  • batch_norm_continuous_input: bool: 如果为 True,我们将在将连续层与分类嵌入结合之前,通过 BatchNorm 层对其进行归一化。默认为 True。

其他配置

  • learning_rate: float: 模型的学习率。默认为 1e-3。

  • loss: Optional[str]: 要应用的损失函数。默认情况下,回归为 MSELoss,分类为 CrossEntropyLoss。除非你确定自己在做什么,否则请保持为 MSELoss 或 L1Loss 用于回归,CrossEntropyLoss 用于分类。

  • metrics: Optional[List[str]]: 训练期间需要跟踪的指标列表。指标应为 torchmetrics 中实现的功能性指标之一。默认情况下,分类为 accuracy,回归为 mean_squared_error

  • metrics_prob_input: Optional[List[bool]]: 是配置中定义的分类指标的强制参数。这定义了指标函数的输入是概率还是类别。长度应与指标数量相同。默认为 None。

  • metrics_params: Optional[List]: 传递给指标函数的参数。

  • target_range: Optional[List]: 我们应限制输出变量的范围。当前在多目标回归中被忽略。通常用于回归问题。如果留空,将不应用任何限制。

  • virtual_batch_size: Optional[int]: 如果不为 None,所有 BatchNorm 都将转换为 GhostBatchNorm,并使用此虚拟批次大小。默认为 None。

  • seed: int: 用于可重复性的种子。默认为 42。

所有实现的模型和大多数常见参数都有智能默认值,你可以通过以下简单的方式开始使用模型:

model_config = <ModelSpecificConfig>(task="classification")

就是这样,这是最基本的需求。其余的都是智能推断或设置为智能默认值。

高级用法:

学习率、损失和指标

Adam 优化器和 1e-3 的学习率是 PyTorch Tabular 中的默认设置。这是一个经验法则,在大多数情况下都有效,并且是一个良好的起点。如果你想改变学习率(这是一个相当重要的超参数),你应该在这里进行。还有一种自动推导良好学习率的方法,我们将在 TrainerConfig 中讨论。在这种情况下,Pytorch Tabular 将忽略通过此参数设置的学习率。

模型的另一个关键组件是 loss。Pytorch Tabular 可以通过此配置使用标准 PyTorch(torch.nn)中的任何损失函数。默认情况下,回归为 MSELoss,分类为 CrossEntropyLoss,这些对于相应用例效果良好,并且是最常用的损失函数。如果你想使用其他特定的损失函数,如 L1Loss,只需在 loss 参数中提及即可。

loss = "L1Loss"
PyTorch Tabular 还通过 TabularModel 中的 fit 方法接受自定义损失函数(这些函数可以作为标准损失函数的直接替代品)。

Warning

如果你不知道自己在做什么,请将损失函数保留为默认值。 模型返回原始的 logits,应用正确的激活函数是损失函数的责任。

虽然损失函数驱动基于梯度的优化,但我们在训练过程中跟踪我们关心的指标。默认情况下,PyTorch Tabular 在分类任务中跟踪准确率,在回归任务中跟踪均方误差。你可以从 TorchMetrics 中选择任何功能性指标(以字符串列表的形式)。

某些指标需要一些参数才能按预期工作。例如,多类 F1 分数的平均方案。这些参数可以通过 metrics_params 传入,这是一个包含指标参数的字典列表,按声明的顺序排列。在分类指标中,PyTorch Tabular 还需要知道定义的指标是否期望预测类别(如准确率)或预测概率(如 ROCAUC)。这可以通过 metrics_prob_input 指定,这是一个 TrueFalse 的列表,每个自定义指标对应一个。metrics_paramsmetrics_prob_inputmetrics 的长度应该相同。

metrics = ["accuracy", "f1_score"]
metrics_prob_input = [False, False]
metrics_params = [{}, {num_classes: 2}]

PyTorch Tabular 还通过 TabularModelfit 方法中的 custom_metric(可调用对象)和 custom_metric_params(传递给指标的参数字典)参数接受具有 callable(pred:torch.Tensor,target:torch.Tensor) 签名的自定义指标函数。

回归的目标范围

对于分类问题,目标值在独热编码类别标签后始终为 0 或 1。但对于回归问题,理论上它是介于 (-inf, inf) 之间的实数值。更实际地,它通常在已知的界限之间。有时,模型学习这些界限是一种额外的负担,而 target_range 是一种减轻模型负担的方法。这种技术由 Jeremy Howard 在 fast.ai 中推广,并且在实践中非常有效。

如果我们知道回归的输出值应在 minmax 值之间,我们可以将这些值作为元组提供给 target_range。对于多个目标,我们将 target_range 设置为元组列表,列表中的每个条目对应于 target 参数中的相应条目。

对于分类问题,此参数将被忽略。

target_range = [(train[target].min() * 0.8, train[target].max() * 1.2)]

可用模型

现在让我们看看 PyTorch Tabular 中可用的几种不同模型及其配置。完整实现的模型列表:

>>> from pytorch_tabular import available_models
>>> available_models()
['AutoIntConfig', 'CategoryEmbeddingModelConfig', 'DANetConfig', 'FTTransformerConfig', 'GANDALFConfig', 'GatedAdditiveTreeEnsembleConfig', 'MDNConfig', 'NodeConfig', 'TabNetModelConfig', 'TabTransformerConfig']

类别嵌入模型(多层感知机)

这是库中最基本的模型。架构非常简单——一个前馈网络,分类特征通过一个可学习的嵌入层传递。你可以通过选择 CategoryEmbeddingModelConfig 来使用它。该模型是任何表格数据集的良好起点。它也是一个与其他模型进行比较的良好基线。

所有参数都有智能的默认值。让我们看看其中的一些:

  • layers: str: 分类头中层数和单元数的连字符分隔字符串。默认为 "128-64-32"
  • activation: str: 分类头中的激活类型。默认的 PyTorch 激活函数 如 ReLU、TanH、LeakyReLU 等。默认为 ReLU
  • initialization: str: 线性层的初始化方案。选项有:kaiming xavier random。默认为 kaiming
  • use_batch_norm: bool: 标志,用于在每个线性层+DropOut 后包含一个 BatchNorm 层。默认为 False
  • dropout: float: 元素被置零的概率。这适用于所有线性层。默认为 0.0

完整的参数列表请参考 API 文档 pytorch_tabular.models.CategoryEmbeddingModelConfig

门控自适应网络用于深度自动化特征学习 (GANDALF)

Gated Adaptive Network for Deep Automated Learning of Features (GANDALF) 是一种新颖的高性能、可解释且参数和计算效率高的深度学习架构,适用于表格数据。GANDALF 依赖于一种新的表格处理单元,该单元具有门控机制和内置的特征选择功能,称为 Gated Feature Learning Unit (GFLU),作为特征表示学习单元。论文通过在多个已建立的公共基准上的实验证明,GANDALF 的表现优于或与 XGBoost、SAINT、FT-Transformers 等最先进的方法相当。您可以通过选择 GANDALFConfig 来使用它。

受 GRU 启发的表示学习层被称为 Gated Feature Learning Unit (GFLU)(来自论文)

GFLU

通过多阶段 GFLU 学习到的表示随后通过一个简单的线性层投影到输出空间。

所有参数均已设置为论文推荐的值。让我们来看看它们:

  • gflu_stages: int: 特征抽象层的层数。默认为 6

  • gflu_dropout: float: 特征抽象层的 dropout 率。默认为 0.0

  • gflu_feature_init_sparsity: float: 仅对 t-softmax 有效。每个 GFLU 阶段选择的特征百分比。这只是初始化,在学习过程中可能会发生变化。默认为 0.3

  • learnable_sparsity: bool: 仅对 t-softmax 有效。如果为 True,稀疏参数将被学习。如果为 False,稀疏参数将固定为 gflu_feature_init_sparsitytree_feature_init_sparsity 中指定的初始值。默认为 True

Note

GANDALF 可以被视为更轻量且性能更优的 Gated Additive Tree Ensemble (GATE)。在大多数情况下,GANDALF 是比 GATE 更好的选择。

有关参数的完整列表,请参阅 API 文档 pytorch_tabular.models.GANDALFConfig

Gated Additive Tree Ensemble (GATE)

Gated Additive Tree Ensemble 是一种新颖的高性能、参数和计算效率高的深度学习架构,适用于表格数据,称为 Gated Additive Tree Ensemble (GATE)。GATE 使用受 GRU 启发的门控机制作为特征表示学习单元,并内置特征选择机制。作者将其与一组可微分的非线性决策树集成相结合,通过简单的自注意力机制重新加权,以预测我们期望的输出。作者还通过在多个公共数据集(分类和回归)上的实验证明,GATE 是 GBDTs、NODE、FT Transformers 等最先进方法的有力竞争者。您可以通过选择 GatedAdditiveTreeEnsembleConfig 来使用它。

GFLU 随后与一组非线性决策树结合,形成 Gated Additive Tree Ensemble (GATE)

Non-Linear Decision Trees

所有参数均已设置为论文推荐的值。让我们来看看其中的一些:

  • gflu_stages: int: 特征抽象层(GFLU)的层数。默认为 6

  • tree_depth: int: 树的深度。默认为 5

  • num_trees: int: 集成中使用的树的数量。默认为 20

  • chain_trees: bool: 如果为 True,我们将树串联在一起,否则它们将并行处理。类似于 boosting(串联树)或 bagging(并行树)。默认为 False

  • share_head_weights: bool: 如果为 True,我们将共享头部的权重。默认为 True

有关参数的完整列表,请参阅 API 文档 pytorch_tabular.models.GatedAdditiveTreeEnsembleConfig

Neural Oblivious Decision Ensembles (NODE)

Neural Oblivious Decision Ensembles for Deep Learning on Tabular Data 是 ICLR 2020 上提出的模型,根据作者的说法,在许多数据集上击败了经过良好调优的梯度提升模型。它使用 Oblivious Trees 的神经等价物(Catboost 使用的树类型)作为架构的基本构建块。您可以通过选择 NodeConfig 来使用它。

基本块或“层”看起来如下(来自论文)

NODE Architecture

通过堆叠这样的层并添加到输入的残差连接(类似于 DenseNet)来创建更深的架构

NODE Architecture

所有参数均已设置为论文推荐的值。让我们来看看其中的一些:

  • num_layers: int: Dense 架构中 Oblivious Decision Tree 层的数量。默认为 1
  • num_trees: int: 每层中 Oblivious Decision Trees 的数量。默认为 2048
  • depth: int: 单个 Oblivious Decision Trees 的深度。参数随着深度的增加呈指数增长。默认为 6
  • choice_function: str: 生成一个稀疏的概率分布,用作特征权重(即软特征选择)。可选值为:entmax15 sparsemax。默认为 entmax15
  • bin_function: str: 生成一个稀疏的概率分布,用作树叶子权重。可选值为:entmoid15 sparsemoid。默认为 entmoid15
  • additional_tree_output_dim: int: 仅用于通过架构的不同层的额外输出维度。只有前 output_dim 个输出将用于预测。默认为 3
  • input_dropout: float: 应用于密集架构中不同层输入的 dropout。元素被置零的概率。默认为 0.0

如需完整参数列表,请参阅 API 文档 pytorch_tabular.models.NodeConfig

注意

NODE 模型参数众多,因此占用大量内存。较小的批次大小(如 64 或 128)使得模型在较小的 GPU(约 4GB)上易于管理。

TabNet

  • TabNet: 注意力可解释表格学习 是 Google Research 推出的另一种模型,它通过在决策过程中的多个步骤使用稀疏注意力来建模输出。您可以通过选择 TabNetModelConfig 来使用它。

架构如下所示(来自论文)

TabNet 架构

所有参数均已设置为论文推荐的值。让我们看看其中几个:

  • n_d: int: 预测层的维度(通常在 4 到 64 之间)。默认为 8
  • n_a: int: 注意力层的维度(通常在 4 到 64 之间)。默认为 8
  • n_steps: int: 网络中连续步骤的数量(通常在 3 到 10 之间)。默认为 3
  • n_independent: int: 每个 GLU 块中独立 GLU 层的数量。默认为 2
  • n_shared: int: 每个 GLU 块中独立 GLU 层的数量。默认为 2
  • virtual_batch_size: int: Ghost Batch Normalization 的批次大小。在大批次上进行 BatchNorm 有时效果不佳,因此 TabNet 中实现了 Ghost Batch Normalization,它在较小的虚拟批次中进行批量归一化。默认为 128

如需完整参数列表,请参阅 API 文档 pytorch_tabular.models.TabNetModelConfig

通过自注意力神经网络自动学习特征交互(AutoInt)

AutoInt 是一种尝试以自动化方式学习特征间交互的模型,并创建更好的表示,然后在下游任务中使用此表示。您可以通过选择 AutoIntConfig 来使用它。

所有参数均已设置为论文推荐的值。让我们看看其中几个:

  • attn_embed_dim: int: 多头注意力层中的隐藏单元数量。默认为 32

  • num_heads: int: 多头注意力层中的头数。默认为 2

  • num_attn_blocks: int: 堆叠的多头注意力层的层数。默认为 3

如需完整参数列表,请参阅 API 文档 pytorch_tabular.models.AutoIntConfig

DANETs: 表格数据分类与回归的深度抽象网络

DANETs: 表格数据分类与回归的深度抽象网络 是一种新颖且灵活的神经组件,称为抽象层(AbstLay),它学习显式地分组相关输入特征并生成更高级别的特征以进行语义抽象。使用 AbstLays 构建了一个特殊的基本块,并通过堆叠此类块构建了一族用于表格数据分类和回归的深度抽象网络(DANets)。您可以通过选择 DANetConfig 来使用它。

所有参数均已设置为论文推荐的值。让我们看看它们:

  • n_layers: int: DANet 中的块数。每个块包含 2 个 Abstlay 块。默认为 8

  • abstlay_dim_1: int: 块中第一个 ABSTLAY 层中间输出的维度。默认为 32

  • abstlay_dim_2: int: 块中第二个 ABSTLAY 层中间输出的维度。如果为 None,则为 abstlay_dim_1 的两倍。默认为 None

  • k: int: ABSTLAY 层中的特征组数。默认为 5

  • dropout_rate: float: 块中应用的 dropout。默认为 0.1

如需完整参数列表,请参阅 API 文档 pytorch_tabular.models.DANetConfig

实现新架构

PyTorch Tabular 非常易于扩展且具有无限的可定制性。在 PyTorch Tabular 中实现的所有模型都继承了一个抽象类 BaseModel,它实际上是一个 PyTorchLightning 模型。 它处理所有主要功能,如解码配置参数、设置损失和指标。它还计算损失和指标,并将其反馈给执行反向传播的PyTorch Lightning Trainer。

如果我们查看PyTorch Tabular模型的结构,有三个主要组件:

  1. 嵌入层
  2. 主干网络
  3. 头部网络

嵌入层从数据加载器接收输入,这是一个包含categoricalcontinuous张量的字典。嵌入层将这个字典转换为一个单一的张量,并正确处理分类张量。已经实现了两种嵌入层,EmbeddingLayer1d和EmbeddingLayer2d。

主干网络是主要的模型架构。

头部网络是线性层,它接收主干网络的输出并将其转换为我们期望的输出。

为了封装和强制执行这种结构,BaseModel要求我们定义三个property方法:

  1. def embedding_layer(self)
  2. def backbone(self)
  3. def head(self)

还有一个方法def _build_network(self)也需要强制定义。我们可以使用这个方法来定义嵌入层、主干网络、头部网络以及模型中需要的任何其他层或组件。

对于作为头部的标准前馈层,我们还可以使用BaseModel中的一个便捷方法_get_head_from_config,它将使用你在ModelConfig中设置的headhead_config来自动为你初始化正确的头部。

使用它的示例:

self._head = self._get_head_from_config()

对于标准流程,已经定义的forward方法就足够了。

def forward(self, x: Dict):
    x = self.embed_input(x)  # 嵌入输入字典并返回一个张量
    x = self.compute_backbone(
        x
    )  # 接收张量输入并进行表示学习
    return self.compute_head(
        x
    )  # 将主干网络输出转换为期望的输出,必要时应用目标范围,并以所需格式打包输出。

这使我们能够定义任何标准的PyTorch模型并将其用作主干网络,然后使用PyTorch Tabular的其余机制来训练、评估和记录模型。

虽然这是最基本的要求,但你可以重新定义或使用任何PyTorch Lightning的标准方法来调整你的模型和训练以符合你的喜好。这种设置的真正美妙之处在于,你需要进行的定制程度完全取决于你自己。对于标准工作流程,你可以进行最小的更改。而对于非常不寻常的模型,你可以重新定义BaseModel中的任何方法(只要接口保持不变)。

除了模型之外,你还需要定义一个配置。配置是Python数据类,应该继承ModelConfig,并且默认情况下将包含ModelConfig的所有参数。任何额外的参数都应在数据类中定义。

需要注意的关键事项:

  1. 在调用super()之前,所有不同配置(如TrainerConfig、OptimizerConfig等)中的不同参数都可在config中获取,调用之后则在self.hparams中。
  2. forward方法中的输入批次是一个包含continuouscategorical键的字典。
  3. _build_network方法中,将你希望在forward中访问的每个组件保存到self中。

请查看实现新架构教程以获取一个实际示例。