Skip to selected work
Ljubljana, SI Open to senior ML roles

Catching
things
that hide

I'm Mark Žakelj, a machine learning engineer. I build production systems that pick bots, fraud and abuse out of live data, then act on them before a human has to look.

Selected work

Four things worth reading about
01

Finding the ones
who hide

Sportradar · Machine Learning Engineer · Feb 2025 → now

A sportsbook has customers quietly gaming it. I built the system that catches them while they are still doing it, not in a report the next morning.

FLAGGED · AUTO-LIMITED EVENTS ARRIVING

The stream

Apache Flink over Kafka, written in Java, joining live event sources and scoring customers as their events land. Thousands of accounts get flagged and auto-limited; millions of customers are profiled every day.

The hard part was labels

Nobody hands you a clean list of who cheated. I used a positive-unlabeled setup, semi-supervised pseudo-labeling, and Bayesian shrinkage to weight every label by how much I actually believed it.

Also bot detection and sharp-customer detection as daily batch models, replacing systems that cried wolf far too often. I own each one end to end: data, features, training, deployment, monitoring.

02

A fleet nobody
ever visits

Monitor · Freelance · 2023 → now

Screens in shops across Europe, each one a Raspberry Pi that no engineer will ever stand in front of. The video is the easy half. The interesting half is what the system does when a device goes quiet.

Server
Multi-tenant FastAPI on PostgreSQL, Redis and S3, with a React console for the people running the floor.
Contract
Devices poll for commands and acknowledge results, and hold an SSE channel open for near-instant pushes.
Absence
410 means decommissioned, so wipe local state. 401 means stop but keep it. 429 means back off and wait.
Ship
GitHub Actions CI, Docker, Ansible-provisioned golden images, around 1,500 backend tests.
OPERATOR CONSOLE postgres · redis · s3 PLAYER retail floor PLAYER retail floor PLAYER retail floor POLL + ACK SSE PUSH × fleet 410 → WIPE STATE 401 → STOP, KEEP IT 429 → BACK OFF
A char 01 02 03 B char 01 02 03
03

Same face,
every frame

KatalistAI · ML Engineer · 2023 → 2024

I built the generation algorithm behind the product: face detection, image embeddings and Stable Diffusion with IP-Adapters, chained so several characters stay recognisably themselves from one image to the next.

Underneath it I designed the Kubernetes serving layer, with custom autoscaling, load balancing and caching. Latency dropped 10% while GPU spend stayed flat. I owned the CI/CD pipelines and container builds too.

github.com/MarkZakelj/ConsistentFacesSD →

04

Labels for free

My favourite small thing. When a pose detector drops joints, the skeleton itself tells you roughly where they should have been, so the training signal is already sitting in the data. Self-supervised, no annotation budget, and it turned out to be the same instinct I now use on fraud data where honest labels barely exist.

github.com/MarkZakelj/openpose-extrapolation →

Inks on hand

Languages
Python · Java · SQL · TypeScript
Streams
Apache Flink · Kafka
Models
XGBoost · LightGBM · PyTorch
Stores
PostgreSQL · Redis · S3
Ship it
Docker · Kubernetes · Ansible · GitHub Actions
Track it
MLflow · DVC

Say hello

If you are building something that has to be right while it is still running, I would like to hear about it.

markzakelj@gmail.com →

MSc in Data Science, University of Ljubljana. First prize at the 2022 Data Science Project Competition, for customer segmentation built with Triglav.

Set in Archivo Black and Courier Prime.
Printed in two inks that never quite line up,
which is rather the point.
Built with Astro. No trackers, no cookie banner.