kurversc 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kurversc-0.1.0/PKG-INFO +474 -0
- kurversc-0.1.0/README.md +448 -0
- kurversc-0.1.0/kurversc/__init__.py +31 -0
- kurversc-0.1.0/kurversc/core.py +4718 -0
- kurversc-0.1.0/kurversc/feature_audit.py +373 -0
- kurversc-0.1.0/kurversc/logging.py +23 -0
- kurversc-0.1.0/kurversc/modeling.py +519 -0
- kurversc-0.1.0/kurversc/relbench.py +520 -0
- kurversc-0.1.0/kurversc/search.py +688 -0
- kurversc-0.1.0/kurversc/specs.py +199 -0
- kurversc-0.1.0/kurversc.egg-info/PKG-INFO +474 -0
- kurversc-0.1.0/kurversc.egg-info/SOURCES.txt +20 -0
- kurversc-0.1.0/kurversc.egg-info/dependency_links.txt +1 -0
- kurversc-0.1.0/kurversc.egg-info/requires.txt +17 -0
- kurversc-0.1.0/kurversc.egg-info/top_level.txt +1 -0
- kurversc-0.1.0/pyproject.toml +38 -0
- kurversc-0.1.0/setup.cfg +4 -0
- kurversc-0.1.0/tests/test_feature_audit.py +170 -0
- kurversc-0.1.0/tests/test_fit.py +868 -0
- kurversc-0.1.0/tests/test_modeling.py +66 -0
- kurversc-0.1.0/tests/test_relbench_adapter.py +270 -0
- kurversc-0.1.0/tests/test_search.py +279 -0
kurversc-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kurversc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Validation-guided configuration search for GraphReduce
|
|
5
|
+
Author: KurveAI
|
|
6
|
+
Project-URL: Homepage, https://github.com/kurveai/kurversc
|
|
7
|
+
Project-URL: Repository, https://github.com/kurveai/kurversc
|
|
8
|
+
Project-URL: Documentation, https://github.com/kurveai/kurversc/blob/main/docs/kurversc-technical-report.md
|
|
9
|
+
Project-URL: Issues, https://github.com/kurveai/kurversc/issues
|
|
10
|
+
Requires-Python: <3.13,>=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: catboost<2,>=1.2
|
|
13
|
+
Requires-Dist: duckdb<1.3,>=1.2
|
|
14
|
+
Requires-Dist: graphreduce==1.10.13
|
|
15
|
+
Requires-Dist: numpy<2,>=1.24
|
|
16
|
+
Requires-Dist: pandas<3.1,>=1.5
|
|
17
|
+
Requires-Dist: pytz>=2024.1
|
|
18
|
+
Requires-Dist: scikit-learn<2,>=1.4
|
|
19
|
+
Requires-Dist: structlog>=23.1
|
|
20
|
+
Provides-Extra: test
|
|
21
|
+
Requires-Dist: pytest<9,>=8; extra == "test"
|
|
22
|
+
Provides-Extra: relbench
|
|
23
|
+
Requires-Dist: relbench<3,>=2.1; extra == "relbench"
|
|
24
|
+
Provides-Extra: tabpfn
|
|
25
|
+
Requires-Dist: tabpfn<9,>=8.5; extra == "tabpfn"
|
|
26
|
+
|
|
27
|
+
# KurveRSC
|
|
28
|
+
|
|
29
|
+
KurveRSC is an integrated relational representation and model-selection
|
|
30
|
+
system. It uses [GraphReduce](https://github.com/wesmadrigal/graphreduce) as
|
|
31
|
+
its relational feature engine, searches graph configurations
|
|
32
|
+
across temporal frames, and selects them by downstream validation performance.
|
|
33
|
+
Its main API is one function:
|
|
34
|
+
|
|
35
|
+
The [KurveRSC technical report](https://github.com/kurveai/kurversc/blob/main/docs/kurversc-technical-report.md)
|
|
36
|
+
([PDF](https://github.com/kurveai/kurversc/blob/main/docs/kurversc-technical-report.pdf)) explains the
|
|
37
|
+
GraphReduce algorithm, relational feature families, learner-guided graph search,
|
|
38
|
+
point-in-time guarantees, frozen-plan lifecycle, and evaluation protocol. The
|
|
39
|
+
shorter [Kurve RSC white paper](https://github.com/kurveai/kurversc/blob/main/docs/kurversc-white-paper.md)
|
|
40
|
+
([PDF](https://github.com/kurveai/kurversc/blob/main/docs/kurversc-white-paper.pdf)) introduces the central optimization idea.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install "kurversc[relbench]" # omit [relbench] for ordinary tables
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
import kurversc
|
|
48
|
+
|
|
49
|
+
result = kurversc.fit(
|
|
50
|
+
parent_node="customers.parquet",
|
|
51
|
+
label_node="churn_labels.parquet",
|
|
52
|
+
parent_key="customer_id",
|
|
53
|
+
label_key="customer_id",
|
|
54
|
+
target="churn",
|
|
55
|
+
split_column="split", # values: train / validation
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
print(result.best_config) # highest validation ROC AUC or lowest MAE
|
|
59
|
+
print(result.recommended_config) # simpler config when the gain is negligible
|
|
60
|
+
print(result.results)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Both node arguments accept a pandas DataFrame, CSV/Parquet path, or the name of
|
|
64
|
+
a table/view on a supplied DuckDB connection. For explicit metadata, use
|
|
65
|
+
`Table` and `Labels`:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
result = kurversc.fit(
|
|
69
|
+
parent_node=kurversc.Table(
|
|
70
|
+
"users", name="users", key="Id", date="CreationDate"
|
|
71
|
+
),
|
|
72
|
+
label_node=kurversc.Labels(
|
|
73
|
+
"user_labels",
|
|
74
|
+
key="user_id",
|
|
75
|
+
target="will_return",
|
|
76
|
+
timestamp="timestamp",
|
|
77
|
+
split="split",
|
|
78
|
+
),
|
|
79
|
+
tables=[
|
|
80
|
+
kurversc.Table(
|
|
81
|
+
"posts", name="posts", key="Id", date="CreationDate"
|
|
82
|
+
),
|
|
83
|
+
kurversc.Table(
|
|
84
|
+
"comments", name="comments", key="Id", date="CreationDate"
|
|
85
|
+
),
|
|
86
|
+
],
|
|
87
|
+
relationships=[
|
|
88
|
+
kurversc.Relationship(
|
|
89
|
+
parent="users",
|
|
90
|
+
child="posts",
|
|
91
|
+
parent_key="Id",
|
|
92
|
+
child_key="OwnerUserId",
|
|
93
|
+
),
|
|
94
|
+
kurversc.Relationship(
|
|
95
|
+
parent="posts",
|
|
96
|
+
child="comments",
|
|
97
|
+
parent_key="Id",
|
|
98
|
+
child_key="PostId",
|
|
99
|
+
),
|
|
100
|
+
],
|
|
101
|
+
connection=duckdb_connection,
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
When the target is a future aggregation over one of the graph's event tables,
|
|
106
|
+
let GraphReduce generate it natively instead of supplying a materialized label
|
|
107
|
+
table:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
label_node=kurversc.GraphLabels(
|
|
111
|
+
table="orders",
|
|
112
|
+
field="id",
|
|
113
|
+
operation="bool",
|
|
114
|
+
period_days=365,
|
|
115
|
+
train_cutoffs=("2023-01-01", "2024-01-01"),
|
|
116
|
+
validation_cutoffs=("2025-01-01",),
|
|
117
|
+
test_cutoffs=("2026-01-01",),
|
|
118
|
+
target="will_order",
|
|
119
|
+
)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
This executes GraphReduce's `prep_for_labels()` and automatic `do_labels`
|
|
123
|
+
aggregation at every cutoff. `Labels` remains the correct interface for
|
|
124
|
+
authoritative external targets such as official RelBench task tables.
|
|
125
|
+
|
|
126
|
+
Relationships are required when the compute graph contains feature tables:
|
|
127
|
+
file names alone cannot determine foreign-key direction or whether a join is
|
|
128
|
+
one-to-many. The two label/entity keys are also explicit so label attachment is
|
|
129
|
+
never guessed.
|
|
130
|
+
|
|
131
|
+
## What `fit` searches
|
|
132
|
+
|
|
133
|
+
The default search is deterministic and starts with the smallest base-only
|
|
134
|
+
configuration. Before building a graph, KurveRSC profiles a small sample from
|
|
135
|
+
every node and utility-ranks its source columns. Structural keys and cutoff
|
|
136
|
+
dates are always retained. A cap therefore admits the strongest observed
|
|
137
|
+
source columns instead of whichever columns happen to occur first in the
|
|
138
|
+
physical schema.
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
result = kurversc.fit(
|
|
142
|
+
...,
|
|
143
|
+
feature_family_max_columns=4, # fixed columns per family
|
|
144
|
+
feature_family_max_features_per_column=32,
|
|
145
|
+
feature_propagation_max_functions_per_column=1,
|
|
146
|
+
feature_ranking_rows=2_000,
|
|
147
|
+
forward_search_beam_width=2,
|
|
148
|
+
screening_rows=10_000,
|
|
149
|
+
sample_rows=50_000, # confirmation fidelity
|
|
150
|
+
confirmation_top_k=8, # diverse 50K candidates
|
|
151
|
+
rerank_top_k=3, # full-data finalists
|
|
152
|
+
rerank_cutoff_frames=3, # sequential walk-forward folds
|
|
153
|
+
adaptive_depth_promotion=True,
|
|
154
|
+
capability_pruning=True,
|
|
155
|
+
search_max_features=8_000,
|
|
156
|
+
random_state=42, # CatBoost and sampling seed
|
|
157
|
+
)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`random_state` is a reproducibility seed, not a trial count. KurveRSC uses the
|
|
161
|
+
same deterministic seed for competing graph configurations so stochastic model
|
|
162
|
+
behavior does not favor one shape over another.
|
|
163
|
+
|
|
164
|
+
The family lattice contains independent additions of `temporal`, `sequence`,
|
|
165
|
+
`conditional`, and `episode` to `base`, including their combinations. It does
|
|
166
|
+
not require a weak family to be present before a later family can be tested.
|
|
167
|
+
Depth 3 is limited to combinations of `base`, `temporal`, and `sequence`; wider
|
|
168
|
+
conditional and episode programs use depths 1 and 2.
|
|
169
|
+
|
|
170
|
+
At the default four-column budget, the forward beam executes at most 24 graph
|
|
171
|
+
shapes: up to four adaptive base variants, then at most 8, 6, 4, and 2
|
|
172
|
+
survivors across the successive family levels. The complete 72-shape lattice remains in the audit
|
|
173
|
+
trail with non-executed candidates marked `pruned`. A wider budget is opt-in:
|
|
174
|
+
`feature_family_max_column_options=(4, 8)` adds another 72 potential records,
|
|
175
|
+
but only the raw narrow-budget winner and the complexity-aware narrow-budget
|
|
176
|
+
recommendation are promoted from four to eight source columns (with the next
|
|
177
|
+
score-ranked shape filling the second slot when they are identical). That
|
|
178
|
+
expanded funnel normally materializes at most 28 configurations rather than
|
|
179
|
+
exhaustively running all 144 potential combinations.
|
|
180
|
+
|
|
181
|
+
```text
|
|
182
|
+
default cap: 4 base + 8 singles + 6 pairs + 4 triples + 2 quadruples = 24
|
|
183
|
+
optional wide cap: top-2 complete narrow-cap shapes = 2
|
|
184
|
+
----
|
|
185
|
+
maximum materialized by the opt-in expanded funnel = 26
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
The default search is multi-fidelity. Beam-admitted configurations are first
|
|
189
|
+
screened with at most 10,000 rows per node. Eight structurally diverse
|
|
190
|
+
candidates are rebuilt and rescored with `sample_rows`: the raw and
|
|
191
|
+
complexity-aware leaders plus representatives of available families, deeper
|
|
192
|
+
propagation, and both annotation policies. The strongest three confirmed
|
|
193
|
+
shapes are then reranked over three complete relational cutoff folds before the
|
|
194
|
+
final graph program is selected. `result.results`,
|
|
195
|
+
`result.confirmation_results`, and `result.rerank_results` expose the three
|
|
196
|
+
audit trails separately.
|
|
197
|
+
|
|
198
|
+
Adaptive depth promotion evaluates both annotation policies at depth 1,
|
|
199
|
+
promotes only the stronger policy to depth 2, and admits depth 3 only when the
|
|
200
|
+
depth-2 gain exceeds both the task tolerance and validation uncertainty.
|
|
201
|
+
Capability pruning removes families that cannot produce operations for the
|
|
202
|
+
available graph schema. Finally, `search_max_features` uses the source-column
|
|
203
|
+
audit and observed parent widths to reject a predicted feature explosion before
|
|
204
|
+
its SQL is materialized. All three guards can be disabled independently.
|
|
205
|
+
|
|
206
|
+
Customize the stages with `max_depth`, `auto_annotate_options`, and
|
|
207
|
+
`feature_family_stages`, or pass explicit `graph_configs` to override the
|
|
208
|
+
frontier. Set `feature_family_max_column_options=(4, 8)` to opt into wider
|
|
209
|
+
refinement, or include `None` as a tier to test an uncapped finalist.
|
|
210
|
+
`feature_family_max_features_per_column` is a separate GraphReduce guardrail:
|
|
211
|
+
it prevents a single temporal or categorical source from expanding into an
|
|
212
|
+
unbounded number of derived SQL features. The propagation cap prevents each
|
|
213
|
+
already-derived column from branching again at every graph hop while retaining
|
|
214
|
+
its canonical continuation (`max→max`, `min→min`, `sum→sum`, `count→sum`, and
|
|
215
|
+
`avg→avg`). Inspect `result.feature_audit` to see every source column's role,
|
|
216
|
+
utility score, family rank, eligible budget tiers, and exclusion reason.
|
|
217
|
+
|
|
218
|
+
`semantic` uses automatic annotations when `auto_annotate_features=True` (or
|
|
219
|
+
caller-supplied GraphReduce annotations). `context` requires peer-group keys;
|
|
220
|
+
`Table.context_keys` supplies them directly, and the RelBench adapter derives
|
|
221
|
+
them from foreign keys other than the edge currently being reduced.
|
|
222
|
+
|
|
223
|
+
Every candidate holds the remaining node policy fixed: GraphReduce's native
|
|
224
|
+
1/3/4/7/14/30/60/90/180/365/730-day time-series periods (plus the compute
|
|
225
|
+
horizon when it exceeds 365 days) unless `infer_ts_periods=True`, categorical
|
|
226
|
+
cardinality threshold 20, categorical top-k 5, automatic text features disabled, and annotation
|
|
227
|
+
bounds 10 categorical columns, 4 gated numeric columns, and top-k 3. These settings are assigned to
|
|
228
|
+
each node explicitly so they are effective with GraphReduce 1.10.
|
|
229
|
+
|
|
230
|
+
### Optional TabPFN v3 estimator
|
|
231
|
+
|
|
232
|
+
CatBoost remains the default downstream estimator. Install the local TabPFN
|
|
233
|
+
integration and select v3 explicitly with:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
pip install "kurversc[relbench,tabpfn]"
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
result = kurversc.fit(
|
|
241
|
+
**problem.fit_kwargs(),
|
|
242
|
+
model_backend="tabpfn_v3",
|
|
243
|
+
estimator_train_rows=10_000,
|
|
244
|
+
model_params={
|
|
245
|
+
"n_estimators": 2,
|
|
246
|
+
"fit_mode": "low_memory",
|
|
247
|
+
},
|
|
248
|
+
)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
`estimator_train_rows` is applied consistently to sampled configuration
|
|
252
|
+
screening, full-history finalist fitting, and final train-plus-validation
|
|
253
|
+
fitting. Classification samples are stratified and deterministic. When the
|
|
254
|
+
TabPFN backend is selected without an explicit cap, KurveRSC defaults it to
|
|
255
|
+
10,000 rows. Graph materialization remains independent of this estimator-only
|
|
256
|
+
cap, and the fitted artifact can be replayed with `kurversc.predict(...)`.
|
|
257
|
+
|
|
258
|
+
By default, each search source—including labels—is exposed to GraphReduce
|
|
259
|
+
through a temporary DuckDB view capped at `sample_rows`. Set
|
|
260
|
+
`search_full_data=True` to evaluate every candidate against complete source
|
|
261
|
+
tables instead:
|
|
262
|
+
|
|
263
|
+
```python
|
|
264
|
+
result = kurversc.fit(
|
|
265
|
+
parent_node=parent,
|
|
266
|
+
label_node=labels,
|
|
267
|
+
tables=tables,
|
|
268
|
+
relationships=relationships,
|
|
269
|
+
sample_rows=50_000, # still used for ordinary sampled searches
|
|
270
|
+
search_full_data=True, # disables row sampling during config search
|
|
271
|
+
full_training_frames=3, # cutoff dates used for final frame ensembling
|
|
272
|
+
infer_ts_periods=True,
|
|
273
|
+
auto_text_features=False,
|
|
274
|
+
)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
`search_full_data=True` uses complete rows at every eligible search cutoff
|
|
278
|
+
selected by `search_training_frames` for every configuration admitted by the
|
|
279
|
+
forward funnel. The winning
|
|
280
|
+
configuration is selected
|
|
281
|
+
directly from those validation scores unless temporal reranking is enabled,
|
|
282
|
+
and is then fit across the requested full-training cutoff dates. Adapters can
|
|
283
|
+
attach a separate connected `search_source` while retaining their uncapped
|
|
284
|
+
production source. A
|
|
285
|
+
new graph is created for every candidate because GraphReduce execution mutates
|
|
286
|
+
node state. If labels contain a timestamp, features are built at each label
|
|
287
|
+
cutoff; otherwise labels are split randomly (or by `split_column`) and the
|
|
288
|
+
current time is used as the feature cutoff.
|
|
289
|
+
|
|
290
|
+
Classification candidates use CatBoost and validation ROC AUC. Regression
|
|
291
|
+
candidates use CatBoost and validation MAE. The highest-performing candidate
|
|
292
|
+
is always retained as `best_trial`. KurveRSC also records feature count,
|
|
293
|
+
feature/model time, and an estimated validation-metric standard error. Trials
|
|
294
|
+
that add at least 2x as many features without improving beyond both the fixed
|
|
295
|
+
0.002 AUC / 0.5% relative MAE floor and the configured uncertainty threshold
|
|
296
|
+
are marked in `result.complexity_notes`. `recommended_trial` is the
|
|
297
|
+
lowest-feature candidate statistically indistinguishable from the raw winner;
|
|
298
|
+
`best_trial` remains the unpenalized validation winner. Set
|
|
299
|
+
`complexity_uncertainty_multiplier=0` to use only the fixed tolerances.
|
|
300
|
+
|
|
301
|
+
By default, rerank the three strongest confirmed finalists over three
|
|
302
|
+
walk-forward full-data cutoff folds:
|
|
303
|
+
|
|
304
|
+
```python
|
|
305
|
+
result = kurversc.fit(
|
|
306
|
+
...,
|
|
307
|
+
rerank_top_k=3,
|
|
308
|
+
rerank_cutoff_frames=3,
|
|
309
|
+
rerank_stability_penalty=0.25,
|
|
310
|
+
)
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
The reranker learns and scores one cutoff frame at a time, releases it, and
|
|
314
|
+
then advances to the next fold. Classification maximizes mean ROC AUC minus
|
|
315
|
+
the configured standard-deviation penalty; regression minimizes mean MAE plus
|
|
316
|
+
that penalty. The raw stability-adjusted winner is selected; the complexity
|
|
317
|
+
guard remains a screening and audit mechanism but cannot override this
|
|
318
|
+
full-frame evidence. The audit trail is available as `result.rerank_results`.
|
|
319
|
+
Set `rerank_cutoff_frames=1` for a single full-data train-to-validation rerank;
|
|
320
|
+
the stability penalty is then zero because there is only one score.
|
|
321
|
+
|
|
322
|
+
## What the returned fitted model means
|
|
323
|
+
|
|
324
|
+
`fit` has a nine-stage lifecycle:
|
|
325
|
+
|
|
326
|
+
1. Utility-rank source columns and record the capped feature-funnel audit.
|
|
327
|
+
2. Build beam-admitted candidates from sampled source views, or from complete
|
|
328
|
+
source rows when `search_full_data=True`.
|
|
329
|
+
3. Rank candidates by one-frame validation ROC AUC or MAE and promote only the
|
|
330
|
+
strongest graph shapes to broader source-column budgets.
|
|
331
|
+
4. Confirm a structurally diverse bounded candidate set at medium fidelity.
|
|
332
|
+
5. Rerank the three strongest confirmed candidates over sequential full-data
|
|
333
|
+
walk-forward cutoff folds and select the raw stability-adjusted winner.
|
|
334
|
+
6. Freeze its exact GraphReduce operation plan and training-only feature schema.
|
|
335
|
+
7. Materialize one production cutoff at a time and fit an independent CatBoost
|
|
336
|
+
model for that frame.
|
|
337
|
+
8. Score validation with the training-frame ensemble, then add independently
|
|
338
|
+
fitted validation-frame models to the final train-plus-validation ensemble.
|
|
339
|
+
9. Replay the plan with `GraphReduce(train=False)` at test cutoffs and expose
|
|
340
|
+
predictions as `result.test_predictions`. If an external `Labels` test
|
|
341
|
+
split contains targets, KurveRSC also records a test score.
|
|
342
|
+
|
|
343
|
+
The resulting production artifact is `result.fitted_model`: selected
|
|
344
|
+
`GraphConfig`, frozen execution plan, ordered feature schema, CatBoost model,
|
|
345
|
+
and validation/test metadata. `result.model` returns its final CatBoost model;
|
|
346
|
+
`result.execution_plan` returns the production GraphReduce plan. Validation
|
|
347
|
+
and test never run feature inference or annotation again.
|
|
348
|
+
|
|
349
|
+
When `infer_ts_periods=True`, KurveRSC asks GraphReduce to infer
|
|
350
|
+
relationship-specific event-cadence windows. Each dated node or relationship
|
|
351
|
+
can then replace the initial `[7, 30, 90]` windows with compact, data-derived
|
|
352
|
+
lookbacks spanning the configured compute horizon. KurveRSC stores those
|
|
353
|
+
inferred periods inside the frozen execution plan and restores them during
|
|
354
|
+
validation, outer refit, and prediction; replay never re-infers them.
|
|
355
|
+
|
|
356
|
+
Replay the fitted artifact on another timestamped entity frame with the same
|
|
357
|
+
declarative graph metadata:
|
|
358
|
+
|
|
359
|
+
```python
|
|
360
|
+
predictions = kurversc.predict(
|
|
361
|
+
result,
|
|
362
|
+
parent_node=parent,
|
|
363
|
+
prediction_node=kurversc.Labels(
|
|
364
|
+
scoring_rows, key="customer_id", timestamp="timestamp"
|
|
365
|
+
),
|
|
366
|
+
tables=tables,
|
|
367
|
+
relationships=relationships,
|
|
368
|
+
)
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
The output preserves prediction-row order and adds a `prediction` column.
|
|
372
|
+
|
|
373
|
+
Point-in-time production training can use many frames. By default, every
|
|
374
|
+
configuration is screened on one frame at the latest eligible cutoff. With
|
|
375
|
+
`search_full_data=True`, that frame uses all available rows. Supply all valid
|
|
376
|
+
cutoffs through `GraphLabels.train_cutoffs`, or all timestamped rows through
|
|
377
|
+
`Labels`, then choose the incremental production frame count:
|
|
378
|
+
|
|
379
|
+
```python
|
|
380
|
+
result = kurversc.fit(
|
|
381
|
+
...,
|
|
382
|
+
search_full_data=True, # evaluate all candidates on complete rows
|
|
383
|
+
full_training_frames=3, # 3 evenly spaced available train cutoffs
|
|
384
|
+
)
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
`full_training_frames=None` (the default) uses every available training
|
|
388
|
+
cutoff. These are point-in-time graph frames, not partitions of raw event
|
|
389
|
+
tables: every frame sees the complete history allowed by its cutoff, and all
|
|
390
|
+
frames replay the selected operation plan. KurveRSC releases each materialized
|
|
391
|
+
feature frame before constructing the next one. Independent CatBoost models are
|
|
392
|
+
combined as an ensemble, so the final fit never concatenates those wide frames
|
|
393
|
+
in memory. When
|
|
394
|
+
`full_training_frames=1`, KurveRSC always uses the latest eligible training
|
|
395
|
+
cutoff. The search audit trail is available as `result.results`.
|
|
396
|
+
|
|
397
|
+
## Official RelBench tasks
|
|
398
|
+
|
|
399
|
+
`load_relbench_problem` uses the production RelBench dataset, task tables,
|
|
400
|
+
date keys, primary keys, and foreign keys without adding task-specific feature
|
|
401
|
+
expressions:
|
|
402
|
+
|
|
403
|
+
```python
|
|
404
|
+
import kurversc
|
|
405
|
+
|
|
406
|
+
problem = kurversc.load_relbench_problem(
|
|
407
|
+
"rel-stack",
|
|
408
|
+
"user-badge",
|
|
409
|
+
sample_rows=10_000,
|
|
410
|
+
max_train_timestamps=1,
|
|
411
|
+
max_enrichment_columns=8,
|
|
412
|
+
)
|
|
413
|
+
result = kurversc.fit(**problem.fit_kwargs(), sample_rows=10_000)
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
For a full-data configuration search followed by a three-cutoff production
|
|
417
|
+
fit, use:
|
|
418
|
+
|
|
419
|
+
```python
|
|
420
|
+
problem = kurversc.load_relbench_problem(
|
|
421
|
+
"rel-stack",
|
|
422
|
+
"user-badge",
|
|
423
|
+
sample_rows=50_000,
|
|
424
|
+
search_full_data=True,
|
|
425
|
+
max_train_timestamps=3,
|
|
426
|
+
)
|
|
427
|
+
result = kurversc.fit(
|
|
428
|
+
**problem.fit_kwargs(),
|
|
429
|
+
sample_rows=50_000,
|
|
430
|
+
search_full_data=True,
|
|
431
|
+
full_training_frames=3,
|
|
432
|
+
infer_ts_periods=True,
|
|
433
|
+
auto_text_features=False,
|
|
434
|
+
)
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
This runs the beam-admitted graph configurations on complete rows at the latest
|
|
438
|
+
training cutoff, promotes only the strongest shapes to the wider source-column
|
|
439
|
+
budget, and fits the selected configuration across three cutoff dates while
|
|
440
|
+
retaining only one materialized feature frame.
|
|
441
|
+
|
|
442
|
+
Install the optional adapter with `pip install "kurversc[relbench]"`. The object
|
|
443
|
+
adapter `relbench_problem_from_objects(...)` accepts a task, an already-censored
|
|
444
|
+
RelBench database, and its train/validation tables; RelArena uses this path so
|
|
445
|
+
its official inner and outer database cutoffs remain authoritative.
|
|
446
|
+
|
|
447
|
+
Relational schemas do require keys. This adapter reads them from official
|
|
448
|
+
RelBench metadata; for ordinary files or database tables, provide them with
|
|
449
|
+
`Table` and `Relationship`. Self-referential/cyclic foreign keys are omitted
|
|
450
|
+
because GraphReduce currently uses an acyclic `DiGraph`; every reachable
|
|
451
|
+
acyclic foreign-key path is represented as its own node instance. Referenced
|
|
452
|
+
dimension tables reached through association/event tables are joined with
|
|
453
|
+
`reduce=False`; by default their projected feature attributes are capped at
|
|
454
|
+
eight, excluding high-cardinality free text. Pass
|
|
455
|
+
`max_enrichment_columns=None` to retain every dimension attribute.
|
|
456
|
+
|
|
457
|
+
For temporally meaningful relational evaluation, provide `Labels.timestamp`
|
|
458
|
+
and date columns on event tables. A dated parent is always filtered with
|
|
459
|
+
`parent.date <= Labels.timestamp` before feature inference and again through
|
|
460
|
+
GraphReduce's `do_filters_ops`. If the parent is a genuinely timeless entity
|
|
461
|
+
table, declare `Table(..., timeless=True)` explicitly; an omitted parent date
|
|
462
|
+
is otherwise rejected for temporal labels. Without event dates, KurveRSC
|
|
463
|
+
cannot distinguish historical features from future data.
|
|
464
|
+
|
|
465
|
+
## Local customer example
|
|
466
|
+
|
|
467
|
+
[`examples/cust_data_future_order.py`](examples/cust_data_future_order.py)
|
|
468
|
+
contains a complete run for `/usr/local/lake/cust_data`. It derives train and
|
|
469
|
+
validation labels through GraphReduce for “places an order in the following
|
|
470
|
+
365 days,” declares
|
|
471
|
+
the customer root as explicitly timeless, supplies every primary/foreign key
|
|
472
|
+
and event date, and runs the default beam-pruned configuration funnel. The example enables
|
|
473
|
+
the `kurversc` logger at `INFO`, showing every attempted configuration, its
|
|
474
|
+
score/feature count/timing, and the selected configuration.
|