Hazium

I wanted to know whether public data could flag a dangerous pesticide before anyone knew to look. What I built predicts something else. This is how that happened, and what it cost.

dated facts
41,917
public sources
5
tests
415
licence
AGPL-3.0

Python 3.12, XGBoost, scikit-learn, SHAP, Pydantic. Site in Next.js.

Picking a target I could score

There is no list of substances that turned out to be dangerous. That is the thing you are trying to find out. There is a list of substances the EU withdrew: dated, public, unambiguous.

So I predicted withdrawals. It is the obvious move, I made it early, and then I stopped looking at it. Everything below follows from that.

The graph

Five public EU and Swedish sources, no shared identifier, no shared schema. I resolved them into one graph: 41,917 facts, each carrying the date it became public.

The dating is the part that took the time. A model scored at a 2015 cutoff sees what was public in 2015 and nothing else, so it cannot quietly score itself on the future.

Over that graph I trained gradient-boosted trees (XGBoost) on six dated feature groups: EFSA assessment history, hazard classifications under CLP, ECHA classification intentions, sales trajectory, independent literature signal, and graph links to substances already flagged. Scores are out of fold, folds grouped by substance.

What was knowable about Clothianidin, year by year

Clothianidin and everything within two steps of it: peer reviews, hazard classifications, regulatory acts, and the substances it shares them with. Press play. Each mark appears in the year its source document became public, and the counter is where the model ranked Clothianidin at that cutoff. It drops out when the EU withdraws it in 2019.

2009rank #402 facts · 1 link

How to read it: every mark is a substance or a hazard classification. A line between two marks means they share something. The picture fills in as each fact became public.

substanceEFSA assessmenthazard classificationregulatory eventrelated substancedrag to rotate · click a mark for detail

Click any mark to see what it is. EFSA assessments link to their published opinion.

The baseline I had not run

Approval age sat inside the model as a feature, so I had never scored it alone. On its own it reached 0.474 against the model's 0.470 across sixteen annual cutoffs, and it reproduced the published lead times to the month.

The model had learned an eligibility test. 96% of the population was never approved in the EU, so it could never be withdrawn, and one date subtraction separates those. I had not measured the evidence at all.

The reformulation

I recast it as discrete-time survival: one approved substance, one year at risk. Approval age becomes the baseline hazard and the evidence has to earn the rest. Ranking on age alone lands 3.6 times better than chance. With the evidence, 8.4. In average precision that is 0.102 to 0.242.

Scores are out of fold with folds grouped by substance, so no substance appears on both sides of a split. Shuffling whole substance histories and refitting puts that gain at p = 0.024.

A separate forward test refits on evidence up to a given year and scores against what actually happened after. Over 9 annual cutoffs the evidence beats the baseline in 7. The best of them is 2019, where the top 50 holds 11 real withdrawals to the baseline's 4.

The two it loses are both fitted before 2016. Subsampling puts that down to regulatory eras not transferring rather than to a shortage of events: the gain holds down to four training events, and 75 of the 102 events sit in the 2017 to 2021 renewal wave.

What it cost

Sweden opened 6 substances for reevaluation in November 2025 because they degrade into TFA, a persistent PFAS compound that reaches groundwater. Against that cohort the model ranks 0 of 6 in its top 100, where chance places 2.3.

That is not a tuning problem. A degradation pathway leaves no trace in an approval file, a hazard classification or a sales table, so there is nothing in the regulatory record to learn it from. A molecular formula has it. One structural test over PubChem returns 26 of 242 approved substances and contains all 6.

Withdrawal is a committee decision. Harm is a property of the molecule. I picked the target I could score, and got a model that predicts paperwork.

What’s here

A reproducible pipeline with 415 tests. Both benchmark versions are published together: the one a date subtraction could answer, and the one that replaced it.

On this site

Elsewhere