Schema — supervised (classification / regression)¶
Tables an experiment of type=supervised (or external) can publish. The
profile discriminator is binary | multiclass | regression. All names below
are suffixes of the canonical id; query the data-kb name (RULE 1), and
confirm presence with the live catalog (RULE 6).
Contents¶
- Fact:
*__predictions - Dimension:
*__rules(label rules, Train and Test measures) - Bridge:
*__rules_fired - Dimension:
*__archetypes - Example queries
Fact — *__predictions (PK row_index)¶
| profile | columns |
|---|---|
| common | row_index (position), the input's declared key column(s) under their own names (catalog role key), row_role? (train / validation_holdout / outer_test / excluded — absent when the scored rows are not the fit's own dataset), archetype_id? (FK → archetypes) |
| binary | predicted_proba (P of positive class), predicted_class (0/1), predicted_class_name |
| multiclass | predicted_class (index), predicted_class_name, proba_<class> — dynamic wide columns, one per class; exact names only in the live catalog |
| regression | predicted, predicted_lower_<level>? / predicted_upper_<level>? — one calibrated interval pair per configured level (predicted_lower_80, predicted_upper_95, …; exact coverage under a random split, approximate under grouped / temporal), residual? (actual − predicted, when y available) |
Per-row errors and band coverage are honest only on held-out rows: filter
row_role = 'outer_test'.
Dimension — *__rules (PK rule_id; classification only, when rules mined)¶
rule_id, engine, text (human-readable predicate), then the Train
measures — on the rows the rules were found on, so optimistic: support (true
positives / all rows — not the share of rows covered), precision, lift?
(precision / base rate) — and the Test measures on held-out rows neither the
model nor the rule search saw: support_holdout?, precision_holdout?,
lift_holdout?, n_covered_holdout?, and holds_up? (holds_up /
does_not_hold_up / too_few_rows; null without held-out rows), then
class_key?. These are label rules — patterns in the labels found through
the model's trees during MLI — the answer to "which rules apply / fire for
predicted X?" Join via *__rules_fired (below). Quote the Test measures and
prefer holds_up = 'holds_up'; call the Train measures in-sample. A separate,
directly-applyable independent "Business Rules" model may also exist as an MLI
artifact (not a SQL table) — see explainability
(get_capabilities.has_business_rules).
Bridge — *__rules_fired (composite PK (row_index, rule_id))¶
row_index (FK → predictions), rule_id (FK → rules). Many-to-many: which rules
fired on which rows.
Dimension — *__archetypes (PK archetype_id; present with MLI archetypes)¶
archetype_id, label, n_members, defining_features (short text), class_key?.
Standard joins¶
- predictions ↔ input: the declared key column(s) (RULE 3).
- predictions ↔ rules: predictions →
rules_fired(row_index) →rules(rule_id). - predictions ↔ archetypes:
archetype_id.
Example queries¶
Placeholders <input>, <predictions>, <rules>, <rules_fired> are the
data-kb names for those tables.
Placeholder <key> is the input's declared key column (catalog role key).
Cohort profile of predicted-positive rows:
SELECT s.region, COUNT(*) AS n, AVG(s.income) AS avg_income
FROM "<input>" s
JOIN "<predictions>" p USING (<key>)
WHERE p.predicted_class = 1
GROUP BY s.region ORDER BY n DESC;
Top rules by test lift among positives (rules that hold up on held-out rows):
SELECT r.text, r.engine, COUNT(*) AS fired,
r.lift_holdout, r.precision_holdout, r.lift AS lift_train
FROM "<predictions>" p
JOIN "<rules_fired>" b USING (row_index)
JOIN "<rules>" r USING (rule_id)
WHERE p.predicted_class = 1 AND r.holds_up = 'holds_up'
GROUP BY r.text, r.engine, r.lift_holdout, r.precision_holdout, r.lift
ORDER BY r.lift_holdout DESC, fired DESC LIMIT 20;
Threshold what-if (no re-scoring):
SELECT CASE WHEN predicted_proba >= 0.7 THEN 'flag' ELSE 'pass' END AS bucket,
COUNT(*) AS n
FROM "<predictions>" GROUP BY 1;
Regression error by segment, on the held-out test rows:
SELECT s.region, AVG(ABS(p.residual)) AS mae
FROM "<input>" s JOIN "<predictions>" p USING (<key>)
WHERE p.row_role = 'outer_test'
GROUP BY s.region ORDER BY mae DESC;
Regression interval coverage and width per level on the test rows (check each level's columns in the catalog first):
SELECT AVG(CASE WHEN p.predicted + p.residual BETWEEN p.predicted_lower_80
AND p.predicted_upper_80
THEN 1 ELSE 0 END) AS coverage_80,
AVG(p.predicted_upper_80 - p.predicted_lower_80) AS width_80
FROM "<predictions>" p WHERE p.row_role = 'outer_test';
Multiclass: read the actual proba_<class> column names from the catalog — do
not hardcode proba_1.