Repository navigation
Whole-network finetuning of the 3D models in the browser - #143
Merged
Merged
Conversation
Marwan Zouinkhi's export of 2026-10-17 (cellmap/onnx-web-models 3331842ec2) gives all six 3D folders (setup_53, 54, 55, 56, 61, 67) whole-network training: an NDHWC training graph with params as the PyTorch state_dict, torch_params.json to rebuild them from the served .onnx, weight_map.json to write them back, and a reference runtime. - cellmap-tfjs-train.ts: his runtime of 3331842ec2 ported to TypeScript, the 2D path unchanged: buildNet on an NDHWC graph, readTorchParams, toOnnxWeights and a checked interpreter for the structured transforms. - net3d.ts: the 3D network trained within a browser's GPU memory. His plain autodiff keeps every intermediate (about 8 GB at 124³, nothing larger fits 11 GB) and, as written, its backward pass exceeds WebGPU's dispatch limit from 108³. Here every op's gradient is written out, conv+BatchNorm+ReLU and InstanceNorm(+add)(+ReLU) are fused, a convolution's gradients are matrix products, the backward recomputes segments from checkpoints, the GPU is synced and TF.js's buffer pool emptied between segments, and Adam is applied only when the WebGPU error scopes report nothing, so running out of memory throws GpuMemoryError with the weights unchanged. On an RTX 2080 Ti, a step with the starting network's forward pass: setup_53 124³ 2.8 s / 2.2 GB, 172³ 8.2 s / 5.3 GB; setup_54 124³ 4.0 s / 4.0 GB, 172³ 11.9 s / 9.9 GB. Logits match onnxruntime-web to 2.3e-5 (setup_53) and PyTorch to 3e-5. - graph.ts: NDHWC graphs, and block sides for N³ (92 + 8k, context 88). - tiles.ts, run-full.ts: cubes around the paint, the raw block around each, 3D targets (affinities with a z neighbour), one block a step, the head's loss settings, distillation to the starting network run on the same block (forwardAsync), augmentation flipping z, y and x and turning in y–x, and the trained weights written back through weight_map.json. - modes.ts offers it for a 3D model whose manifest names torch_params and a weight map (lifting 74bbd72's 2D-only guard); the Finetune tab's Tile Size becomes Block Size (124³ by default, up to 172³) with the measured cost, and Batch Size stays 1. Co-authored-by: Marwan Zouinkhi <zouinkhi.marwan@gmail.com>
…at augmentation costs A 3D run is epochs × blocks steps and wants 60 to 150 of them, so paint in one or two blocks needed more than the field's 50: Number of Epochs now goes to 500, and its hint in the browser says how many steps to aim for. The Augmentation box and its advice said it keeps the network from learning its tiles by heart; on jrc_jurkat-1 with setup_55 and one painted nucleus it held the loss at guessing through 500 steps, so they now say it slows learning several times over and suits paint on several objects. The docs give the test's numbers and how to read the loss.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #142 (
browser-full-augment), itself on #137. Once those merge, this PR's base becomes main.The browser can now train the whole network of the 3D models,
setup_53,setup_54,setup_55,setup_56,setup_61andsetup_67, not only their last layer. This builds on the export Marwan Zouinkhi added tocellmap/onnx-web-modelson 2026-10-17 (3331842ec2): a 3D training graph per folder,torch_params.jsonandweight_map.jsonto read the weights out of the served.onnxand write them back, and a reference runtime.Who sees a change
Memory and speed
Marwan's runtime trains with TensorFlow.js's own gradients. Those keep every intermediate: about 8 GB at 124³, and nothing larger fits an 11 GB GPU. As written, its backward pass also exceeds WebGPU's dispatch limit from 108³.
net3d.tsbuilds the same network from the same graph and weights, but trains it lean:One step with the starting network's forward pass, on an RTX 2080 Ti (TF.js 4.22.0, WebGPU, Chromium):
Out of memory raises nothing in TensorFlow.js; it just corrupts the step. Each step therefore runs inside WebGPU error scopes, and Adam's update is applied only when they report nothing. Tested: setup_54 at 196³ threw cleanly, none of its weights changed, and 124³ trained normally afterwards.
Code
full/cellmap-tfjs-train.ts: Marwan's runtime at 3331842ec2, ported to TypeScript; the 2D path is unchanged. Adds the 3DbuildNet,readTorchParams,toOnnxWeights, and a checked interpreter for the structured transforms.full/net3d.ts(new): the lean 3D network behindbuildNet3d, withstep,forward/forwardAsyncandexportWeights.full/graph.ts: NDHWC graphs and N³ block sides (92 + 8k, context 88).full/tiles.ts,full/run-full.ts: 3D blocks around the paint, the raw around each, 3D targets, the 3D run, and write-back throughweight_map.json.modes.ts: offers the whole network for a 3D model whose manifest namestorch_paramsand a weight map. This lifts Batch: PRs #126–#141 in one merge #137's 2D-only guard (74bbd72).browser.rst) and CHANGELOG.Checks
npm run checkin web/: typecheck, 1,558 tests passed, build.test_importing_leaves_the_process_alone[blockwise-logging]failing, as on main in that environment.readTorchParams/toOnnxWeightsreproduce the served bytes exactly. An opt-in live test round-trips setup_53's real fp32 and fp16 files byte for byte.Not included