What a 200-Line Keras Tutorial Left Out
For my grad-school capstone, a partner and I set out to classify autism from brain MRIs with a 3D convolutional neural network. We started where everyone starts — from a tutorial. A clean, well-known Keras example that trains a 3D CNN on CT scans in about two hundred lines: it downloads a tidy, pre-split dataset, builds the model, trains, and prints a number. Start to finish, it runs in a few minutes.
Our final model reached 61% test accuracy. Getting there took months, three preprocessing pipelines, and roughly 25 hours of GPU time. Almost all of that work happened outside the model code shown in the tutorial.
(Credit up front: this was a two-person capstone, the work was shared, and the starting notebook was a public Keras example, not ours. What follows is what I took from it.)
The one-line download became an ETL job
The tutorial’s data step is a single call: download a zip, already split into train and validation, volumes already uniform. That one line is the entire dataset problem, solved for you, invisibly.
Real data does not arrive like that. Ours came from a public research archive — an open bucket with per-site folders, paginated listings, inconsistent naming. Getting it meant pulling site by site with pattern-matching over the listings, reorganizing and renaming files into something uniform, and then — the part no tutorial mentions — recovering the labels. The labels lived in separate phenotype tables, one per collection site, with mismatched column names and even different text encodings, and you had to join scans to labels across all of that before you had anything a model could learn from.
None of this changed the network architecture, but the model could not be trained without it. Before doing machine-learning work, we had to build a repeatable ETL process across the participating sites.
Resizing the scans required three representations
In the tutorial, every scan is the same size, so resizing is a throwaway line. In real data every scan was a different shape, and “what size do I make them” became a decision I had to actually study — I ended up histogramming the distribution of volume dimensions across the whole dataset just to choose a target, because there was no obvious right answer.
We didn’t even settle on one. We shipped three representations and compared them: a 128×128×128 cube, a differently-cropped version, and — reaching for a completely different angle — a “video” of a handful of 2D slices pulled from each volume. The 2D-versus-3D-versus-slice-stack tradeoff that papers discuss in the abstract was, for us, three preprocessing pipelines we built and ran because we genuinely couldn’t tell in advance which framing the signal would survive.
The dataset would not fit in RAM
A few thousand 3D volumes is small as a number of examples and enormous as bytes. It does not fit in memory. The tutorial never has to care; ours did, from day one.
We preprocessed each volume once, wrote the arrays to disk, and trained through a custom generator that loaded only a small batch at a time. The stock image helpers did not handle our file types, so the project needed its own loader.
The workstation spent about 25 hours training
A fork runs through the whole project: the same notebooks exist twice, once for Google Colab (mount Drive, stream the data in) and once for a local workstation with a real GPU. The workstation trained at roughly fifteen minutes an epoch and something like 25 hours total across all the experiments. That’s the actual, unhidden cost of “just train a 3D CNN a few different ways” — a number the tutorial’s two-minute run will never prepare you for.
The model reached 61% on the test set
Here’s where it landed: about 64% on validation, 61% on test, against a majority-class baseline of roughly 52%. Published models on richer brain-imaging data reach 79–95%. Ours misclassified the disorder group more often than the control group. By the standards of a demo, that’s a disappointing result.
Structural MRI alone is a difficult signal for this task. The pooled sites used different scanners, adding variation unrelated to the target, and a few thousand examples is small for a 3D CNN. The 61% result was only a modest gain over baseline, but it was consistent with those constraints. A result near 95% would have sent us looking for leakage before celebrating it.
The tutorial covered about 5% of the project
The tutorial covered the recognizable modelling steps. The rest of the project was data retrieval, label recovery, representation choices, memory management, custom loading, compute time, and evaluation against a baseline. That work is why the demo is not the system, especially when the demo begins with a dataset whose difficult decisions have already been made.
More on Applied experiments DuckLake on One Machine →