Skip to content

Use the Bijectors batched RQS for nsf and drop MonotonicSplines - #63

Open
shravanngoswamii wants to merge 23 commits into
mainfrom
sg/nsf-bijectors-rqs
Open

Use the Bijectors batched RQS for nsf and drop MonotonicSplines#63
shravanngoswamii wants to merge 23 commits into
mainfrom
sg/nsf-bijectors-rqs

Conversation

@shravanngoswamii

@shravanngoswamii shravanngoswamii commented Jul 18, 2026

Copy link
Copy Markdown
Member

nsf now builds its rational quadratic splines with a batched implementation in this package (src/flows/rqs.jl) instead of MonotonicSplines, which is dropped as a dependency. The spline is written with whole-array operations, so it runs on the GPU and every AD backend differentiates it without hand-written rules. A small ReverseDiff extension strips tracking from the bin search and the root sign mask, which are piecewise constant and carry no gradient.

The implementation was first proposed for Bijectors (TuringLang/Bijectors.jl#485) and moved here instead: it assumes a (D, N) batch layout, which Bijectors deliberately does not commit to (#214, #370), while the coupling layers here already use that convention.

Behaviour change: MonotonicSplines ignored B when scaling the knots and always scaled into (-5, 5]. Flows built with any B other than 5 now define a different transform. Whether the nsf default of B = 30 with K = 10 is still sensible is worth a maintainer decision.

The parameterisation follows the reference implementations: a minimum bin fraction and minimum derivative of 1e-3, boundary knots pinned exactly to -B and B, and the cancellation-free form of the quadratic root for either sign of b.

Tests: test/rqs.jl checks shapes, the parameter layout, monotone knots, the identity tails, round trips, agreement with the single-sample spline in Bijectors, and gradients against ForwardDiff under Zygote, ReverseDiff, Mooncake (reverse and forward), and Enzyme (Julia 1.11+, where it does not hit its LLVM verification bug), over interior inputs, mixed in-range and out-of-range batches, and parameters extreme enough to saturate the floors. test/ext/CUDA/cuda.jl checks device execution without scalar indexing, host agreement, and the Zygote gradient on device.

The neural spline coupling now calls Bijectors.rqs_params_from_raw, rqs_forward, and
rqs_inverse, which are written with whole-array operations. nsf now trains under every
supported AD backend and runs on the GPU, so the Zygote-only restriction is gone.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts:
#	Project.toml
#	test/Project.toml
@github-actions

Copy link
Copy Markdown
Contributor

NormalizingFlows.jl documentation for PR #63 is available at:
https://TuringLang.github.io/NormalizingFlows.jl/previews/PR63/

shravanngoswamii and others added 21 commits July 19, 2026 11:20
The neural spline demo needs the batched RQS, which is not yet released, so the example
environment needs the same source pin as the main project.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…elow 0.13.189

Julia 1.10 ignores the [sources] pin, so the batched RQS was missing there. Enzyme
0.13.189 fails with an LLVM canonicalization error on 1.10; 0.13.188 is fine.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…constructor

@leaf MvNormal now runs once in runtests.jl instead of inside every testset loop, and the
base distributions use an identity covariance instead of the deprecated vector-of-sigmas
form.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Enzyme 0.13.188 fails LLVM function verification when differentiating the batched RQS on
Julia 1.10 (Float64 only); the other backends pass there and Enzyme passes on 1.11+.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mal constructor

MvNormal(mu, I) builds an IsoNormal, and Enzyme crashes differentiating destructure over
that type. Diagonal(ones(T, 2)) keeps the exact DiagNormal the deprecated form produced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@shravanngoswamii
shravanngoswamii marked this pull request as ready for review August 19, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant