Signal from text
Columns your numeric features can’t see — sentiment, topic, phrasing — become
predictive features.
Zero-shot
No fine-tuning, no gradients. A frozen sentence encoder plus an unsupervised
SVD; Nori’s weights never move.
One estimator
It’s still a
NoriRegressor. Name the text columns in the constructor and call
fit / predict on your DataFrame.scikit-learn native
Round-trips through
clone / GridSearchCV / cross_val_score and pickle,
just like the numeric path.Text support needs the optional
text extra (pip install "synthefy-nori[text]"),
which pulls in sentence-transformers. It’s imported lazily, so numeric-only use
never requires it. Extraction runs on the local synthefy-nori package; the
sentence-encoder weights download from Hugging Face on first use.How it works
The text path is a preprocessing layer in front of the ordinary numeric model — Nori itself is unchanged.1
Build one paragraph per row
Each row’s text columns are concatenated into a single column-prefixed string,
e.g.
"title: Wireless Mouse. review: works great, tiny lag.".2
Embed with a frozen encoder
A sentence-transformer (MiniLM by default) turns each paragraph into a dense
vector. The encoder is frozen — no fine-tuning.
3
Reduce with TruncatedSVD
The embeddings are reduced to
svd_dim columns (default 128) with a
TruncatedSVD fit on the training rows only — unsupervised, it never sees
y.4
Append and predict
The SVD columns are appended to the numeric/categorical block, and the frozen
Nori predicts on the widened table.
predict re-embeds the query rows and
applies the already-fit SVD, so the train/test transform is symmetric.Quickstart
Name the text columns in the constructor and use the estimator exactly as you would for a numeric table —X is a pandas.DataFrame that holds numeric,
categorical, and text columns together.
fit / predict. Numeric and categorical columns you don’t list
as text are handled automatically — numeric passes through, categorical is
label-encoded.
Does it actually help? A runnable check
examples/text_features_synthetic.py
builds a small synthetic dataset where the target depends on numeric columns
(x1, x2), a categorical column (brand), and the sentiment word buried in
a free-text review — signal the numeric columns can’t reach. It then fits Nori
twice, with and without the text column, on a held-out split.
text_columns=[] is a valid fit on a DataFrame that keeps only the numeric and
categorical columns (no encoder loaded) — handy for an apples-to-apples baseline
against text_columns=[...].Configuration
Constructor parameters
Constructor parameters
Choosing an encoder
Choosing an encoder
"minilm" (384-d, fast) is a strong default and needs no extra setup. Larger
encoders trade speed for representation quality:You can also pass a preloaded
SentenceTransformer (reuse one across fits) or
any callable texts -> (n, dim) ndarray.Under the hood: the numeric-only path (
text_columns=None) is unchanged.
High-cardinality columns are embedded rather than label-encoded, categorical codes
are bounded (unseen values map to a single in-range “other” code), and the SVD is
fit on train only — so a fitted text model pickles and clones like any sklearn
estimator.