Koziarski Lab, SickKids · seeking a Winter 2027 co-op

ZiYun (Gilbert) Wang Computer Engineering, University of Waterloo

Most of my work is about what machine learning costs to run, not only how accurate it is.

BRACE asks what it costs a wet lab to actually make the molecules a generative model proposes, and picks the subset that shares the most chemistry. ridgeline asks what it costs a GPU to serve a language model, one pass over the weights per token, and how close a hand-written engine can get to that ceiling. One is the cost of producing candidates. The other is the cost of serving models.

  • CE 3B · class of 2028
  • First author, BRACE (in preparation)
  • Second author, IEEE Trans. on AI 2026
  • Toronto / Waterloo, ON
01 · Publications

Two papers. One published, one in preparation.

Every number on this page comes from the papers' own data.

First author In preparation · 2026

BRACE: Batch Route Analysis for Cost-Efficient Synthesis

Koziarski Lab · The Hospital for Sick Children (SickKids), Toronto

The problem. A generative model can design thousands of candidate drug molecules. A wet lab can afford to synthesize a few hundred. Ranking by predicted quality and taking the top N ignores that every candidate needs its own reactions, reagents and bench time. Two molecules that share four of their five synthesis steps cost far less together than two unrelated molecules of equal predicted quality.

What BRACE does. It pairs a generative model that emits each molecule together with its synthesis route (SCENT, a reaction-template GFlowNet, and its late-stage variant SCENT-LSD) with an optimizer that charges a shared reaction only once (SPARROW). The research question is a fixed-budget comparison between two sampling strategies: does re-sampling only the last step of a proven route give a better synthesis portfolio than simply drawing more molecules?

40–47%fewer distinct reactions a chemist must run, at equal scientific value
33 / 33equal-budget head-to-head comparisons won
38,600routes from an independent retrosynthesis planner (ASKCOS) used as the control
1,274runs in the sensitivity sweep: 637 parameter cells × 2 methods
My part
The pipeline that combines the pieces into something chemists can use to pick what to make, and the entire evaluation. SCENT, SCENT-LSD and SPARROW existed before this work.

Checked my own numbers

Before circulating draft 2 I re-derived every headline figure in draft 1 and corrected six of them. The largest: a reward ratio against the ASKCOS planner computed with two different averaging methods on the two sides of the comparison. One consistent estimator over the 192 shared targets took it from 3.06× to 2.15×. All six corrections are written into the draft's change log.

GFlowNetsMixed-integer LP · PuLP/CBCRDKitGPyTorch / GAUCHEASKCOS · Docker · MongoDBPyTorch
Two candidate molecules that share their first four reactions cost five distinct reactions together, not eight. RANK BY SCORE · TAKE TOP 2 molecule A · 4 reactions molecule B · 4 reactions 8 distinct reactions SELECT FOR SHARED CHEMISTRY molecule A′ molecule B′ · same prefix 5 distinct reactions shared intermediate built once · diversify off it in parallel
The pieces
SCENT
A reaction-template GFlowNet. Emits each molecule with the route used to build it.
SCENT-LSD
Keeps a route's prefix and re-samples only the final reaction, so analogues share their upstream chemistry.
SPARROW
Route-and-selection optimizer. Keys reactions by reaction SMILES, so a shared step is charged once.
ASKCOS
MIT's retrosynthesis planner, self-hosted here. Plans routes to the same targets as the independent control.
Second of five authors Published · 2026

DSGI: Dual-Semantic Graph Spatiotemporal Inference for Industrial Prognostics

IEEE Transactions on Artificial Intelligence, 2026 · doi:10.1109/TAI.2026.3685615
Y. Wang, Z. Wang, B. Shen, B. Wan, H. Cai · Shanghai Jiao Tong University

The problem. Predict when an industrial machine will fail, from 17 sensors that disagree with each other, sample at different rates, and drop out entirely.

The method. Two separate maps of sensor relationships, which sensors move alike and which sensors cause which, feed a multi-scale spatiotemporal graph convolutional network (MS-STGCN). Before that, a quality filter vets every candidate helper sensor for the missing-data stage and refuses the unhelpful ones. So the error drops sharply where useful helpers exist, and is provably unchanged where none qualify.

80.5%lower imputation MSE where helper sensors qualify
0.0252RUL RMSE, most accurate of five methods
0.047 Mparameters, about one fifth of the runner-up
3.4×faster inference than the runner-up: 4.42 vs 15.18 ms
My role
Architect and sole implementer. I designed the method, then built the model, all four baselines, the missing-data stage, the pipeline and every experiment. 90 commits, all mine.
Fault identification
98.6–100% across four components.
PyTorchGraph neural networksLSTM · TCN baselinesPCMCI causal discoveryTensorBoard
DSGI Figure 1: three-stage framework from sensor time series through a sensor feature graph, multi-strategy imputation, and multi-scale spatiotemporal prediction
Fig. 1 · the three-stage framework
DSGI Figure 4: MS-STGCN architecture with parallel graph convolutions over correlation, causation and identity adjacency channels, feeding RUL regression and state classification heads
Fig. 4 · MS-STGCN backbone, two task heads
02 · Projects

Things I built.

Screenshots are from the running software on my own machine.

BRACE Studio

Koziarski Lab · 2026 · Python stdlib + ES2020

The lab's route viewer, rebuilt. A chemist pastes raw model output; the tool detects the format, builds the reaction graph, re-runs the optimizer live with parameters the chemist controls, and draws the selected subtree with every molecule sized by how many products depend on it.

  • Zero installation. The server is Python's standard-library ThreadingHTTPServer, so it runs on any node with Python and no pip step. The frontend is plain ES2020 with Cytoscape.js and dagre vendored locally. No build step anywhere.
  • Accepts SCENT, SCENT-LSD and ASKCOS output, plus pre-built route graphs from the old tool. Ships six sample datasets from the paper's frozen bundle, each with numbers measured by actually solving it.
  • Restoring the ancestry. Raw SCENT-LSD rows describe only the final reaction step, so parsed naively every analogue looks independent and reuse comes out at 1.00, which hides the whole point. I splice each analogue back onto its real upstream route, locating the branch point rather than assuming it. With ancestry restored the tool reproduces the paper's 3.60 reuse factor live, with one reaction serving 40 targets.
  • Two silent defects found in the old tool while porting it: its template normalizer matched 0 of 18,661 SCENT steps to a reaction family and reported no error, and it read only one reactant, dropping a component on every three-component coupling.
  • The frontend and backend were built in parallel against a written API contract, frozen before either side existed.
PythonRDKitPuLP / CBCCytoscape.jspytest
internal lab tool · no public repo
BRACE Studio results view: metric tiles for targets selected, expected reward, distinct reactions, reuse factor and solver status above a reaction graph where shared intermediates fan out to many targets results · reuse 3.67× on the shipped LSD sample
BRACE Studio parameters view with reward, starting-material cost and reaction burden weight sliders, paper presets, and a Run SPARROW button parameters · presets from the paper

Chroma Studio

2025–2026 · Python, PyTorch, FastAPI, vanilla JS

Repaint any product photo and keep every reflection. Chroma separates paint from light, finds each part, and recolours only the pigment, so the new finish sits under the same highlights, shadows and grain as the original shot.

  • Separate paint from light. Intrinsic decomposition (Careaga & Aksoy, TOG 2024) splits every pixel into albedo, shading and a residual for reflections and glare. Only the albedo is edited; the original shading relights the result.
  • Find the parts. SAM 2.1 proposes masks at the density you choose, then overlapping proposals are resolved, two-tone parts split, gaps filled with superpixels, and regions grouped into one entry per original paint colour (CIEDE2000). Merge, split and move parts in the app.
  • Pick the colours. Set each part's target with a colour picker, drag swatches onto parts, or type a look ("Hawaii sunset", "navy and gold") and get a palette from Wikimedia Commons reference imagery with Hungarian assignment as a starting point.
  • Render on the GPU. Lab-space repaint that keeps texture, recolours the old paint's bounce light, keeps chrome and glare where they were, and snaps coverage to part edges. Previews in 20–70 ms, 12 MP export under a second, a full analysis in 7–9 s on an RTX 5090.
  • FastAPI server with SSE job events, a no-build-step web app, 190 unit tests that need neither models nor network. Models load on first use and unload after two minutes idle.
SAM 2.1Intrinsic decompositionOpenCVFastAPICUDA-backed PyTorchpytest
personal project
A red Ducati 748 photograph shown in its original red, recoloured blue, and recoloured yellow, with identical lighting and reflections in all three original · flat #1f5fd6 · shift #f2b705
The same motorcycle photo split into original, albedo and shading layers original · albedo · shading
Red Ducati before, and the same photo repainted black with reflections intact repainted black
Chroma Studio web app: a drop zone for product photos and a row of sample images, with an RTX 5090 memory readout in the header the app · plain HTML + ES modules

SaxScope

2026 · JavaScript ES modules, Web Audio, Python

A saxophone tone analyzer. It listens to you play, measures your tone, diagnoses it with no reference needed, compares you against a reference player when you have one, and turns the result into words. The saxophone is the subject; the project is signal processing.

  • The DSP is hand-written and runs in the browser: FFT, YIN pitch detection, pitch tracking, harmonic analysis, attack, vibrato, modulation, noise, spectral shape, stability, loudness. No audio library.
  • Every analyzer is verified against a synthetic saxophone whose pitch contour, harmonic amplitudes, attack envelope, vibrato and noise floor are known by construction. If a number appears in the interface, there is a test asserting it is the right number. 136 of them, and the same suite runs headless under Node.
  • A technique studio with sixteen scored drills across ten techniques, and a target sound learned from recordings you tag rather than from a threshold someone picked.
  • Real systems detail: microphone capture and SharedArrayBuffer both require a secure context, so the server speaks HTTPS with a self-signed certificate, and answers a mistyped http:// with a redirect instead of a reset, so the wrong scheme is not mistaken for a dead server.
  • Python handles source separation, notation and benchmarking on the server side.
DSPWeb AudioES2020PythonHTTPS / COOP-COEP
personal project
SaxScope self-test page listing 136 passed and 0 failed, with rows such as 'YIN recovers f0 within one cent from 65 Hz to 1500 Hz' self-test · 136 passed, 0 failed
SaxScope technique studio with a list of drills grouped by technique and a panel for learning the target sound from tagged recordings studio · 16 drills, 10 techniques

ridgeline

Llama-style LLM inference engine · C++, CUDA, cuBLAS, Nsight

An LLM inference runtime written from scratch for TinyLlama-1.1B on an RTX 5090.

  • Own weight exporter, a CPU reference implementation as the correctness oracle, then a CUDA runtime with cuBLAS matrix multiplies, hand-written kernels (RMSNorm, RoPE, softmax, SwiGLU), KV-cache decoding, FP16 weights, and no allocation in the token loop.
  • Validated layer by layer against PyTorch. Benchmarking tokens/s against the card's 1.79 TB/s bandwidth ceiling and profiling with Nsight to locate the decode bottleneck.
C++CUDA CcuBLASNsight Systems / ComputeRoofline analysis
Roofline. Attainable throughput rises with arithmetic intensity until the ridge point at 117.2 FLOP per byte, then flattens. Single-stream decode sits far to the left, in the bandwidth-bound region. arithmetic intensity · FLOP / byte (log) attainable throughput (log) 1 10 100 1k ridge · 117.2 FLOP/byte compute-bound → single-stream decode one pass over 2.2 GB of weights per token 1.79 TB/s → 815 tok/s ceiling bandwidth-bound region RTX 5090 · TinyLlama-1.1B
Roofline for TinyLlama-1.1B decode on one RTX 5090.

High-Performance Matrix Library

2025 · C++, OpenMP, SIMD

A C++ linear-algebra library that reaches up to 500× the speed of a naïve triple loop, through cache-aware blocking for memory locality, SIMD vectorization (AVX2 / AVX-512 / NEON) and OpenMP multi-threading, with a CUDA path for GPU acceleration.

C++Cache blockingAVX2 / AVX-512 / NEONOpenMPCUDA
GitHub →
Four layers stacked: naive triple loop, cache blocking, SIMD intrinsics, OpenMP threads. naïve triple loopthe baseline · 1× cache-aware blockingL1/L2 tiles · unit-stride operands SIMD intrinsicsAVX2 / AVX-512 / NEON, picked at runtime OpenMP threadsthreads tuned to matrix size · up to 500×
Also

Smaller things, older things.

Voice- and text-driven CAD agent

SJTU · 2025

Generates 3D CAD models from speech or text. Whisper-tiny transcribes, Qwen3-0.6B does retrieval over FreeCAD's function set, and an LLM composes the FreeCAD code.

PythonOllamaRAGFreeCAD

Home server

self-built · 2026

Ryzen 9 9950X, 91 GB RAM, RTX 5090, NVMe on LVM, Ubuntu 24.04, with a 21 TB NAS over NFS. It runs 35 containers, including the 20-container ASKCOS retrosynthesis platform (MongoDB, RabbitMQ, Celery, more than a dozen model servers) that BRACE uses as its control planner, plus media and game servers. Reached over a Tailscale mesh, nothing exposed to the open internet.

DockerLinuxNFSTailscale

Systems programming in C

ECE 252 · Waterloo

A multi-handle curl downloader, PNG strip and CRC handling, a work queue on POSIX semaphores, and a concurrent web crawler. Course labs, done properly.

CPOSIXlibcurl

Real-time operating system

ECE 350 · Waterloo

A course RTOS built as a two-person team. We wrote it side by side at the same desk rather than splitting it in half, so both of us can explain every line.

CARM

Iris classifier in NumPy

2024 · GitHub

A deep neural network for the Iris dataset written with NumPy only, no framework: forward pass, backprop and the optimizer by hand.

PythonNumPy

Java games and tools

2024 · GitHub

A rhythm game, a 2D shooter, tic-tac-toe on a JPanel with mouse listeners, and a TV-show tracker. Early Java, before a co-op term of Java UI components at Schneider Electric.

JavaSwing
03 · Experience

Four co-op terms. Two of them research.

Jan 2026 – presentToronto, ON

Research Assistant, Machine Learning in Drug Discovery

Koziarski Lab · The Hospital for Sick Children (SickKids)

  • Lead author on BRACE (above): the pipeline and the entire evaluation.
  • Rebuilt the lab's route viewer as BRACE Studio. Chemists paste raw model output; it detects the format, builds the reaction graph, re-runs the optimizer live, and draws each molecule sized by how many products need it. Zero installation on any machine with Python.
  • Ran the full research pipeline on infrastructure I manage: a local Ubuntu 24.04 / RTX 5090 workstation and a local containerized ASKCOS deployment whose MongoDB buyables collections I build and swap with my own scripts. Also the DRAC clusters (Killarney, Nibi) over SSH with Slurm.
PyTorchGFlowNetsRDKitGPyTorchPuLPDockerMongoDBSlurm
May – Aug 2025Shanghai, China

Machine Learning Software Intern

Shanghai Jiao Tong University · School of Software

  • Built and ran everything experimental for DSGI (above): the model, four competing baselines, the ablations, the missing-data stage and the full data pipeline. Published in IEEE Transactions on Artificial Intelligence, 2026.
  • Delivered two further prototypes that grew into real projects: photorealistic image recoloring (now Chroma Studio) and a voice-driven CAD agent (Whisper + retrieval over FreeCAD).
PyTorchGraph neural networksTensorBoardSAM 2Whisper
Sep – Dec 2024Remote, ON

Web Developer Intern

Measure Tek

  • Sole developer on a rebuild of the company website in HTML, CSS and JavaScript, from implementation through testing and deployment.
  • Improved page performance and accessibility, and documented the codebase for whoever came next.
HTML / CSSJavaScript
Jan – Apr 2024Shanghai, China

Software Engineering Intern

Schneider Electric

  • Built reusable Java UI components for the HMI Designer platform: a conveyor-belt animation tool and 3D pie charts, used by clients designing interfaces for automated machinery.
  • Researched and implemented the underlying animation algorithms, and documented each component for client use.
JavaUI components
04 · Skills & education

What I work in.

Each of these is backed by something on this page.

Languages

PythonC++CUDA CCJavaJavaScript / TypeScriptBash

GPU & HPC

cuBLASNsight Systems / ComputeOpenMPSIMD (AVX2 / AVX-512 / NEON)Roofline analysisSlurm

ML & numerics

PyTorchNumPyPandasGPyTorch / GAUCHEBoTorchRDKitOpenCVWeights & Biases

Methods

TransformersGraph neural networksCNNsLSTM / TCNGFlowNetsBayesian optimizationMixed-integer LPCausal discovery

Tools

GitLinuxDockerMongoDBPuLP / CBCpytestFastAPIReactCytoscape.jsOllamaTailscale

University of Waterloo · Bachelor of Applied Science, Computer Engineering

Currently in 3B. Seeking a Winter 2027 co-op in machine learning research or GPU / systems engineering.

Sep 2023 – Apr 2028 (expected)
Waterloo, Ontario
05 · Contact

Open to research labs, GPU and systems teams, and software roles.

Winter 2027 co-op. Happy to talk about synthesis-aware generation, graph models for sensor data, or making a decode loop hit its bandwidth ceiling.

[email protected]