Open-source project
LuxDL/Lux.jl avatar
LuxDL/Lux.jl

Lux.jl: Explicit-Parameter Deep Learning for Julia, Reviewed

Elegant and Performant Deep Learning

728 stars90 forksJuliaMIT

At a glance

What is it?
Lux.jl is an MIT-licensed Julia deep learning framework built around explicit model parameters and XLA compilation. It suits Julia-native scientific work that needs GPU or TPU execution, and it asks for more manual wiring than a typical Python training stack.
Who is it for?
Adopt Lux.jl if your work already lives in Julia and you want models whose parameters are ordinary values you can inspect, transform, and move between devices without a hidden state object. Do not adopt it if you need a large catalog of pretrained models with one-line loading, or if your team has no Julia experience.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly Julia, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Lux.jl solves: parameters that are not hidden inside the model

Most deep learning frameworks couple a layer's configuration to its learned weights. You construct a layer, and it immediately owns tensors that change during training. That coupling makes certain things awkward: extracting all weights for a custom optimizer, replicating a model across devices, serializing just the parameters without the architecture, or applying a transformation to every weight uniformly. Lux.jl's answer is to keep the two separate. The README describes the project as elegant and performant deep learning in JuliaLang, and the repository layout shows the split is enforced structurally: the core abstractions live in lib/LuxCore, the numerical kernels in lib/LuxLib, device handling in lib/MLDataDevices, initialization schemes in lib/WeightInitializers, and test helpers in lib/LuxTestUtils. The target audience is Julia users doing scientific machine learning, the same group the topics list names alongside deep-learning and neural-networks. If you are porting a PyTorch training script line by line, this design will feel like extra ceremony. If you are building a differentiable simulation and need the neural network to behave like any other Julia value, the separation is the point.

How the explicit-parameter mechanism shapes the code you write

In Lux.jl a layer is a description, not a container of weights. Calling a layer with input data and a parameter object returns the output and a new parameter object; the layer itself is not mutated. The documentation frames this as functional-style model definition, and the practical consequence is that a model's parameters are a plain nested structure you can pass around, map over, or hand to an optimizer independently of the architecture that produced them. LuxCore.jl holds these abstractions, which is why the subpackage exists as a separate dependency rather than being folded into the main package: other packages can depend on the layer and parameter interfaces without pulling in the training loop. The GPU and TPU support advertised in the repository topics routes through MLDataDevices.jl, whose most recent release in the supplied material is MLDataDevices-v1.17.9 dated 2026-05-02. That version numbering is worth noticing. MLDataDevices has reached 1.17 while WeightInitializers sits at 1.3.4 and LuxTestUtils at 2.3.1, so the subpackages are versioned and released independently. The README's tagline, model with the elegance of Julia and the performance of XLA, points at the compilation path rather than at any specific layer implementation.

Installing Lux.jl and what the README actually shows

The installation instructions are three lines and use Julia's standard package manager. The README gives this example:

import Pkg Pkg.add("Lux")

That is the whole of the documented setup in the supplied material. The README also notes that to use Lux online you can open Google Colab, and states that the Julia Runtime there comes pre-installed with Lux and Reactant. No configuration keys, environment variables, or setup files appear in the material I have. That absence is itself informative: Lux.jl does not appear to require a global config step, and device selection is handled through MLDataDevices.jl rather than through a project-level settings file. I cannot confirm from the supplied material what the exact call is to move a model to a GPU, or whether a CUDA runtime must be installed separately before MLDataDevices will detect it. Those details live in the documentation site, not in the README excerpt available here.

The subpackage split is a maintenance surface, not just a design choice

Six packages sit under the LuxDL organization in the repository table: Lux.jl itself, LuxLib.jl, LuxCore.jl, MLDataDevices.jl, WeightInitializers.jl, LuxTestUtils.jl, and LuxCUDA.jl. Each has its own version badge and its own CI status. The three most recent releases in the supplied material are LuxTestUtils-v2.3.1, WeightInitializers-v1.3.4, and MLDataDevices-v1.17.9, spread across July, May, and May 2026 respectively. For an application developer this means a single Pkg.add("Lux") resolves a graph of independently moving parts. A change in MLDataDevices can alter which devices are available without any change to Lux.jl's own version number. For a library author it means you can depend on LuxCore.jl alone if you only need the layer and parameter interfaces, which keeps your dependency footprint smaller than depending on the full training stack. The cost is that compatibility questions sometimes have to be answered at the subpackage level rather than the Lux level. The README does not state a version compatibility matrix, so I cannot tell you which LuxLib version pairs with which LuxCore version. That information would need to come from the docs or from the Project.toml files in the repository.

Where Lux.jl is the wrong tool

The explicit-parameter design has a real cost. Every training loop has to thread the parameter object through the step function and reassign it, because layers do not hold state. Frameworks that mutate weights in place let you write a training loop that ignores parameter plumbing entirely. Lux.jl does not. If your work is closer to standard supervised learning on tabular or image data, and you value a short path from data to a trained model, the extra structure is overhead you will pay on every step. There is also the ecosystem question. The supplied material contains no evidence of a pretrained model zoo, no mention of a Hugging Face style hub integration, and no listing of available architectures beyond what the documentation site presumably holds. If you need to fine-tune an existing large model, Lux.jl is not obviously the right starting point, and I cannot confirm from this material that it is. Finally, the Julia requirement itself is a boundary. A team that writes Python cannot use Lux.jl without adopting Julia, and the README's Colab tip does not change that.

Lux.jl compared with Flux.jl

Flux.jl is the older and more widely used Julia deep learning library, and the difference is architectural rather than cosmetic. Flux layers are callable structs that carry their own parameter arrays; you construct a model, and the weights exist inside it. Lux.jl separates those two things, so a model is a pure function over an explicit parameter structure. The practical difference shows up when you want to do something unusual with the weights: apply a custom transformation to every parameter, compute a gradient with respect to parameters you constructed yourself, or run the same architecture with two different parameter sets side by side. In Flux that requires reaching into the model and manipulating its fields, which is possible but couples your code to the layer's internal layout. In Lux the parameters are already a separate value, so the operation is a map over that value. The trade is that Flux's approach produces shorter, more familiar code for conventional training, and its larger user base means more third-party layers and more answered questions. Lux.jl's topics list includes TPU and XLA, which suggests the compilation path is a deliberate part of the pitch, but I cannot verify from the supplied material how the two libraries compare on any specific hardware.

Licence, release cadence, and what to check before adopting

Lux.jl is MIT licensed, which permits commercial and closed-source use, modification, and redistribution provided the copyright notice and permission notice are preserved. That is the same licence family as most of the Julia numerical ecosystem, so combining Lux.jl with other Julia packages is unlikely to raise licence conflicts. This is a description of the licence text, not legal advice; if you are shipping a product, have your own counsel read the terms. On cadence: the repository shows a push as recent as 2026-09-09 and a release stream that includes patch versions of supporting packages in mid-2026, so the project is active rather than dormant. The archived flag is false. The CI badges in the README cover GitHub Actions, a pre-release workflow, and a separate Buildkite pipeline labeled gpu, which suggests GPU testing runs on different infrastructure than the CPU tests. I cannot confirm what those pipelines actually execute. The README also references JET.jl static analysis and Aqua.jl quality checks, which are Julia ecosystem tools for catching type instability and package metadata problems. Their presence in the badge list indicates the maintainers run them, but says nothing about the results.

Editorial conclusion

Adopt Lux.jl if your work already lives in Julia and you want models whose parameters are ordinary values you can inspect, transform, and move between devices without a hidden state object. Do not adopt it if you need a large catalog of pretrained models with one-line loading, or if your team has no Julia experience. Before committing, verify three things against the current stable docs at lux.csail.mit.edu: that the device you intend to run on is covered by MLDataDevices.jl, that the layer types you need exist in LuxCore.jl rather than in a third-party extension, and that the subpackage versions resolved by Pkg.add("Lux") are mutually compatible, since LuxLib, LuxCore, MLDataDevices, WeightInitializers, and LuxTestUtils each carry independent version numbers and release on their own schedules.

Official sources

  1. License: MIT
  2. LuxDL/Lux.jl on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes