● model training console · 05 // deployed systems NEW

KAMI

Your Machine-Learning Tutor

Knowledge-Aware Model Interpreter

A Python library that builds a model from your data — then explains what it found, in plain English. Built for the rest of us: honest about what it knows, and patient enough to teach you why. As of 0.10.0 it does neural networks too — and reads the PyTorch you wrote.

// the magic moment — three lines, one plain-English verdict

It answers the question you actually have.

You hand it a messy spreadsheet, type three lines, and kami tells you what your data can predict, how good the model is, how much to trust it, and exactly what to do next. No metrics to google. No charts to decode.

load · clean · learn

from ablevlabs import kami

df = kami.load("houses.csv")        # read it
df = kami.clean(df)                  # tidy it
result = kami.train(df, target="price")  # learn from it
kami ▸ output
   ======================================================================
   WHAT KAMI FOUND
   ======================================================================
   Question      Can 'price' be predicted from the other columns?
   Answer        Yes - and quite well.

   How good      R2 = 0.97. In plain terms, the model explains about 97% of
                 why 'price' changes from one row to the next.
   Typical miss  the model is usually off by about 17324 (e.g. predicted
                 159179, actual 173500).
   Verdict       [*****] Excellent
   Confidence    Moderate - 60 unseen test rows.

   What we learned:
     - 'size_sqft' and 'age_years' look most related to 'price' (related to,
       not necessarily the cause).
     - There's real signal here - your columns do help predict 'price'.

   Do next       kami.feature_importance(result)
   ======================================================================

// what it is

Most ML tools assume you already know ML. Kami doesn't.

Kami does the modelling for you — it figures out whether you're predicting a number or a category, cleans the data, trains a solid model the right way, and scores it on data it has never seen. Then it turns the result into a sentence you can actually understand.

It favours clear explanations and safe defaults over raw speed and endless knobs. It's the friend who teaches you to ride the bike — and when you outgrow it, the model it hands you is plain scikit-learn, so you walk straight into the big leagues with it already in hand.

› regression & classification › built for beginners › real, messy datasets › fast prototyping › learning the craft

// it doesn't just model — it teaches

A tutor built into the library.

Stuck on a concept? Ask about any model and get a story, not a textbook. Hit a word you don't know? Kami translates the jargon. Every number comes with a sentence — and every sentence is one you can follow.

kami.learn("RandomForest")

kami.learn("RandomForest")
kami academy
======================================================================
KAMI ACADEMY  -  RANDOM FOREST
======================================================================
Difficulty:   Beginner   (Kami's default model)

THE IDEA
   Ask one person to guess and they might be biased. Ask a hundred different
   people and average their guesses, and the errors tend to cancel out. A
   Random Forest grows hundreds of decision trees, each on a random slice of
   your rows and columns, then averages their votes. The crowd beats the
   individual.

GOOD FIT WHEN
   + Almost any table
   + Mixed data and missing values
   + You want strong results with no tuning

MAYBE NOT WHEN
   - You need maximum speed
   - You need a model you can read as one simple rule
======================================================================

kami.translate("overfitting")

kami.translate("overfitting")
kami ▸ plain english
'Overfitting' in plain English:
   The model memorised the training data instead of learning the general
   pattern - so it looks great on data it has seen, but does poorly on new data.

Why it matters:
   It gives false confidence: it will likely disappoint on the data you
   actually care about. Cross-validation helps you catch it.

// charts that explain themselves

Every chart comes with a caption.

Kami draws the charts you'd expect — histograms, scatter plots, bar and pie charts, a correlation heatmap — but it never just hands you a picture and walks away. Each one prints a plain-English note telling you what you're looking at and what to notice. And if you're not sure which chart even fits your data, kami.suggest_charts(df) tells you, with copy-ready code.

kami ▸ matplotlib
A histogram of price and a scatter plot of size versus price, both drawn by kami

…and the caption Kami prints with each one — so you read the picture instead of guessing at it:

kami ▸ what you're looking at
kami.hist(df, 'price')
What you're looking at: how often each range of 'price' shows up - tall
   bars are common values, and the overall spread tells you how varied 'price'
   is.
   Your data: 'price' ranges from 29000 to 428800, with most values near
   227750.

kami.scatter(df, 'size_sqft', 'price')
What you're looking at: each dot is one row, placed by its 'size_sqft'
   (left-right) and 'price' (up-down). A clear upward or downward drift means
   they move together; a shapeless cloud means little relationship.
   Your data: 'size_sqft' and 'price' show a strong positive relationship
   (correlation +0.96).

not sure which chart? ask kami

kami.suggest_charts(df)
kami ▸ chart ideas
Kami: Chart ideas for your data (3 numeric, 1 category column(s)):

   See how ONE column is spread out:
     kami.hist(df, 'size_sqft')        # the shape of a number column
     kami.bar(df, 'neighborhood')         # how many rows per category
     kami.pie(df, 'neighborhood')         # the same, as shares of the whole

   See how columns RELATE to each other:
     kami.scatter(df, 'size_sqft', 'bedrooms')   # do two numbers move together?
     kami.heatmap(df)                  # every numeric pair at once

   A quick overview of everything at once:
     kami.quickplot(df)

// guardrails

It won't let you fool yourself.

Quietly, automatically, on every run, kami watches for the traps that burn beginners (and plenty of pros). When something looks too good to be true, it says so before you stake anything on it.

Data leakageA column that secretly gives away the answer? Flagged before you trust a fantasy.
ID columnsIt won't let the model "memorise" row numbers and call it learning.
Fake-perfect scores100% accuracy on six test rows is Low confidence, not a win.
Duplicate rowsCopies land in both the training and test halves, so the model gets graded on rows it memorised. Kami counts them and says the score is too generous.
Entangled columnsWhen two columns carry the same information the model splits the credit arbitrarily — so kami says the ranking is unstable, not wrong.
Meaningless rankingsIt refuses to rank raw coefficients. One might be "per dollar" and the next "per year" — a bigger number would only mean smaller units.
Wrong-scale featuresScales the columns for models that measure distance, and for penalised models where scale decides which coefficient gets punished.
Wrong-scale answersSVR and neural nets assume the answer is a small number. Kami scales the target for them, so a house price in the hundred-thousands doesn't look like a broken model.
Scores with no yardstickEvery regression result is shown next to the error you'd get by always guessing the average — including "no better than guessing" when that's the truth.
Messy realityCurrency symbols, commas, percent signs, mixed dates, blanks — cleaned without being asked.
Unseen test dataAlways scored on rows the model never saw, so the number is honest.

// 0.10.0 — neural networks — PyTorch, without the cliff

It keeps teaching after you outgrow it.

Most teaching wrappers help right up to the moment you write your own training loop, and then they stop. Kami starts there. The deep half has three rungs, and it is built to get weaker on purpose as you get stronger.

RUNG 01

Kami does all of it

kami.deep_train(df, target="churn") prepares the columns, designs a network from the shape of your data, trains with early stopping, and scores on rows it never saw.

RUNG 02

Kami shows its work

result.show_code() prints the exact, runnable PyTorch that just executed — module, loop, optimizer. Copy it into a cell and start changing things.

RUNG 03

Kami reads code you wrote

kami.deep_check(model, ...) takes your own model and your own training loop, and names the traps before they cost you an afternoon.

Rung three is the whole argument for building this. The errors that crash are the easy ones. The expensive ones run fine, drop your loss a little, and leave you with a model that is quietly worse than it should be — and nothing in PyTorch says a word.

kami.deep_check ▸ output
   --- CODE CHECK ---

   Kami read your code. 3 things will bite you.

   [!] Your last layer is Softmax and your loss is CrossEntropyLoss.
       CrossEntropyLoss applies softmax itself, so yours runs twice.
       Fix: delete the nn.Softmax line and let the loss do it.

   [!] optimizer.zero_grad() is never called in your loop. PyTorch ADDS
       each batch's gradients to the last batch's instead of replacing
       them. Fix: call optimizer.zero_grad() at the top of the batch loop.

   [!] model.train() and model.eval() are never called, and this model
       contains Dropout. That layer behaves differently in the two modes.
       Fix: model.train() before training, model.eval() before validation.

   The rest looked fine: shapes line up end to end, model and data agree
   on device and number type.

Kami reads plain functions, class methods and closures. It never claims to have checked something it could not read — whatever it did not look at is listed under Not checked.

Photos, and the trap nobody warns you about. Hand deep_look() a folder instead of a table and it reads your classes the way torchvision expects them. Then it does the thing torchvision will not.

kami.deep_look(folder=…) ▸ output
   --- BEFORE YOU TRAIN ---

   Classes:  2
   Images:   120

      cats      60  ########################
      dogs      60  ########################

   [!] 39 of the 120 images Kami looked at are near-copies of another
       one, in 1 group(s). The biggest group has 40 almost-identical
       images in it.

       If copies of the same shot end up on both sides of the split, the
       model is scored on pictures it has effectively already trained on.
       The number comes back wonderful and means nothing.

   Genuinely different pictures, once near-copies are counted once:
      cats      60 of 60
      dogs      21 of 60

That last block is the point. A class can be sixty files and twenty-one pictures, and a random split will happily put copies of the same dog in the training half and in the test half. Kami fingerprints every image, groups the near-copies, counts your classes in pictures rather than in files, and splits so every copy of a shot stays on one side. On the folder above, a random split left 264 near-duplicate pairs straddling train and test. The grouped split left zero.

Honest scores, not flattering onesScaling, filling and encoding are learned from the training rows only, after the split. Doing it before is textbook data leakage, and Kami prints the reason on screen so you learn the habit instead of inheriting it.
It won't let you pick by test scoreTrain five times on the same table and Kami points out that you have been choosing with the rows that were supposed to be held back. No other library warns about this.
Its own defaults are something to beatThe architecture rule won outright on one of four real datasets, and Kami says so out loud. deep_tune() sweeps one setting at a time and ranks on validation loss.
Thresholds are measured, not assumedThree numbers first picked by convention turned out wrong when they were swept: the skew threshold, the network width, and the image duplicate distance. All three now come from a measurement, and the measurement is in the source.
Errors translated before they crashShape, device and dtype mismatches are roughly half of all beginner PyTorch errors. deep_trace() prints the shape at every layer, which is the cure for the commonest one.
PyTorch stays optionalImporting kami never loads torch. Each deep function asks for it only when you actually call that function, and says how to install it if it is missing.

297 tests, lint clean. In: tables, regression and classification, feedforward networks, eleven lessons, save and load, importance, honest comparison — and, for folders of images, reading the folder, near-duplicate detection and a leak-free grouped split. Not yet: training on images, text and transformers, Lightning. Each of those gets its own release, and the three rungs above are the structure they plug into.

// 0.9.0 — statistical corrections

Some numbers changed. The new ones are the honest ones.

This release fixes results that were being computed correctly and reported misleadingly. If a score or a ranking moves after you upgrade, that's the point — and it's worth knowing which ones, because one of them now raises an error where it used to print a table.

feature_importance() refuses plain LinearRegressionIt raises instead of ranking. On unscaled data a coefficient's size depends on its column's units, so ranking them measures your choice of units. The error points at model='Ridge' (kami standardizes it) or a tree model.
Ridge and Lasso tune their own penaltysklearn's default alpha=1.0 is a placeholder. On a benchmark where the answer was literally a straight line, a default-alpha Lasso scored 0.799 while LinearRegression scored 0.998 — the penalty was eating the signal. Alpha is now chosen by cross-validation.
SVR and MLP scale the targetOn a dataset where every other model scored 0.98, these two scored −0.008 and −29.0. That was never their performance — it was a units problem being reported as a bad model.
Scores move on messy dataDatasets with duplicate rows or entangled columns now come with warnings attached. The numbers didn't get worse; the reporting got honest.

Verified against a benchmark of eleven datasets whose answers are known by construction — a straight line, pure noise, a step function, XOR, a 95/5 imbalance and six others. The pure noise case is the one that matters: with no relationship in the data at all, every model must score at or below zero. Anything claiming otherwise has found a leak, not a pattern. 266 tests, including a reproducibility check for every one of the nineteen models.

One thing deliberately not changed: median imputation happens before cross-validation, which is a real methodological error. It was measured across three dataset sizes and four missingness levels — the largest gap was 0.015 R² and most were under 0.003. Fixing it is a breaking change to the result object for no measurable benefit, so it waits. Stated here because the mechanism sounds alarming and the magnitude isn't.

// how it works

Three steps. Plain English out.

01

Load

Point kami at a CSV or a DataFrame. It reads it and shows you what's inside.

02

Clean

Text-numbers, dates, missing values, rare categories — handled automatically.

03

Train

It picks a model, scores it on unseen data, and explains the result out loud.

You get a real result object back. result.raw is the underlying scikit-learn model, and result.predict(new_row) makes predictions on new data — so kami is a starting point, never a dead end.

// cheat sheet

Everything you need to use it.

install / upgrade & import

# install or upgrade to the latest
pip install -U ablevlabs

from ablevlabs import kami

train a model — and get the explanation

df = kami.load("houses.csv")
df = kami.clean(df)
result = kami.train(df, target="price")   # trains + explains
champ  = kami.bakeoff(df, target="price")  # races models, ranks them, names a winner

predict on new data

new_row = result.example_row()     # a filled-in template to edit
new_row["size_sqft"] = 2200
kami.predict(result, new_row)

understand & visualise

kami.feature_importance(result)   # what mattered, in plain words
kami.plot_predictions(result)     # see how close it got
kami.suggest_charts(df)           # which charts fit your data

What feature_importance() measures depends on the model, because one method doesn't fit all. Tree models report the share of decisions each column drives. Scaled linear models (Ridge, Lasso, LogisticRegression) report standardized coefficients — comparable, and signed, so you get direction too. Plain LinearRegression is refused, and KNN and SVR have no per-column weights at all.

learn the craft

kami.learn("GradientBoosting")   # a lesson on any model
kami.learn("TabPFN")             # what's new in tabular ML right now
kami.translate("R2")             # any jargon term, decoded
kami.roadmap()                  # the whole workflow, step by step

neural networks — the deep half

pip install torch                       # only needed for the deep functions

kami.deep_info()                       # the whole map, in the terminal
kami.deep_look(df, target="churn")      # should this be a network at all?
kami.deep_look(folder="photos/")        # same verb, a folder of images

result = kami.deep_train(df, target="churn")
result.show_code()                     # the PyTorch that just ran
result.importance()                    # which columns it leaned on

kami.deep_check(my_model, df, target="churn",   # now check code YOU wrote
                loss_fn=loss_fn, loop=my_loop)
kami.deep_learn("transfer learning")     # eleven lessons, each naming its trap
train() argumentwhat it does
targetThe column you want to predict. Required.
explain'silent', 'guide' (default), or 'teacher' — how much kami talks.
validate'holdout' (default) or 'cross' for cross-validation.
missing'fill' (default) or 'drop' for rows with gaps.
ignoreA list of columns to leave out of the model.
bakeoff() argumentwhat it does
targetThe column you want to predict. Required.
rank_byWhich metric decides the winner. 'auto' (default) uses accuracy for classification and R² for regression — but switches to 'f1' by itself when your categories are lopsided, and tells you why. Or name one: 'accuracy', 'precision', 'recall', 'f1', 'roc_auc', 'r2', 'mae', 'rmse'.
models'default' races the full roster. Pass a list of model names to race just those. On big tables the default roster swaps in the faster histogram booster for you.
medalsTrue (default) prints the podium above the metric table.
explainSame as train() — 'silent', 'guide' (default), or 'teacher'.
missing / ignoreSame meaning as in train(), applied to every model in the race.

// start here

Bring a spreadsheet. Kami does the rest.

One line to install, three to your first explained model. Kami meets you exactly where you are — and grows with you when you're ready for more.