Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
144 commits
Select commit Hold shift + click to select a range
29b3705
up
jeremiedb Jan 21, 2026
4ab436f
up
jeremiedb Jan 21, 2026
57e10fb
Update model.jl
jeremiedb Jan 21, 2026
5ea33c4
cleanup
jeremiedb Jan 23, 2026
5024688
up
jeremiedb Jan 24, 2026
31776f4
up
jeremiedb Jan 24, 2026
0859d48
up
jeremiedb Jan 24, 2026
97bd3da
up
jeremiedb Jan 26, 2026
4bbdc79
up
jeremiedb Jan 28, 2026
e2a3dfc
Replace Zygote with Enzyme for gradient computation
AdityaPandeyCN Jan 30, 2026
e877c06
revert back loss logic
AdityaPandeyCN Jan 31, 2026
2fe0010
up
jeremiedb Jan 31, 2026
9e3d29d
up
jeremiedb Jan 31, 2026
020d4d0
fit return cpu model
jeremiedb Feb 4, 2026
a342bd5
use reactant and flux approach
AdityaPandeyCN Feb 5, 2026
7c3d33e
formatting
AdityaPandeyCN Feb 5, 2026
c2ad582
revert changes
AdityaPandeyCN Feb 6, 2026
c0fc0ff
add back imports
AdityaPandeyCN Feb 6, 2026
01477ac
update callback.jl
AdityaPandeyCN Feb 6, 2026
9c832e7
revert back NAdam and remove CUDA dependency
AdityaPandeyCN Feb 6, 2026
389d624
Compile gradient function once in init(), reuse across all epochs
AdityaPandeyCN Feb 9, 2026
afcc486
remove CuDNN dependency
AdityaPandeyCN Feb 12, 2026
4258de8
refactor fit.jl
AdityaPandeyCN Feb 12, 2026
30897d0
Add _sync_to_cpu! to MLJ interface to synchronize trained weights fro…
AdityaPandeyCN Feb 12, 2026
7950273
Update mlogloss to accept pre-encoded one-hot matrices, removing inte…
AdityaPandeyCN Feb 12, 2026
5587aed
make track_stats false
AdityaPandeyCN Feb 12, 2026
08974b4
update benchmark file
AdityaPandeyCN Feb 12, 2026
a0bfa18
simplify cpu sync logic
AdityaPandeyCN Feb 13, 2026
c8b14d5
clean MLJ.jl
AdityaPandeyCN Feb 13, 2026
2388bcd
up
jeremiedb Feb 13, 2026
1066ecd
fix imports
AdityaPandeyCN Feb 13, 2026
19f5c25
up
jeremiedb Feb 13, 2026
27fe14d
Merge branch 'reactantv1' of github.com:AdityaPandeyCN/NeuroTabModels…
jeremiedb Feb 13, 2026
9a984a2
fix data loader
jeremiedb Feb 13, 2026
0ba7aa3
Merge branch 'jdb/neuro-v3' of github.com:Evovest/NeuroTabModels.jl i…
jeremiedb Feb 13, 2026
94c667b
up
jeremiedb Feb 15, 2026
1acb975
up
jeremiedb Feb 15, 2026
5c6f97b
up
jeremiedb Feb 15, 2026
b8becdf
up
jeremiedb Feb 15, 2026
8c02e99
up
jeremiedb Feb 15, 2026
47bd880
up
jeremiedb Feb 15, 2026
e8a28e7
up
jeremiedb Feb 15, 2026
3ca7a83
up
jeremiedb Feb 15, 2026
c7fa43a
fix inference, callbacks, and classification
AdityaPandeyCN Feb 15, 2026
88cf9a7
simplify get_device
AdityaPandeyCN Feb 16, 2026
24f3fde
up
jeremiedb Feb 16, 2026
be881a3
model cleanup
AdityaPandeyCN Feb 16, 2026
9dad435
fix imports
AdityaPandeyCN Feb 16, 2026
b6b47f4
fix imports
AdityaPandeyCN Feb 16, 2026
674ef55
add gpu inference support
AdityaPandeyCN Feb 16, 2026
2a63954
revert test
AdityaPandeyCN Feb 16, 2026
8f0f70f
cleanup
AdityaPandeyCN Feb 17, 2026
0d70551
merge conflicts
AdityaPandeyCN Feb 17, 2026
d4984a2
merge conflicts
AdityaPandeyCN Feb 17, 2026
c0799f1
merge conflicts
AdityaPandeyCN Feb 17, 2026
75c6b53
Switch to lazy data loading to reduce memory usage and replace custom…
AdityaPandeyCN Feb 19, 2026
a329289
revert Project.toml dependency
AdityaPandeyCN Feb 19, 2026
e704a38
revert comments
AdityaPandeyCN Feb 19, 2026
20c9b74
revert y_pred to p
AdityaPandeyCN Feb 19, 2026
7082adb
operate callback directly on active object
AdityaPandeyCN Feb 20, 2026
dc129e4
cleanup callback.jl
AdityaPandeyCN Feb 20, 2026
8abf99b
handle MLogLoss with Lux.CrossEntropyLoss
AdityaPandeyCN Feb 20, 2026
6ed2364
use train state for metrics
AdityaPandeyCN Feb 20, 2026
f72db19
fix data loader
AdityaPandeyCN Feb 20, 2026
9fc003f
fix fit function arguments
AdityaPandeyCN Feb 20, 2026
52a662d
fix dimension flow
AdityaPandeyCN Feb 20, 2026
162094d
file changes cleanup
AdityaPandeyCN Feb 20, 2026
916de8b
fix array typing
AdityaPandeyCN Feb 20, 2026
b749fa8
sync
jeremiedb Feb 20, 2026
62f0a00
sync
jeremiedb Feb 20, 2026
2385451
up
jeremiedb Feb 20, 2026
13c106d
up
jeremiedb Feb 20, 2026
9ab274d
up
jeremiedb Feb 20, 2026
ea2b5de
apply partial=false and fix infer
AdityaPandeyCN Feb 21, 2026
7461b0f
revert project.toml
AdityaPandeyCN Feb 21, 2026
e0d7da7
up
jeremiedb Feb 22, 2026
685375d
Jdb/grant review (#24)
jeremiedb Feb 22, 2026
f3ea6f0
Merge branch 'main' into jdb/neuro-v3
jeremiedb Feb 22, 2026
efdc333
Merge branch 'jdb/neuro-v3' into lux-new
jeremiedb Feb 22, 2026
309408f
up
jeremiedb Feb 22, 2026
efded44
Merge branch 'aditya/lux' of github.com:AdityaPandeyCN/NeuroTabModels…
jeremiedb Feb 22, 2026
491e68d
cleanup
jeremiedb Feb 22, 2026
873eb2d
up
jeremiedb Feb 26, 2026
8784a1f
up
jeremiedb Feb 26, 2026
7db9d34
Fix inference and crash from use of deval (#27)
AdityaPandeyCN Feb 27, 2026
69641bc
up
jeremiedb Feb 28, 2026
15f449b
up
jeremiedb Mar 4, 2026
9d3cb94
up
jeremiedb Mar 4, 2026
a10f863
Merge branch 'lux-new' of github.com:Evovest/NeuroTabModels.jl into l…
jeremiedb Mar 4, 2026
2a16920
Use AbstractLuxWrapperLayer for Neurotrees (#30)
AdityaPandeyCN Mar 6, 2026
d2e0733
up
jeremiedb Mar 10, 2026
abf767d
up
jeremiedb Mar 10, 2026
bf55f45
Add documentation for the loss function (#32)
AdityaPandeyCN Mar 14, 2026
e4dfedb
Merge branch 'main' of github.com:Evovest/NeuroTabModels.jl into lux-new
jeremiedb Mar 18, 2026
6a763ab
up
jeremiedb Mar 18, 2026
5cb5bd6
Add TabM architecture and numerical embeddings module (#29)
AdityaPandeyCN Mar 18, 2026
de061cd
up
jeremiedb Mar 18, 2026
5d86f99
up
jeremiedb Mar 19, 2026
9456f70
docs
jeremiedb Mar 19, 2026
439f5cd
docs
jeremiedb Mar 19, 2026
c0d766c
docs
jeremiedb Mar 19, 2026
c9a9747
Add EmbeddingConfig for architecture-independent embeddings (#33)
AdityaPandeyCN Mar 25, 2026
9c73c9b
Embed (#34)
jeremiedb Apr 14, 2026
a29a4e9
up
jeremiedb Apr 15, 2026
2afe9ef
up
jeremiedb Apr 17, 2026
891d900
up (#42)
jeremiedb Apr 18, 2026
631b118
up
jeremiedb Apr 18, 2026
5fdeecf
test
jeremiedb Apr 19, 2026
bb5460c
up
jeremiedb Apr 19, 2026
c05ea3b
up
jeremiedb Apr 23, 2026
6da26df
Merge branch 'lux-new' of github.com:Evovest/NeuroTabModels.jl into l…
jeremiedb Apr 23, 2026
84bb138
up
jeremiedb Apr 23, 2026
e52f34b
add support for multi-AD backend through extension
AdityaPandeyCN Apr 24, 2026
8944fd9
up
jeremiedb Apr 24, 2026
c70480c
Merge branch 'lux-new' of github.com:Evovest/NeuroTabModels.jl into l…
jeremiedb Apr 24, 2026
0d1ff5e
revert default to cpu
AdityaPandeyCN Apr 25, 2026
5f60665
REMOVE ZYGOTE COMPAT
AdityaPandeyCN Apr 25, 2026
1eb6420
Move Reactant selection from to , keep Enzyme as the AD backend unde…
AdityaPandeyCN May 1, 2026
90a110a
up
jeremiedb May 2, 2026
dc14149
Merge branch 'aditya/multi-ad' of github.com:AdityaPandeyCN/NeuroTabM…
jeremiedb May 2, 2026
e38782b
up
jeremiedb May 3, 2026
81b0279
up
jeremiedb May 3, 2026
1512874
Multi-AD backend support via package extensions (#44)
AdityaPandeyCN May 3, 2026
8b4cb2e
up
jeremiedb May 3, 2026
dde6d6b
Merge branch 'jdb/multi-ad' of github.com:Evovest/NeuroTabModels.jl i…
jeremiedb May 3, 2026
ae427c4
correlation metric
jeremiedb May 3, 2026
9e76eea
correlation metric
jeremiedb May 3, 2026
c518293
correlation metric
jeremiedb May 3, 2026
1fc5fba
up
jeremiedb May 3, 2026
d410747
up
jeremiedb May 3, 2026
af6ae4c
rewrite mlogloss with ifelse (#45)
AdityaPandeyCN May 4, 2026
d9cf82b
up
jeremiedb May 4, 2026
b49feaa
Merge branch 'lux-new' of github.com:Evovest/NeuroTabModels.jl into l…
jeremiedb May 4, 2026
c87095c
up
jeremiedb Jun 9, 2026
d436d47
up
jeremiedb Jun 9, 2026
afa5857
up
jeremiedb Jun 10, 2026
f921287
up
jeremiedb Jun 10, 2026
179e409
up
jeremiedb Jun 10, 2026
307b515
sync main
jeremiedb Jun 10, 2026
14e7d38
sync main
jeremiedb Jun 10, 2026
4586f5f
sync main
jeremiedb Jun 10, 2026
126b3d2
Merge branch 'main' of github.com:Evovest/NeuroTabModels.jl into lux-new
jeremiedb Jun 13, 2026
f99d51a
up
jeremiedb Jun 13, 2026
b3e08aa
Add temporal embedding and ModernNCA model (#49)
AdityaPandeyCN Jul 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions benchmarks/titanic-logloss.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ learner = NeuroTabRegressor(
device=:cpu,
backend=:reactant
)
learner.embedding_config
# main / lux-new
# NeuroTabModels.Models.Embeddings.EmbeddingConfig(:batchnorm, 1, :relu, 32, 32, 0.01f0)
# mnca/temporal
# NeuroTabModels.Models.Embeddings.EmbeddingLayer{NeuroTabModels.Models.Embeddings.BatchNormEmbeddings, Nothing}(NeuroTabModels.Models.Embeddings.BatchNormEmbeddings(), nothing)
# NeuroTabModels.Models.Embeddings.EmbeddingLayer{NeuroTabModels.Models.Embeddings.PiecewiseLinearEmbeddings, Nothing}(NeuroTabModels.Models.Embeddings.PiecewiseLinearEmbeddings(8, 16, :identity, :B), nothing)

@time m = NeuroTabModels.fit(
learner,
Expand Down
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pages = [
"Quick start" => "quick-start.md",
"API" => "API.md",
"Design" => "design.md",
"Embeddings" => "embeddings.md",
"Models" => [
"Interface" => "models/models.md",
"MLP" => "models/mlp.md",
Expand Down
38 changes: 38 additions & 0 deletions docs/src/embeddings.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,43 @@
# Embeddings

Embeddings transform raw input columns before they reach a model backbone. Numerical
embeddings operate column-wise, while temporal embeddings reserve one column for
time features and concatenate that branch with the remaining numerical features.

## Available Embeddings

- `IdentityEmbedding`: leaves numerical features unchanged.
- `LinearEmbeddings`: projects each numerical feature to a learned vector.
- `PeriodicEmbeddings`: expands each feature with learned sinusoidal terms before projection.
- `PiecewiseLinearEmbeddings`: computes feature bins from the training data and embeds the resulting piecewise-linear encoding.
- `BatchNormEmbeddings`: batch-normalizes raw numerical features without expanding them.
- `TemporalEmbeddings`: embeds one time column with Fourier features and an optional trend term.

## Configuration

Use `EmbeddingLayer` to combine a numerical embedding with an optional temporal
branch. A dictionary form is also available for model configuration dictionaries.

```julia
EmbeddingLayer(PeriodicEmbeddings(; d_embedding=24))

EmbeddingLayer(;
num=PiecewiseLinearEmbeddings(; bins=32),
temp=TemporalEmbeddings(; index=1),
)

EmbeddingLayer(Dict(
:embedding_type => :periodic,
:d_embedding => 24,
:temporal => Dict(:index => 1),
))
```

Piecewise-linear and temporal embeddings need training data when the embedding chain is
built. Use `needs_x_train` to check that requirement for a spec.

## API

```@autodocs
Modules = [NeuroTabModels.Models.Embeddings]
```
7 changes: 6 additions & 1 deletion ext/NeuroTabModelsReactantExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ function _get_device(::Val{:reactant}, ::Val{D}; gpuID::Integer=0) where {D}
return reactant_device()
end

_same_shape(a::AbstractArray, b::AbstractArray) = size(a) == size(b)
_same_shape(a::Tuple, b::Tuple) =
length(a) == length(b) && all(_same_shape(ai, bi) for (ai, bi) in zip(a, b))
_same_shape(_, _) = false

function _infer_loop(::Val{:reactant}, chain, data, x0, dev, cdev, ps, st)
compiled = @compile _forward_reduce(chain, dev(x0), ps, st)

preds = Vector{AbstractArray}()
for x in data
if size(x) == size(x0)
if _same_shape(x, x0)
pred = compiled(chain, dev(x), ps, st)
else
pred = Reactant.@jit _forward_reduce(chain, dev(x), ps, st)
Expand Down
5 changes: 4 additions & 1 deletion src/Fit/callback.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ using ..Learners: LearnerTypes
using ...Infer: reduce_pred, _get_device
using ..Data: get_df_loader_train
using ..Metrics
using ...Models

using Lux: Training, testmode

Expand All @@ -26,7 +27,8 @@ end
function CallBack(
config::LearnerTypes,
df::AbstractDataFrame,
cache;
cache,
m;
feature_names,
target_name,
weight_name=nothing,
Expand All @@ -43,6 +45,7 @@ function CallBack(
deval = get_df_loader_train(dfg; feature_names, target_name, weight_name, offset_name, scalers, batchsize, shuffle=false) |> dev

ps, st = ts.parameters, testmode(ts.states)
deval = Models.eval_dataloader(m.chain, m.info, deval, dev, ps, st)
d0 = first(deval)
eval_compiled = _build_eval_step(ts.model, feval, d0, ps, st; reactant=config.backend == :reactant)

Expand Down
25 changes: 10 additions & 15 deletions src/Fit/fit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ using ..Losses
using ..Metrics
using ..Infer: reduce_pred, _get_device

import Random: Xoshiro
import Random: Xoshiro, default_rng
import Statistics: mean, std
import MLJModelInterface: fit
import Optimisers: OptimiserChain, WeightDecay, NAdam, Adam
Expand Down Expand Up @@ -73,19 +73,12 @@ function init(

# Build chain: optional embeddings + architecture backbone
embed_config = config.embedding_config
if isnothing(embed_config)
chain = config.arch(; nfeats, outsize)
else
if embed_config.embedding_type == :piecewise
x_train = Matrix{Float32}(df[:, feature_names])
else
x_train = nothing
end
embed_chain = embed_config(; nfeats, x_train)
d_in = nfeats * embed_config.d_embedding
d_features = fill(embed_config.d_embedding, nfeats)
chain = Chain(embed_chain, config.arch(; nfeats=d_in, outsize, d_features, scaling_init_override=:normal))
end
x_train = Models.Embeddings.needs_x_train(embed_config) ? Matrix{Float32}(df[:, feature_names]) : nothing
embed_chain = Models.Embeddings.build_embedding_chain(embed_config, nfeats; x_train)
d_in = Models.Embeddings.embedding_width(embed_chain, randn(Float32, nfeats, 2), default_rng())
chain = Models.build_chain(config.arch, embed_chain;
nfeats, outsize, d_in, embedding_config=embed_config, loss_type=L)


info = Dict(
:nrounds => 0,
Expand All @@ -105,6 +98,8 @@ function init(

rng = Xoshiro(config.seed)
ps, st = Lux.setup(rng, m.chain) |> dev
data = Models.train_dataloader(config.arch, m, data, df;
feature_names, target_name, loss_type=L, scalers, batchsize, dev, rng)
opt = OptimiserChain(NAdam(config.lr), WeightDecay(config.wd))
ts = Training.TrainState(m.chain, ps, st, opt)

Expand Down Expand Up @@ -164,7 +159,7 @@ function fit(

logger = nothing
if !isnothing(deval)
cb = CallBack(config, deval, cache; feature_names, target_name, weight_name, offset_name, group_key)
cb = CallBack(config, deval, cache, m; feature_names, target_name, weight_name, offset_name, group_key)
logger = init_logger(config)
cb(logger, 0, cache[:train_state])
(verbosity > 0) && @info "Init training" metric = logger[:metrics][end]
Expand Down
32 changes: 16 additions & 16 deletions src/learners.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ import MLJModelInterface: fit, update, predict, schema
import Random

using ..Models
using ..Models: EmbeddingConfig
using ..Models: AbstractEmbedding, IdentityEmbedding, EmbeddingLayer
export NeuroTabRegressor, NeuroTabClassifier, LearnerTypes

_to_embedding(::Nothing) = IdentityEmbedding()
_to_embedding(e::AbstractEmbedding) = e
_to_embedding(d::AbstractDict) = EmbeddingLayer(d)
_to_embedding(x) = error("`embedding_config` must be `nothing`, an `AbstractDict`, or an `AbstractEmbedding`; got $(typeof(x)).")

mutable struct NeuroTabRegressor <: MMI.Deterministic
loss::Symbol
metric::Symbol
arch::Architecture
embedding_config::Union{Nothing,EmbeddingConfig}
embedding_config::AbstractEmbedding
nrounds::Int
early_stopping_rounds::Int
lr::Float32
Expand Down Expand Up @@ -47,8 +52,10 @@ A model type for constructing a NeuroTabRegressor, based on [NeuroTabModels.jl](
- `backend=:zygote`: Backend used by Lux. One of `:enzyme`, `:zygote`, or `:reactant`.
- `device=:gpu`: Execution device. One of `:cpu` or `:gpu`.
- `gpuID=0`: GPU device to use, only relevant if `device = :gpu`. `0` auto-selects.
- `embedding_config=nothing`: Optional `Dict` or `EmbeddingConfig` for numerical feature embeddings.
E.g. `embedding_config=Dict(:embedding_type => :periodic, :d_embedding => 24)`.
- `embedding_config=nothing`: Optional numerical/temporal embeddings. Accepts `nothing` (no-op),
an `AbstractEmbedding` (e.g. `EmbeddingLayer(num=PeriodicEmbeddings(d_embedding=24))`), or an
`AbstractDict` selecting the type via `:embedding_type` (e.g.
`Dict(:embedding_type => :periodic, :d_embedding => 24)`).

`backend=:zygote` works on `:cpu` and `:gpu`; `backend=:reactant` works on `:cpu` and `:gpu` and uses Enzyme for AD.
`backend=:enzyme` with `device=:gpu` is currently known to fail for some NeuroTabModels models.
Expand Down Expand Up @@ -194,11 +201,7 @@ function NeuroTabRegressor(arch::Architecture; kwargs...)
@warn "`backend=:enzyme` with `device=:gpu` is currently known to fail for some NeuroTabModels models. Prefer `backend=:zygote` on GPU, `backend=:reactant` for Reactant, or `backend=:enzyme` on CPU."
end

# Build EmbeddingConfig from Dict if needed
embed = args[:embedding_config]
if embed isa AbstractDict
embed = EmbeddingConfig(; embed...)
end
embed = _to_embedding(args[:embedding_config])

config = NeuroTabRegressor(
loss,
Expand Down Expand Up @@ -231,7 +234,7 @@ mutable struct NeuroTabClassifier <: MMI.Probabilistic
loss::Symbol
metric::Symbol
arch::Architecture
embedding_config::Union{Nothing,EmbeddingConfig}
embedding_config::AbstractEmbedding
nrounds::Int
early_stopping_rounds::Int
lr::Float32
Expand Down Expand Up @@ -259,7 +262,8 @@ A model type for constructing a NeuroTabClassifier, based on [NeuroTabModels.jl]
- `backend=:zygote`: Backend used by Lux. One of `:enzyme`, `:zygote`, or `:reactant`.
- `device=:gpu`: Execution device. One of `:cpu` or `:gpu`.
- `gpuID=0`: GPU device to use, only relevant if `device = :gpu`. `0` auto-selects.
- `embedding_config=nothing`: Optional `Dict` or `EmbeddingConfig` for numerical feature embeddings.
- `embedding_config=nothing`: Optional numerical/temporal embeddings. Accepts `nothing` (no-op),
an `AbstractEmbedding`, or an `AbstractDict` selecting the type via `:embedding_type`.

`backend=:zygote` works on `:cpu` and `:gpu`; `backend=:reactant` works on `:cpu` and `:gpu` and uses Enzyme for AD.
`backend=:enzyme` with `device=:gpu` is currently known to fail for some NeuroTabModels models.
Expand Down Expand Up @@ -390,11 +394,7 @@ function NeuroTabClassifier(arch::Architecture; kwargs...)
@warn "`backend=:enzyme` with `device=:gpu` is currently known to fail for some NeuroTabModels models. Prefer `backend=:zygote` on GPU, `backend=:reactant` for Reactant, or `backend=:enzyme` on CPU."
end

# Build EmbeddingConfig from Dict if needed
embed = args[:embedding_config]
if embed isa AbstractDict
embed = EmbeddingConfig(; embed...)
end
embed = _to_embedding(args[:embedding_config])

config = NeuroTabClassifier(
:mlogloss,
Expand Down
Loading
Loading