Separate from #91 (which is about config.json keys being merged in unvalidated) — this is about the constructor itself, and it affects anyone calling TabFM(...) directly in Python.
I tested every dimensional parameter at 0 and -1 on b15593e4c1111ddb5f4f30dd2957df2edbaa04ca, in a clean container. Ten of thirteen accept 0 and build a model with no error. Three accept -1 as well.
param value outcome
------------------------------------------------------------------------
embed_dim 0 BUILT OK (no validation)
embed_dim -1 RuntimeError: Trying to create tensor with negative di
max_classes 0 BUILT OK (no validation)
max_classes -1 RuntimeError: Trying to create tensor with negative di
col_num_blocks 0 BUILT OK (no validation)
col_num_blocks -1 BUILT OK (no validation)
col_nhead 0 ZeroDivisionError
col_nhead -1 RuntimeError: Trying to create tensor with negative di
col_num_inds 0 BUILT OK (no validation)
col_num_inds -1 RuntimeError: zeros: Dimension size must be non-negati
row_num_blocks 0 BUILT OK (no validation)
row_num_blocks -1 BUILT OK (no validation)
row_nhead 0 ZeroDivisionError
row_nhead -1 RuntimeError: upper bound and lower bound inconsistent
row_num_cls 0 BUILT OK (no validation)
row_num_cls -1 RuntimeError: zeros: Dimension size must be non-negati
icl_num_blocks 0 BUILT OK (no validation)
icl_num_blocks -1 BUILT OK (no validation)
icl_nhead 0 ZeroDivisionError
icl_nhead -1 RuntimeError: Trying to create tensor with negative di
ff_factor 0 BUILT OK (no validation)
ff_factor -1 RuntimeError: Trying to create tensor with negative di
feature_group_size 0 BUILT OK (no validation)
feature_group_size -1 RuntimeError: zeros: Dimension size must be non-negati
num_freq 0 BUILT OK (no validation)
num_freq -1 RuntimeError: zeros: Dimension size must be non-negati
The one I would draw your attention to is *_num_blocks. Passing 0 or -1 makes range(...) empty, so the ModuleList is empty and the model is built with no attention blocks at all. It still runs and still returns predictions. Nothing warns. That is a worse outcome than the crashes elsewhere in the table, because a crash is at least honest about what happened.
Where errors do occur they come from PyTorch rather than from tabfm, so the message describes a tensor shape rather than the parameter the caller actually got wrong — Trying to create tensor with negative dimension does not tell someone that ff_factor was the problem.
A small guard at the top of __init__ rejecting non-positive values for these parameters would turn all twenty-six rows into one clear message. I am happy to send that PR if you would like it — I did not want to presume which parameters you consider legitimately zero-able (decoder_hidden is already None-able, so there may be others by design).
Disclosure: I used an AI assistant to help find this. I ran the matrix myself.
Separate from #91 (which is about
config.jsonkeys being merged in unvalidated) — this is about the constructor itself, and it affects anyone callingTabFM(...)directly in Python.I tested every dimensional parameter at
0and-1onb15593e4c1111ddb5f4f30dd2957df2edbaa04ca, in a clean container. Ten of thirteen accept0and build a model with no error. Three accept-1as well.The one I would draw your attention to is
*_num_blocks. Passing0or-1makesrange(...)empty, so theModuleListis empty and the model is built with no attention blocks at all. It still runs and still returns predictions. Nothing warns. That is a worse outcome than the crashes elsewhere in the table, because a crash is at least honest about what happened.Where errors do occur they come from PyTorch rather than from tabfm, so the message describes a tensor shape rather than the parameter the caller actually got wrong —
Trying to create tensor with negative dimensiondoes not tell someone thatff_factorwas the problem.A small guard at the top of
__init__rejecting non-positive values for these parameters would turn all twenty-six rows into one clear message. I am happy to send that PR if you would like it — I did not want to presume which parameters you consider legitimately zero-able (decoder_hiddenis alreadyNone-able, so there may be others by design).Disclosure: I used an AI assistant to help find this. I ran the matrix myself.