Open-source project
elixir-nx/scholar avatar
elixir-nx/scholar

Scholar: classical machine learning algorithms written as Nx numerical definitions

Traditional machine learning on top of Nx

498 stars53 forksElixirApache-2.0

At a glance

What is it?
Scholar is the elixir-nx project that implements classification, regression, clustering, dimensionality reduction, metrics and preprocessing on top of Nx. Its defining constraint is that every accepted algorithm must be expressible as a numerical definition, which shapes both what it can do and what it refuses.
Who is it for?
Adopt Scholar if you are already in the Nx ecosystem and want classical algorithms that compile to EXLA on CPU, CUDA or ROCm without leaving Elixir. Do not adopt it if your problem needs decision trees or forests, which the contributing guide explicitly rules out of scope.
Can I use it commercially?
Yes. Apache-2.0 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 13 days ago.
What is it written in?
Mainly Elixir, 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 gap Scholar fills between Nx and Axon

Nx gives Elixir tensors and numerical definitions. Axon sits on top of that for deep learning. Between the two there was nothing for the ordinary statistical work that shows up before or beside a neural network: k-means, dimensionality reduction, a confusion matrix, feature scaling. Scholar is that layer. The README lists its scope as classification, regression, clustering, dimensionality reduction, metrics and preprocessing, and points at Axon explicitly for deep learning, so the split is intentional rather than accidental. The audience is an Elixir engineer who has data in tensors already and does not want to shell out to Python for a linear model. That is a narrower audience than a general scikit-learn replacement, and the project seems comfortable with that.

The defn-only rule and what it excludes

The contributing section states the rule plainly: only implementations fully written as numerical definitions are accepted, because that is what lets the algorithms compile and run on GPUs. The README then names the casualty. Decision trees and forests are called out as algorithms that cannot be implemented under this constraint, and readers are directed to EXGBoost instead. This is the single most important fact about Scholar. It is not a library that happens to be GPU-friendly; it is a library whose API surface is defined by that requirement. The implementation pattern follows from it. Most public functions validate options and then delegate to code written inside a defn or defnp, and the README links a pull request as the worked example of that shape. The recommended test is equally specific: wrap your implementation in an Nx.Defn.jit/2 call and confirm it still runs. If it does not survive JIT, it does not belong in Scholar.

Installing Scholar and the JIT configuration it demands

For a Mix project the dependency is {:scholar, "~> 0.3.0"}, and the README recommends pairing it with a compiler backend such as {:exla, ">= 0.0.0"}. The configuration is where the project is unusually insistent. In config/config.exs you set config :nx, :default_backend, EXLA.Backend, and you set config :nx, :default_defn_options, [compiler: EXLA, client: :host]. The README marks this as required rather than recommended, noting that many algorithms use loops which are much more memory efficient when JIT compiled. The client can be :cuda or :rocm instead of :host. In a notebook the equivalent is Mix.install with the same two dependencies, followed by Nx.global_default_backend(EXLA.Backend) and Nx.Defn.global_default_options(compiler: EXLA, client: :host). There is an escape hatch if you cannot set a global compiler: JIT a single function yourself, for example EXLA.jit(&Scholar.Cluster.AffinityPropagation.fit/1). That escape hatch is worth knowing, because it tells you the functions are jittable individually and the global setting is a convenience, not a hard requirement on every call site.

Where the design costs you something

The defn-only rule buys GPU compilation and pays for it in coverage. Anything whose control flow depends on the data, which is most of tree induction, is out. The README does not claim otherwise, and naming EXGBoost is a more honest move than quietly omitting the category. The second cost is environmental. Because the README states that many algorithms rely on JIT for memory efficiency, a plain Nx binary backend is not a neutral substitute; running without EXLA configured changes the memory profile rather than just the speed. The third is maturity signal. No releases were retrieved for this review, the homepage field is empty, and the installation examples pin ~> 0.3.0, so treat the API as pre-1.0 and check hexdocs for the specific module you intend to call rather than assuming a stable surface across minor versions. None of this is disqualifying; it is the normal shape of a library whose design is still being argued out in pull requests.

Scholar against EXGBoost: a difference in kind, not degree

The README's own pointer makes the comparison concrete. EXGBoost is named as the additional library for decision trees and forests, the algorithms Scholar excludes. The difference is not that one is faster or has more estimators. It is that EXGBoost wraps a gradient boosting implementation whose tree construction is inherently not a numerical definition, while Scholar only admits algorithms that can be written as defn code and compiled through EXLA. So the two do not overlap: if your model is a boosted tree ensemble, Scholar has nothing for you and the README says so. If your model is a linear regression, a clustering pass or a preprocessing step that must run inside the same compiled graph as the rest of your Nx pipeline, EXGBoost is the wrong tool and Scholar is the one built for it. Choosing between them is a question about your algorithm, not about benchmarks.

Maintenance, contribution and the Apache-2.0 terms

Scholar is maintained by the Machine Learning Working Group of the Erlang Ecosystem Foundation, and the copyright line in the README names that group rather than a single author, which matters for anyone assessing bus factor. The Apache License, Version 2.0 governs use and distribution. The README reproduces the standard disclaimer that the software is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, and that is worth reading literally: nothing in the repository promises fitness for a particular model or dataset. The licence also carries the usual patent grant and notice obligations, and the README points to the full text at apache.org rather than summarising it, so read the licence itself if you are redistributing. This is not legal advice. On the contribution side, the cost of adding an algorithm is the cost of writing it as a defn plus the JIT test the README recommends, and the linked pull request is the template. Expect review to focus on whether the implementation is genuinely a numerical definition, since that is the stated acceptance criterion.

Editorial conclusion

Adopt Scholar if you are already in the Nx ecosystem and want classical algorithms that compile to EXLA on CPU, CUDA or ROCm without leaving Elixir. Do not adopt it if your problem needs decision trees or forests, which the contributing guide explicitly rules out of scope. Before committing, verify that your chosen algorithm is present in the current 0.3.x documentation and that you can set a default defn compiler, since the README states many algorithms rely on JIT for memory efficiency.

Official sources

  1. elixir-nx/scholar on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
Community notes

Community notes