tabm
TabM 是一款专为表格数据深度学习设计的开源模型,旨在通过高效的集成学习策略提升预测性能。在传统机器学习任务中,表格数据处理往往依赖梯度提升树(GBDT),而深度学习方法虽潜力巨大却常受限于训练成本高或泛化能力不足。TabM 巧妙地在单个神经网络架构内模拟了多个多层感知机(MLP)的集成效果,既保留了集成学习的强大表现力,又大幅降低了资源消耗。
其核心技术亮点在于“并行训练”与“权重共享”。不同于传统集成方法需独立训练多个模型,TabM 允许在训练过程中实时监控整体集成效果并适时停止,同时所有子网络共享大部分参数,这不仅显著提升了运行速度和内存效率,还起到了一种有效的正则化作用,从而在真实工业数据集上取得了优于现有深度学习方法的成果。该模型已在多个 Kaggle 竞赛中助力团队夺冠,并能从容应对包含数千万甚至上亿条记录的大规模数据场景。
TabM 非常适合从事数据挖掘、预测建模的算法工程师、数据科学家以及学术研究人员使用。如果你正在寻找一种既能媲美顶级集成模型性能,又具备深度学习灵活性与扩展性的解决方案,TabM 值得尝试。
使用场景
某金融风控团队正在处理包含数百万用户交易记录的高维表格数据,急需构建一个能精准预测违约概率且适应数据分布漂移的深度学习模型。
没有 tabm 时
- 集成成本高昂:为了提升准确率,工程师不得不训练多个独立的 MLP 模型进行集成,导致显存占用翻倍,训练时间成倍增加。
- 调优目标错位:只能单独监控每个子模型的损失,无法直接观测整体集成效果,往往在单模型最优时停止训练,却错过了集成性能的最佳点。
- 难以应对漂移:面对工业界常见的随时间变化的数据分布漂移(Distribution Drift),传统表格深度学习模型泛化能力不足,线上预测稳定性差。
- 推理延迟高:多个模型串行推理导致单次预测耗时过长,难以满足实时风控系统对低延迟的严苛要求。
使用 tabm 后
- 参数高效集成:tabm 通过权重共享机制,将多个 MLP 集成压缩进一个类 MLP 结构中,在保持集成优势的同时,大幅降低了显存需求和训练时长。
- 并行协同优化:支持并行训练多个预测头,团队可直接监控整体集成指标并在最佳时刻停止训练,显著提升了最终模型的预测精度。
- 鲁棒性增强:在真实的工业数据集基准测试中,tabm 展现出更强的抗漂移能力,有效解决了因数据分布变化导致的模型性能下降问题。
- 推理速度提升:得益于紧凑的架构设计,tabm 的推理吞吐量远超传统表格深度学习方法,轻松支撑大规模数据的实时在线预测。
tabm 通过参数高效的并行集成架构,让表格深度学习在保持高精度的同时,具备了落地大规模真实业务所需的效率与鲁棒性。
运行环境要求
- 未说明
- 未说明 (基于 PyTorch,支持 CPU 和 GPU
- 论文实验提及使用混合精度训练和 torch.compile 加速,暗示兼容 NVIDIA GPU)
未说明 (文中提及可处理 1300 万至 1 亿 + 样本的大型数据集,实际内存需求取决于数据规模)

快速开始
TabM:通过参数高效的集成推进表格深度学习》(ICLR 2025)
:scroll: arXiv :books: 其他表格DL项目
这是论文《TabM:通过参数高效的集成推进表格深度学习》的官方仓库。它由两部分组成:
TabM在Kaggle上的应用(截至2025年6月)
TabM在TabReD(一项具有挑战性的基准测试)上的表现
TabReD是一个基于真实世界工业数据集的基准测试,这些数据集存在与时间相关的分布漂移和数百个特征,因此比传统基准更具挑战性。下图显示,与先前的表格深度学习方法相比,TabM在TabReD(加上另一个真实世界数据集)上取得了更高的性能。
每个点代表一个数据集上的性能得分。对于给定的模型,菱形表示各数据集上的平均值。
训练与推理效率
TabM是一种简单且效率合理的模型,因此非常适合实际应用,包括处理大规模数据集。论文中使用的最大数据集包含1300万个样本,我们还了解到曾成功地在超过1亿个样本上进行过训练,尽管在这种情况下训练所需的时间会更长。
下图显示,TabM的速度相对MLP和GBDT较慢,但比之前的表格深度学习方法更快。请注意:(1) 推理吞吐量是在单线程CPU上测量的,且未进行任何优化,特别是未采用本文后续介绍的TabM专用加速技术;(2) 左侧图表采用了对数尺度。
每个点代表在一个数据集上的测量结果。对于给定的模型,菱形表示各数据集上的平均值。在左图中,$\mathrm{TabM_{mini}^{\dagger*}}$ 表示使用混合精度和torch.compile训练的$\mathrm{TabM_{mini}^{\dagger}}$。
TL;DR
TabM(即Tabular DL模型,能够进行Multiple预测)是一种简单而强大的表格深度学习架构,可高效模拟MLP集成的效果。与常规MLP集成相比,TabM的两个主要区别在于:
- 并行训练MLP。这使得可以在训练过程中监控集成的整体性能,并在对整个集成最优时停止训练,而不是分别针对每个MLP进行训练。
- 权重共享。实际上,整个TabM可以整合为一个类似MLP的单一模型。这不仅显著提升了运行时间和内存效率,还起到了有效的正则化作用,从而提升任务性能。
复现实验与浏览结果
[!IMPORTANT] 若要在实践中及未来工作中使用TabM,请使用下方介绍的
tabm软件包。
与论文相关的内容(代码、指标、超参数等)位于paper/目录下,并在paper/README.md中进行了详细说明。
Python软件包
tabm是一个基于PyTorch的Python软件包,提供了TabM模型,以及用于构建自定义TabM-like架构(即高效MLP-like模型集成)的层和工具。
安装
pip install tabm
基本用法
本节展示了在典型应用场景下如何创建模型,并对训练和推理给出了高层次的说明。
创建TabM
以下示例展示了不带特征嵌入的基本版TabM。为了获得更好的性能,通常应按照下一节的说明传递num_embeddings参数。
[!NOTE] 下文使用的
TabM.make(...)会根据提供的参数添加默认超参数。
import torch
from tabm import TabM
# >>> 所有后续章节的通用设置。
d_out = 1 # 例如,一个回归任务。
batch_size = 256
# 数据集包含24个数值型(连续)特征。
n_num_features = 24
# 数据集包含2个分类特征。
# 第一个分类特征有3个唯一类别。
# 第二个分类特征有7个唯一类别。
cat_cardinalities = [3, 7]
# <<<
model = TabM.make(
n_num_features=n_num_features,
cat_cardinalities=cat_cardinalities, # 将使用独热编码。
d_out=d_out,
)
x_num = torch.randn(batch_size, n_num_features)
x_cat = torch.column_stack([
# 第i个类别特征的取值范围为[0, cat_cardinalities[i])。
torch.randint(0, c, (batch_size,)) for c in cat_cardinalities
])
y_pred = model(x_num, x_cat)
# TabM表示由k个模型组成的集成,因此每个样本会有k个预测。
assert y_pred.shape == (batch_size, model.k, d_out)
使用特征嵌入创建TabM
在典型的表格数据任务中,通常通过将特征嵌入模块作为num_embeddings传入来获得最佳性能(在论文中,带有嵌入的TabM被记作$\mathrm{TabM^\dagger}$)。TabM支持来自rtdl_num_embeddings包中的多种特征嵌入模块。下面的例子展示了最简单的嵌入模块LinearReLUEmbeddings。
[!TIP] 通常,更高级的嵌入方法,如
PiecewiseLinearEmbeddings和PeriodicEmbeddings,能够带来更好的性能。它们的使用将在端到端示例中介绍(见#examples)。
from rtdl_num_embeddings import LinearReLUEmbeddings
model = TabM.make(
n_num_features=n_num_features,
num_embeddings=LinearReLUEmbeddings(n_num_features),
d_out=d_out
)
x_num = torch.randn(batch_size, n_num_features)
y_pred = model(x_num)
assert y_pred.shape == (batch_size, model.k, d_out)
在自定义输入和输入模块中使用TabM
[!TIP]
tabm.TabM的实现是定义基于TabM的模型中输入和输入模块的一个良好示例。
假设您希望改变TabM接收的输入内容或处理方式,但仍想以TabM作为骨干网络。那么典型的用法如下:
from tabm import EnsembleView, make_tabm_backbone, LinearEnsemble
class Model(nn.Module):
def __init__(self, ...):
# >>> 创建任何自定义模块。
...
# <<<
# 创建集成输入模块。
self.ensemble_view = EnsembleView(...)
# 创建骨干网络。
self.backbone = make_tabm_backbone(...)
# 创建预测头。
self.output = LinearEnsemble(...)
def forward(self, arg1, arg2, ...):
# 根据需要将输入转换为一个张量。
# 这一步骤可以包括特征嵌入和其他各种特征变换。
# `handle_input`是一个假想的用户定义函数。
x = handle_input(arg1, arg2, ...) # -> (B, D) 或 (B, k, D)
# 与传统模型唯一的区别在于调用了self.ensemble_view。
x = self.ensemble_view(x) # -> (B, k, D)
x = self.backbone(x)
x = self.output(x)
return x # -> (B, k, d_out)
[!NOTE] 关于
x = handle_input(...)这行中x的形状:
- TabM可以用作传统的类似MLP的骨干网络,此时
x在训练和推理阶段都具有标准形状(B, D)。由于其简单性和更高的效率,这种做法是默认推荐的。- 另一种高级训练策略是,在训练时
x的形状为(B, k, D),而在推理时为(B, D)。端到端示例(见#examples)涵盖了这两种方法。
训练
至关重要的是要独立训练TabM的k个预测结果,而不要对它们进行平均。 换句话说,必须优化平均损失,而不是平均预测结果的损失。端到端示例(见#examples)提供了关于如何训练TabM的完整参考。
推理
在推理阶段,为了得到某个样本的预测结果,需要对k个预测结果进行平均。具体的平均策略取决于任务和损失函数。例如,在分类任务中,通常应该对概率进行平均,而不是对logit进行平均。端到端示例(见#examples)展示了如何使用TabM进行预测。
示例
example.ipynb提供了一个训练TabM的端到端示例:
高级用法
[!TIP] 在构建自定义模型之前,请先尝试并调整TabM。尽管TabM使用的是普通的MLP作为基础模型,但它的简单性可能会让人误以为它不够强大,实际上它是一个非常强的基线。
本部分的内容超出了TabM论文的范围,提供了用于构建自定义TabM类架构的组件,包括:
- MLP、线性层和归一化层的高效集成;
- 其他对高效集成有用的层,如
EnsembleView和ElementwiseAffine; - 将单个模型就地转换为高效集成的函数;
- 以及其他工具。
部分内容将在专门章节中讨论,其余则在下面的示例中展示。
[!IMPORTANT] 理解TabM的实现细节对于构建正确且有效的TabM类模型至关重要。其中一些内容将在本节稍后讨论。其他重要参考资料包括:
- 本包的源代码,特别是
TabM模型和make_tabm_backbone函数;- TabM论文,尤其是第3.3节中的$\mathrm{TabM_{mini}}$段落(arXiv v3版本)。
直觉
回想一下,在传统的类似MLP的模型中,一个典型的模块代表一层作用于形状为(B, D)的张量上,其中B是批次大小,D是潜在表示的维度。相比之下,本包中的典型模块:
- 代表
k个层的集合,这些层并行地作用于k个输入上; - 操作的对象是形状为
(B, k, D)的张量,该张量表示k个输入(每个层对应一个输入)。
示例:
LinearEnsemble是k个独立线性层的集合;LinearBatchEnsemble是k个共享大部分权重的线性层的集合。需要注意的是,权重共享并不会改变模块的应用方式:它仍然代表k个层并行作用于k个输入上。
EnsembleView
EnsembleView是一个特殊的轻量级模块,只做一件简单的事情:
- 将形状为
(B, D)的张量转换为形状为(B, k, D)的张量,其中存储了原始张量的k个完全相同的视图。这是一个廉价且无需复制的操作。 - 形状为
(B, k, D)的张量会原样传递,不做任何更改。
MLP 集成模型
该包提供了以下高效的 MLP 集成模型:
MLPBackboneBatchEnsemble(由 $\mathrm{TabM}$ 使用)MLPBackboneMiniEnsemble(由 $\mathrm{TabM_{mini}}$ 使用)MLPBackboneEnsemble(由 $\mathrm{TabM_{packed}}$ 使用)
[!NOTE] 直接创建上述集成模型与使用
tabm.make_tabm_backbone函数之间的区别在于,make_tabm_backbone中的某些细节是为 TabM 优化的。这些细节在 TabM 之外也可能有用,但目前尚未深入探讨。
与 TabM 不同,它们仅接受形状为 (batch_size, k, d) 的三维输入。因此,用户需要负责将输入转换为一个张量(例如使用嵌入、独热编码等),其中存储的是同一对象的 k 个视图,或者 k 个完整的批次。一个基本的使用示例:
import tabm
import torch
import torch.nn as nn
d_in = 24
d_out = 1
k = 32
model = nn.Sequential(
tabm.EnsembleView(k=k),
tabm.MLPBackboneBatchEnsemble(
d_in=d_in,
n_blocks=3,
d_block=512,
dropout=0.1,
k=k,
tabm_init=True,
scaling_init='normal',
start_scaling_init_chunks=None,
),
tabm.LinearEnsemble(512, d_out, k=k)
)
x = torch.randn(batch_size, d_in)
y_pred = model(x)
assert y_pred.shape == (batch_size, k, d_out)
重要实现细节
本节介绍构建自定义 TabM 类模型时需要注意的实现细节。
层的顺序。 最重要的指导原则是:在用线性层混合表格特征之前,应先生成 $k$ 种不同的对象表示。这直接源自论文(arXiv V3)第 3.3 节中关于 $\mathrm{TabM_{mini}}$ 的说明。
d_in = 24
d = 512
k = 16
# 好的:前两个模块共同在第一个线性层之前生成 k 种不同的对象表示。
scaling_init = "normal" # 或 "random-signs"
good_model = nn.Sequential(
tabm.EnsembleView(k=k),
tabm.ElementwiseAffine((k, d_in), bias=False, scaling_init=scaling_init),
nn.Linear(d_in, d),
...
)
# 好的:LinearBatchEnsemble 内部首先进行非共享的逐元素缩放,从而在进行线性变换之前使 k 种对象表示多样化。
scaling_init = "normal" # 或 "random-signs"
# 或 ("normal", "ones")
# 或 ("random-signs", "ones")
good_model = nn.Sequential(
tabm.EnsembleView(k=k),
tabm.LinearBatchEnsemble(d_in, d, k=k, scaling_init=scaling_init),
...
)
# 不好的:表格特征在线性层之前就被混合了。
bad_model = nn.Sequential(
nn.Linear(d_in, d),
tabm.EnsembleView(k=k),
nn.ReLU(),
...
)
# 不好的:虽然在第一次线性变换之前生成了 k 种表示,但这些表示并不不同。从数学上讲,下面的代码与上一个例子等价。
bad_model = nn.Sequential(
tabm.EnsembleView(k=k),
nn.Linear(d_in, d),
nn.ReLU(),
...
)
权重共享。 在选择 torch.nn.Linear(在集成成员之间完全共享线性层)、tabm.LinearBatchEnsemble(共享大部分权重)和 tabm.LinearEnsemble(不共享权重)时,请注意基于权重共享的参数高效集成策略(如 BatchEnsemble 和 MiniEnsemble)不仅能显著提高 TabM 的效率,还能提升其任务性能。因此,权重共享似乎是一种有效的正则化方法。然而,这种正则化的“最佳程度”以及它如何依赖于具体任务,仍有待进一步研究。
示例:无权重共享的简单集成模型
以下代码是对 tabm.MLPBackboneEnsemble 的重新实现:
k = 32
d_in = 24
d = 512
d_out = 1
dropout = 0.1
model = nn.Sequential(
tabm.EnsembleView(k=k),
# >>> MLPBackboneEnsemble(n_blocks=2)
tabm.LinearEnsemble(d_in, d, k=k),
nn.ReLU(),
nn.Dropout(dropout),
tabm.LinearEnsemble(d, d, k=k),
nn.ReLU(),
nn.Dropout(dropout),
# <<<
tabm.LinearEnsemble(d, d_out, k=k),
)
示例:MiniEnsemble
MiniEnsemble 是一种简单的参数高效集成策略:
- 通过将对象分别经过 $k$ 个非共享且随机初始化的仿射变换,生成 $k$ 种不同的表示。
- 将这 $k$ 种表示并行地送入一个共享的主干网络。可以使用任何主干网络。
- 使用非共享的输出头进行预测。
以下代码是对 tabm.MLPBackboneMiniEnsemble 的重新实现。实际上,backbone 可以是任何类似 MLP 的模型。对 backbone 的唯一要求是能够支持任意数量的批量维度,因为 EnsembleView 会增加一个新的维度。另一种方法是在主干网络前后对表示进行重塑。
d_in = 24
d = 512
d_out = 1
k = 32
# 可以使用任何类似 MLP 的主干网络。
backbone = tabm.MLPBackbone(
d_in=d_in, n_blocks=2, d_block=d, dropout=0.1
)
model = nn.Sequential(
tabm.EnsembleView(k=k),
# >>> MLPBackboneMiniEnsemble
tabm.ElementwiseAffine((k, d_in), bias=False, scaling_init='normal'),
backbone,
# <<<
tabm.LinearEnsemble(d, d_out, k=k),
)
示例:BatchEnsemble
以下代码是对 tabm.MLPBackboneBatchEnsemble 在 n_blocks=2 情况下的重新实现:
k = 32
d_in = 24
d = 512
dropout = 0.1
tabm_init = True # TabM 风格的初始化
scaling_init = 'normal' # 或 'random-signs'
model = nn.Sequential(
tabm.EnsembleView(k=k),
# >>> MLPBackboneBatchEnsemble(n_blocks=2)
tabm.LinearBatchEnsemble(
d_in, d, k=k,
scaling_init=(scaling_init, 'ones') if tabm_init else scaling_init,
),
nn.ReLU(),
nn.Dropout(dropout),
tabm.LinearBatchEnsemble(
d, d, k=k,
scaling_init='ones' if tabm_init else scaling_init
),
nn.ReLU(),
nn.Dropout(dropout),
# <<<
tabm.LinearEnsemble(d, d_out, k=k),
)
示例:自定义架构
以下是一个随机且很可能糟糕的架构,展示了该包中可用的各种层:
d_in = 24
d = 512
d_out = 1
k = 16
dropout = 0.1
model = nn.Sequential(
# (B, d_in) 或 (B, k, d_in)
tabm.EnsembleView(k=k), # -> (B, k, d_in)
// 大部分权重共享
tabm.LinearBatchEnsemble( # -> (B, k, d)
d_in, d, k=k, scaling_init=('random-signs', 'ones')
),
nn.ReLU(), # -> (B, k, d)
nn.Dropout(dropout), # -> (B, k, d)
// 不共享权重
tabm.BatchNorm1dEnsemble(d, k=k), # -> (B, k, d)
// 不共享权重
tabm.LinearEnsemble( # -> (B, k, d)
d, d, k=k
),
nn.ReLU(), # -> (B, k, d)
nn.Dropout(dropout), # -> (B, k, d)
// 权重完全共享
nn.Linear( # -> (B, k, d)
d, d,
),
nn.ReLU(), # -> (B, k, d)
nn.Dropout(dropout), # -> (B, k, d)
// 不共享权重
tabm.ElementwiseAffine( # -> (B, k, d)
(k, d), bias=True, scaling_init='normal'
),
// 权重完全共享
tabm.MLPBackbone( # -> (B, k, d)
d_in=d, n_blocks=2, d_block=d, dropout=0.1
),
// 几乎所有权重共享
tabm.MLPBackboneMiniEnsemble( # -> (B, k, d)
d_in=d, n_blocks=2, d_block=d, dropout=0.1,
k=k, affine_bias=False, affine_scaling_init='normal',
),
// 不共享权重
tabm.LinearEnsemble(d, d_out, k=k), # -> (B, k, d_out)
)
x = torch.randn(batch_size, d_in)
y_pred = model(x)
assert y_pred.shape == (batch_size, k, d_out)
将现有模型转换为高效集成模型
[!WARNING] 下文讨论的方法需要充分理解原始模型和高效集成的所有实现细节,因为它无法保证所得到模型的正确性和性能。
假设您有一个类似 MLP 的模型,并希望在不修改模型源代码的情况下快速评估高效集成对您的模型的潜力。那么,您可以创建一个单模型实例,并通过将其层替换为对应的集成层来将其转换为高效集成模型。为此,该包提供了以下函数:
tabm.batchensemble_linear_layers_tabm.ensemble_linear_layers_tabm.ensemble_batchnorm1d_layers_tabm.ensemble_layernorm_layers_
例如,以下代码创建了一个由 $k$ 个独立 MLP 组成的完整集成模型:
d_in = 24
d = 512
d_out = 1
// 创建一个标准的 MLP 主干。
backbone = tabm.MLPBackbone(
d_in=d_in, n_blocks=3, d_block=d, dropout=0.1
)
// 将该主干转换为高效集成。
k = 32
tabm.ensemble_linear_layers_(backbone, k=k)
// 组装最终模型。
model = nn.Sequential(
tabm.EnsembleView(k=k),
backbone,
tabm.LinearEnsemble(d, d_out, k=k),
)
assert model(torch.randn(batch_size, d_in)).shape == (batch_size, k, d_out)
超参数
默认模型
TabM.make 允许用户使用默认超参数创建 TabM,并根据需要进行覆盖:
[!NOTE] 默认超参数并非“常量”,即它们会根据提供的参数而变化。
// 使用默认超参数的 TabM。
model = TabM.make(n_num_features=16, d_out=1)
// 自定义 n_blocks,其余超参数保持默认值的 TabM。
model = TabM.make(n_num_features=16, d_out=1, n_blocks=2)
默认优化器
目前,对于默认的 TabM,其默认优化器是 torch.optim.AdamW(..., lr=0.002, weight_decay=0.0003)。
arch_type
TL;DR:默认情况下使用 TabM。
'tabm'是默认值,在大多数情况下应能提供最佳性能。'tabm-mini'可能在训练和/或推理速度上更快,同时性能下降不明显,不过此选项可能需要更精确地选择适合给定k值的d_block和n_blocks。在某些情况下,如果更高的正则化程度对特定任务有益,'tabm-mini'甚至可能带来略微更好的性能。'tabm-packed'仅出于完整性而实现。在大多数情况下,它会导致模型更慢、更重且性能较差。
k
[!TIP] 除第一点外,以下关于
k的内容均受论文(arXiv v3)图 7 的启发。
- 如果您打算调整
k,建议分别运行多个独立的超参数调优实验,每次使用不同的但固定的k值。原因是改变k可能会影响其他超参数的最佳取值,若与其他超参数同时调整,则可能使超参数调优过程更加复杂。 - 在深度和宽度一定的情况下,适当增加
k可以提升性能;但超过某个阈值后,性能可能不再提升,甚至有所下降。这种现象在arch_type='tabm-mini'时更为明显(未在图中显示)。 - 为了探索性实验,可以尝试使用较小的
k值(如 24 或 16),通常仍能获得具有竞争力的结果(尽管更改k后可能需要重新调整其他超参数)。 - 一般而言,当增大
k时,也应考虑相应增加d_block或n_block(或两者)。其背后的直觉是,由于权重共享机制的存在,较大的集成规模可能需要更大的基础架构,才能有效容纳k个子模型。 - 如果您的数据集规模与论文中使用的数据集相近,除非您有充足的预算进行超参数调优,否则通常应避免使用
n_blocks=1。
num_embeddings
- 从历史来看,分段线性嵌入通常是用户的更常见选择。然而,在某些任务上,周期性嵌入可能是更好的选择。
rtdl_num_embeddings包的文档提供了关于嵌入超参数调优的建议。
初始化
本节概述了在使用 TabM.make 之外的 API 时,需要指定的初始化相关选项。
[!NOTE] 初始化相关设置对任务性能的影响程度取决于具体任务。通常,这些设置旨在充分发挥 TabM 的潜力,而非避免某些失败模式。
TabM 风格的初始化。tabm_init 是一个标志,用于触发基于 BatchEnsemble 模型的 TabM 风格初始化。简而言之,这是一种保守的初始化策略,使得 $k$ 个子模型仅在第一个集成层中有所不同,而在其他所有层中则完全相同(初始化时)。在基准测试中,tabm_init=True 表现出更好的默认策略。如果训练过程中 $k$ 个子模型坍缩为同一个模型,请尝试将 tabm_init=False。
缩放参数的初始化。start_scaling_init、scaling_init 和 affine_scaling_init 这些参数在略微不同的上下文中指代同一内容。TabM 使用一种非正式的经验法则,大致可以总结为:如果 TabM 主干之前存在“非平凡”的模块(例如 num_embeddings),则使用 "normal";否则使用 "random-signs"。这仍然是 TabM 中尚未充分探索的一个方面。
初始化分块。类似 start_scaling_init_chunks 或 scaling_init_chunks 的参数会触发缩放参数的启发式分块初始化,其中各分块的大小之和必须精确等于主干输入大小(即 d_in)。默认情况下,在 TabM 中,“分块”被简单定义为特征表示的大小(参见 tabm.TabM.__init__ 中的 d_features 变量),这意味着在初始化过程中,每个特征恰好会采样一个随机标量。在其他场景下,如何定义分块可能并不明确。在这种情况下,一种可行的方法是先从 None 开始,必要时再通过试错找到更优的方案。
超参数调优
[!TIP] 上文提供的通用注意事项同样适用于自动超参数调优。
在论文中,为了调优 TabM 的超参数,使用了 Optuna 的 TPE 采样器(Optuna 文档),在较小的数据集上进行了 100 次迭代,在较大的数据集上进行了 50 次迭代。如果对达到最高性能并非至关重要,则进行 30–50 次迭代即可得到一个较为合理的配置。
下表提供了论文中使用的超参数分布。 请根据您的实际设置并结合前文内容调整这些分布,尤其是在迭代次数较少的情况下。
| 超参数 | TabM | 带有 PiecewiseLinearEmbeddings 的 TabM |
|---|---|---|
k |
Const[32](不调优) |
与 TabM 相同 |
n_blocks |
UniformInt[1, 5] |
UniformInt[1, 4] |
d_block |
UniformInt[64, 1024, step=16] |
与 TabM 相同 |
lr |
LogUniform[1e-4, 5e-3] |
与 TabM 相同 |
weight_decay |
{0, LogUniform[1e-4, 1e-1]} |
与 TabM 相同 |
n_bins |
无 | UniformInt[2, 128] |
d_embedding |
无 | UniformInt[8, 32, step=4] |
实用提示
推理效率
如论文第 5.2 节所示,可以在训练完成后大幅剪枝 TabM 的子模型数量(即降低 k),代价是性能略有下降。理论上,还有更先进的算法可用于选择最佳子模型子集,例如 Caruana 等人提出的算法(AMLTK 文档),但这些算法并未在论文中进行分析。此外,请注意,先以 k=32 训练后再选择 k=8 子模型,其效果会优于直接以 k=8 训练。
API
要浏览包的 API 和文档字符串,可采取以下任一方法:
- 克隆此仓库并运行
make docs。 - 在 GitHub 上打开源代码并使用符号面板。
- 在 VSCode 中打开源代码并使用大纲视图。
若想在不克隆或安装任何东西的情况下列出所有可用项,可运行以下代码片段:
uv run --no-project --with tabm python -c """
import tabm
for x in sorted(
x
for x in dir(tabm)
if getattr(getattr(tabm, x), '__module__', None) == 'tabm'
and not x.startswith('_')
):
print(x)
"""
版本历史
v0.0.32025/08/14常见问题
相似工具推荐
openclaw
OpenClaw 是一款专为个人打造的本地化 AI 助手,旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚,能够直接接入你日常使用的各类通讯渠道,包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息,OpenClaw 都能即时响应,甚至支持在 macOS、iOS 和 Android 设备上进行语音交互,并提供实时的画布渲染功能供你操控。 这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地,用户无需依赖云端服务即可享受快速、私密的智能辅助,真正实现了“你的数据,你做主”。其独特的技术亮点在于强大的网关架构,将控制平面与核心助手分离,确保跨平台通信的流畅性与扩展性。 OpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者,以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力(支持 macOS、Linux 及 Windows WSL2),即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你
stable-diffusion-webui
stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面,旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点,将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。 无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师,还是想要深入探索模型潜力的开发者与研究人员,都能从中获益。其核心亮点在于极高的功能丰富度:不仅支持文生图、图生图、局部重绘(Inpainting)和外绘(Outpainting)等基础模式,还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外,它内置了 GFPGAN 和 CodeFormer 等人脸修复工具,支持多种神经网络放大算法,并允许用户通过插件系统无限扩展能力。即使是显存有限的设备,stable-diffusion-webui 也提供了相应的优化选项,让高质量的 AI 艺术创作变得触手可及。
everything-claude-code
everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上
ComfyUI
ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎,专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式,采用直观的节点式流程图界面,让用户通过连接不同的功能模块即可构建个性化的生成管线。 这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景,也能自由组合模型、调整参数并实时预览效果,轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性,不仅支持 Windows、macOS 和 Linux 全平台,还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构,并率先支持 SDXL、Flux、SD3 等前沿模型。 无论是希望深入探索算法潜力的研究人员和开发者,还是追求极致创作自由度的设计师与资深 AI 绘画爱好者,ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能,使其成为当前最灵活、生态最丰富的开源扩散模型工具之一,帮助用户将创意高效转化为现实。
gemini-cli
gemini-cli 是一款由谷歌推出的开源 AI 命令行工具,它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言,它提供了一条从输入提示词到获取模型响应的最短路径,无需切换窗口即可享受智能辅助。 这款工具主要解决了开发过程中频繁上下文切换的痛点,让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用,还是执行复杂的 Git 操作,gemini-cli 都能通过自然语言指令高效处理。 它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口,具备出色的逻辑推理能力;内置 Google 搜索、文件操作及 Shell 命令执行等实用工具;更独特的是,它支持 MCP(模型上下文协议),允许用户灵活扩展自定义集成,连接如图像生成等外部能力。此外,个人谷歌账号即可享受免费的额度支持,且项目基于 Apache 2.0 协议完全开源,是提升终端工作效率的理想助手。
markitdown
MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具,专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片(含 OCR)、音频(含语音转录)、HTML 乃至 YouTube 链接等多种格式的解析,能够精准提取文档中的标题、列表、表格和链接等关键结构信息。 在人工智能应用日益普及的今天,大语言模型(LLM)虽擅长处理文本,却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点,它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式,成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外,它还提供了 MCP(模型上下文协议)服务器,可无缝集成到 Claude Desktop 等 LLM 应用中。 这款工具特别适合开发者、数据科学家及 AI 研究人员使用,尤其是那些需要构建文档检索增强生成(RAG)系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性,但其核心优势在于为机器