如何使用NVIDIA结构化数据模型进行零训练表格预测
How to Make Zero-Training Tabular Predictions with NVIDIA Structured Data Models
In this tutorial, we implement Structured Data Models, NVIDIAs new library that puts several pretrained foundation models for tables behind one PyTorch interface, and use it to make predictions without training. The library wraps TabICLv2 and KumoTabular for single tables and KumoRelational for whole relational databases, and each of them answers by in-context learning: we hand the model a set of labeled rows and the rows we want predicted, and it returns probabilities or a full predictive distribution in one forward pass. We start with the librarys typed table tensors, compare the two tabular models against trained scikit-learn baselines, reuse an encoded context across many queries, read calibrated prediction intervals off a regression, and scale to twenty classes. We then look at the...
In this tutorial, we implement Structured Data Models, NVIDIAs new library that puts several pretrained foundation models for tables behind one PyTorch interface, and use it to make predictions without training. The library wraps TabICLv2 and KumoTabular for single tables and KumoRelational for whole relational databases, and each of them answers by in-context learning: we hand the model a set of labeled rows and the rows we want predicted, and it returns probabilities or a full predictive distribution in one forward pass. We start with the librarys typed table tensors, compare the two tabular models against trained scikit-learn baselines, reuse an encoded context across many queries, read calibrated prediction intervals off a regression, and scale to twenty classes. We then look at the places where the defaults quietly do the wrong thing: a preprocessing recipe that drops timestamp and text columns and an explainer with two traps in it, before building a small three-table shop database and predicting customer activity from it directly, including the one argument that separates an honest relational model from a leaky one. Check out the Full CODES here. Copy CodeCopiedUse a different Browser We install Structured Data Models from the GitHub repository, pinned to the commit this notebook was verified against, since the package on PyPI is only a placeholder. The relational sampler also needs pyg-lib, and that is where the first trap lies. pyg-lib wheels are published per minor PyTorch release, on pages named like torch-2.14.0+cpu, but the librarys own ImportError builds the URL from the exact patch version, torch-2.14.1+cpu, which is an empty page, so following its advice fails. We build the index URL from the major and minor version instead. We run everything on the CPU, which is the path verified end to end here, and print the models the library exposes together with their checkpoint sizes and licenses; the two Google models it also wraps, TabFM and TimesFM 3, are large and non-commercial and are left out. Check out the Full CODES here. Copy CodeCopiedUse a different Browser Everything in the library flows through TableTensor, a PyTorch tensor subclass that keeps one typed block per semantic type: numerical, categorical, datetime, text and id. infer_stypes decides the types, and with its defaults it gets two things wrong on a realistic support-ticket frame: the free-text comment becomes a categorical with four hundred levels and the ticket id becomes a number, so both would reach a model as features. Passing text and id inference flags fixes that. The round trip back to pandas preserves every value, missing ones included, but not every dtype: numbers return as float32 because the numerical block is a single float tensor, nullable integers become floats with NaN, and categorical strings return as a pandas category. On pandas 2.x the string columns print as object rather than str and the timestamp goes in at nanosecond resolution; the same values come back either way. One more trap is worth knowing before you load a real event log: the library stores datetimes as integer microseconds, and Arrow refuses any cast that would drop a digit. A nanosecond column of whole seconds converts fine, but a single value with nanosecond digits fails the whole column, so we floor timestamps to microseconds first. Check out the Full CODES here. Copy CodeCopiedUse a different Browser The tabular models take labelled context rows and unlabelled query rows and return a TableTensor with one probability column per class, named by label, so there is no fit step and no hyperparameters. On the breast cancer dataset, with three hundred labelled rows and two hundred and sixty-nine to predict, TabICLv2 and KumoTabular reach 0.970 accuracy and AUCs of 0.996 and 0.995 with no training, against 0.970 and 0.993 for a logistic regression and 0.967 and 0.992 for gradient boosting, both fitted on the same three hundred rows. num_estimators sets how many differently preprocessed views of the data the model averages over, which is the librarys built-in ensembling. Copy CodeCopiedUse a different Browser Calling the model directly re-encodes the context on every call. When the same labelled rows will answer many batches of queries, fit encodes the context once into a key and value cache and predict then runs only the query rows; clear frees the cache. Nothing is learned in fit, which here means remember these examples. Answering five batches of thirty rows against the same four hundred context rows finished several times faster this way on our CPU, and once the context was cached, each further batch cost a small fraction of a full forward pass. The exact ratio depends on the machine, which is why the cell measures it rather than assuming it. Copy CodeCopiedUse a different Browser For regression, the model does not return a single number. It returns 999 quantiles per query row, a full predictive distribution read off one forward pass. On the diabetes dataset with three hundred labelled rows, the median of that distribution has an RMSE of 53.6, slightly better than RidgeCV at 54.3 and clearly better than gradient boosting at 64.7, both trained on the same rows. The more useful property is calibration: the interval between the 10th and 90th percentiles contains 81.0 percent of the held-out targets and the 5th to 95th percentile interval 91.5 percent, close to their nominal 80 and 90 percent, while the 50 percent band runs somewhat narrow at 43.7 percent. Copy CodeCopiedUse a different Browser The pretrained classification head has a fixed number of class slots, and the library handles problems with more classes than that through error-correcting output codes, splitting the problem into smaller coded subproblems and recombining the log-probabilities. The caller never sees this: on a balanced twenty-class synthetic problem with thirty labelled rows per class, TabICLv2 returns twenty probability columns and reaches 0.760 accuracy in a single forward pass, against 0.615 for gradient boosting trained on the same rows. Copy CodeCopiedUse a different Browser Preprocessing in the library is a Recipe of composable processors, and the default TabICLv2 recipe dispatches on semantic type with branches only for categorical and numerical columns. Timestamp and text columns therefore never become features. On support tickets whose escalation depends on when they were opened and on words such as refund, the default recipe scores an AUC of 0.525, close to chance. The library does emit a RuntimeWarning naming the ignored column types. Still, it is a warn-once: it fires the first time and is suppressed for the rest of the process, so every later model in the same notebook or service drops those columns in silence. Prepending two processors fixes it: AddCalendarFields turns the timestamp into cyclic hour and weekday features, lifting the AUC to 0.634, and TFIDF adds the comments terms, lifting it to 0.789. Copy CodeCopiedUse a different Browser The librarys GradientExplainer returns the gradient of a chosen output with respect to the preprocessed query inputs, and we test it on synthetic data where only three of eight features matter, with known signs. It has two traps, both visible only by looking at what the output function receives. First, the function is called once per estimator and each call overwrites the previous result, so with four estimators an output function that is live only on the first call yields an all-zero explanation, and the explanation you get is only the last estimators. Second, each estimators raw output has its own class order, because the default recipe shuffles class labels per estimator. Explaining with a single estimator across six seeds, selecting the probability of class one by column position flips the sign of every feature on the two seeds whose order is reversed, while selecting it by column name gives the right sign on all six, and averaging over the seeds recovers the three rea