Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d3dae39
feat: add lazymatrix feature
jolars Oct 8, 2026
39f64c1
Use MSE criterion in base tree regressor
slievens Oct 14, 2026
ce1ee48
No leaf has a split_score.
slievens Oct 15, 2026
6505833
Remove gini and tests
slievens Oct 15, 2026
d4e67bc
Clamp mass residue to zero
slievens Oct 15, 2026
be58518
Merge 'always-shuffle'
slievens Oct 17, 2026
e7a8008
Use a stable MSE improvement and drop zero-mass rows
slievens Oct 18, 2026
501e5d5
Refactor grow
slievens Oct 18, 2026
c7eb8a3
update changelog
slievens Oct 18, 2026
c34b214
Add feature importances to the regression trees and forests
slievens Oct 20, 2026
0ff587f
Make the base tree generic over a split criterion
slievens Oct 22, 2026
4cef0b0
Rename BaseTreeRegressor to BaseTree
slievens Oct 22, 2026
f2f29e6
Move regression predict out of BaseTree
slievens Oct 22, 2026
553d3bf
Make BaseForestRegressor generic over the split criterion
slievens Oct 22, 2026
b8184a0
Rename BaseForestRegressor to BaseForest
slievens Oct 22, 2026
808caad
Move regression predict out of BaseForest
slievens Oct 22, 2026
06f2b36
Merge branch 'main' into make-generic
Mec-iS Oct 23, 2026
7a8237c
Make BaseTree and BaseForest generic over the leaf output
slievens Oct 23, 2026
782683f
Merge branch 'make-generic' of https://github.com/slievens/smartcore …
slievens Oct 23, 2026
0a62442
Merge branch 'main' into make-generic
Mec-iS Oct 24, 2026
f5d884c
Merge main into feat/lazy-normalization: resolve CHANGELOG and ci.yml…
Mec-iS Oct 24, 2026
ddaac60
Merge PR #480 (lazy normalization) into v0.7-release: resolve Cargo.t…
Mec-iS Oct 24, 2026
f813a4e
Merge PR #492 (MSE criterion in base tree regressor) into v0.7-releas…
Mec-iS Oct 24, 2026
a67a93f
chore: require ndarray 0.17.2
Mec-iS Oct 24, 2026
5ebb033
Merge remote-tracking branch 'pr/497' into v0.7-release
Mec-iS Oct 24, 2026
47411ee
Merge remote-tracking branch 'pr/502' into v0.7-release
Mec-iS Oct 24, 2026
3cd696e
chore(changelog): consolidate candidate changes under [v0.7] section
Mec-iS Oct 24, 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
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ jobs:
- "--features datasets"
- "--features ndarray-bindings"
- "--features std,ndarray-bindings"
- "--features lazy-normalization"
- "--features lazy-normalization,ndarray-bindings"
- ""
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -96,7 +98,7 @@ jobs:
;;
esac
- name: Tests
if: matrix.features == '--features ndarray-bindings' || matrix.features == '--features std,ndarray-bindings' || matrix.features == '--features datasets'
if: matrix.features == '--features ndarray-bindings' || matrix.features == '--features std,ndarray-bindings' || contains(matrix.features, 'lazy-normalization') || matrix.features == '--features datasets'
run: cargo test --no-default-features ${{ matrix.features }}
- name: Explicit std does not activate ndarray
if: matrix.features == ''
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [v0.7]
### Added
- A `Dependency audit` CI workflow runs `cargo deny` and `cargo audit` on each push and pull request, and every week. It fails when a dependency has a known vulnerability, is yanked, uses a license that is not allowed, or comes from an unknown source. The `deny.toml` file holds the rules.
- Optional `lazy-normalization` support for Lasso and Elastic Net. It applies normalization to a borrowed design and keeps Elastic Net's identity-block augmentation implicit, while retaining the dense Gram workspace. Enable the feature and set `with_lazy_normalization(true)` to select this path. The default remains eager. The new parameter field is available only with the feature and defaults to false during deserialization (#479).
- `tree`, `ensemble`: `DecisionTreeRegressor`, `RandomForestRegressor` and `ExtraTreesRegressor` get a `compute_feature_importances` method.

### Changed
- `Cargo.toml`: optional `ndarray` is now `default-features = false`, and the default feature set is `std` (`ndarray?/std`). Ordinary builds still enable ndarray's standard-library support when `ndarray-bindings` is on, while `std` alone does not activate ndarray. The `std` feature only controls ndarray's standard-library support; smartcore itself is not `no_std` (#421).
- **Migration:** builds that use `--no-default-features --features ndarray-bindings` (or `default-features = false` with `ndarray-bindings`) no longer get ndarray's `std` feature. Add `std` to the feature list to keep the previous behavior.
- **Breaking change:** Enabling `lazy-normalization` adds a public `lazy_normalization` field to `LassoParameters`, `LassoSearchParameters`, `ElasticNetParameters`, and `ElasticNetSearchParameters`. Struct literals without `..Default::default()` must add `lazy_normalization: false` to retain the eager path, or `true` to select the lazy path. This also applies when another dependency enables the feature through Cargo feature unification (#479).
- **Breaking change:** the fitted `DecisionTreeRegressor`, `RandomForestRegressor` and `ExtraTreesRegressor` store new fields that the feature importances use. Models serialized with an earlier version cannot be deserialized. Fit these models again.
- `tree`: `BaseTreeRegressor` (used by `DecisionTreeRegressor`, `RandomForestRegressor` and `ExtraTreesRegressor`) uses a new internal `Criterion` trait with `MSECriterion`. The MSE split improvement uses a numerically stable formula. The selected splits do not change when a constant is added to y. Exactly tied splits can be broken in a different way, so fitted trees can differ slightly from earlier versions.
- `tree`: in the `...Regressor`s, rows with sample weight 0 are removed before the tree grows. They no longer count toward `min_samples_leaf` and `min_samples_split`, and they no longer move a split threshold. A tree fitted with a zero-weight row is the same as a tree fitted without that row.
- `Cargo.toml`: `ndarray` requires version `0.17.2` or later.

## [0.7.0]
### Added
Expand Down
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ exclude = [
[dependencies]
approx = "0.5.1"
cfg-if = "1.0.0"
ndarray = { version = "0.17", optional = true, default-features = false }
lazymatrix = { version = "0.6.0", optional = true, default-features = false }
ndarray = { version = "0.17.2", optional = true, default-features = false }
num-traits = "0.2.12"
num = "0.4"
rand = { version = "0.10.1", default-features = false, features = ["alloc"] }
Expand Down Expand Up @@ -55,6 +56,9 @@ serde = ["dep:serde", "dep:typetag"]
# Optional bindings for the ndarray crate (DenseMatrix <-> ndarray).
ndarray-bindings = ["dep:ndarray"]

# Apply Lasso and Elastic Net normalization without copying the design matrix.
lazy-normalization = ["dep:lazymatrix"]

# Sample datasets (iris, boston, digits, ...) and dataset generators.
# Enables serde because datasets ship serialized bundles. Does not enable
# std_rand: the generators use the crate RNG (SmallRng without std_rand).
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,29 @@ smartcore organizes algorithms into clear modules with consistent traits:

Recent refactors emphasize reusable components in trees/forests and expanded multiclass SVM capabilities. XGBoost-style regression and single-linkage clustering have been added. See CHANGELOG for API changes and migration notes.

## Optional lazy normalization

The optional `lazy-normalization` feature lets Lasso and Elastic Net borrow the
design matrix during normalization. Elastic Net also applies its identity-block
augmentation without storing the augmented design. Enable it with `features =
["lazy-normalization"]`, then select it with
`LassoParameters::default().with_lazy_normalization(true)` or
`ElasticNetParameters::default().with_lazy_normalization(true)`. The default
remains eager, even when the feature is enabled. The `normalize` option still
controls whether columns are centered and scaled. Parameter searches use the
fixed `lazy_normalization` setting. It works with `DenseMatrix` and
`ndarray-bindings`.

Lazy normalization reduces memory use by computing normalized values when the
solver needs them. This adds repeated arithmetic and can increase fit time for
both estimators, including Elastic Net on large inputs. The solver still stores
a dense Gram matrix with one row and column per feature.

Enabling the feature adds a public `lazy_normalization` field to both estimators'
parameter and search parameter structs. Code that constructs these structs
without `..Default::default()` must add the field. Missing fields default to
`false` during deserialization.

## Data access and readers

- CSV readers: Read matrices from CSV with configurable delimiter and header rows, with helpful error messages and testing utilities (including non-IO reader abstractions).
Expand Down
Loading
Loading