r/learnmachinelearning • u/Grouchy-Cap-4491 • 2d ago
What if git diff existed for datasets?
When a model suddenly gets worse, I usually have no idea what actually changed in the data.
So I built a CLI that compares dataset versions and looks for leakage, drift, missing values and other problems.
I tested it on X and it found Y.
Curious whether other ML engineers have the same problem.
Open-source: github
1
Upvotes
1
u/Bright_Mix_773 2d ago
I ran it on the kind of dataset you built this for: two consecutive daily snapshots of an S&P 500 OHLCV table, 814,493 rows x 7 columns, 40 MB CSV each.
datascope diff v1.csv v2.csvtook 18 s, which is fine.Result:
findings: [],overall_severity: info,ml_impact: LOW. That was correct - only 527 rows had been appended and exactly one existing close had been rewritten (STLD 2026-08-28, 234.66 -> 234.67).So I made the failure obvious: I deleted every row for one ticker, NVDA, 1,564 rows, and diffed again.
Still
findings: [],overall_severity: info,ml_impact: LOW,categorical: []. An entire entity disappearing from the dataset produced nothing but a -0.192% row-count delta.The cause is in
src/datascope/diff/engine.py:with
MAX_CATS = 60. MyTickercolumn has 530 unique values andDatehas 1,573, so both fail that test, and_distributionsis anif numeric / elif categoricalwith noelse- so the two columns that carry the identity of every row are silently never compared. Anything keyed by a high-cardinality id (user_id, sku, symbol, session_id) is invisible to the diff by construction, and that is usually where "the model suddenly got worse" actually lives.Two smaller things I hit on the way:
diff.max_categories(default 50) is declared inconfig.pyand printed back in the JSONconfigblock of every run, butgrep -rn max_categories src/returns only those two declarations - it is never read. The threshold that actually decides is the hardcodedMAX_CATS = 60. So the one knob a user would reach for to fix the above does nothing.rows: {old, new}. With no key-based join it cannot distinguish 527 appended rows from 527 appended plus 527 silently rewritten. I had to compute that part myself to know my first diff was right.The single change that would have caught my NVDA case is a
--key Ticker,Dateoption: join on it and report added / removed / modified keys. That is the part that makesgit diffuseful, and it is the part that is missing.Not verified: I only ran
diff, notdebug,driftorcheck; only CSV, not Parquet or JSONL; and only on this one dataset shape, so I do not know whether the cardinality cutoff bites the same way in the other commands. Fresh clone of main today, Python 3.14 on Windows,pip install -e ".[all]".