Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
c31b921
Merge pull request #49 from scikit-learn-contrib/0.3.X
MatthewSZhang Feb 21, 2025
ba0351d
CI add test for macos and windows
MatthewSZhang Feb 27, 2025
cf5b913
CI replace uv with pip
MatthewSZhang Feb 27, 2025
42307f0
CI avoid meson use MINGW64 but MSVC
MatthewSZhang Feb 27, 2025
e5c4b35
CI test nogil
MatthewSZhang Feb 27, 2025
561f855
Merge pull request #52 from MatthewSZhang/beam
MatthewSZhang Feb 27, 2025
b389610
FEAT make NARX accept multi-output
MatthewSZhang Mar 14, 2025
b1363f0
Merge pull request #54 from MatthewSZhang/multi-output
MatthewSZhang Mar 14, 2025
413baa2
DOC fix warning message in plot_narx_msa
MatthewSZhang Mar 17, 2025
e6ed426
Merge pull request #62 from MatthewSZhang/multi-output
MatthewSZhang Mar 17, 2025
11dfe3d
DOC add multi-output narx example
MatthewSZhang Mar 19, 2025
32b9809
Add plot_narx_multi.py
MatthewSZhang Mar 19, 2025
357b22f
Merge pull request #64 from MatthewSZhang/narx-mulit-doc
MatthewSZhang Mar 19, 2025
f7ff796
FEAT add jac for narx
MatthewSZhang Mar 31, 2025
539fa28
TST add divergence test for narx
MatthewSZhang Apr 1, 2025
ec54175
CI adopt new pixi (0.43.0) reinstall to replace manually rebuild
MatthewSZhang Apr 1, 2025
9c5bfba
MNT improve readability of grad and change grad of minimize to grad o…
MatthewSZhang Apr 1, 2025
6f882fd
MNT fix wrong grad when having missing values
MatthewSZhang Apr 3, 2025
ee26c61
MNT fix poor msa narx results on windows
MatthewSZhang Apr 7, 2025
183d8cc
FEAT add fd2tp and tp2fd
MatthewSZhang Apr 7, 2025
6efac05
Merge pull request #66 from MatthewSZhang/narx-jac
MatthewSZhang Apr 7, 2025
84b2f83
FEAT add time-narx to evaluate opt speed of narx fit
MatthewSZhang Apr 7, 2025
993a9ed
Merge pull request #70 from MatthewSZhang/narx-speed
MatthewSZhang Apr 7, 2025
70536ac
ENH speed up grad computation via Cython
MatthewSZhang Apr 9, 2025
74ed9b2
MNT fix time-narx put all code in setup and timing empty
MatthewSZhang Apr 9, 2025
b96534e
MNT fix nogil-h, nogil-eta put all code in setup and timing empty
MatthewSZhang Apr 9, 2025
820f4e6
Merge pull request #71 from MatthewSZhang/narx-cython
MatthewSZhang Apr 9, 2025
727a676
MNT output proper constant when some outputs only have intercepts
MatthewSZhang Apr 10, 2025
7ed5825
Merge pull request #73 from MatthewSZhang/multi-output
MatthewSZhang Apr 10, 2025
4172a64
MNT add error that some
MatthewSZhang Apr 11, 2025
74dbde9
Merge pull request #75 from MatthewSZhang/all-minus-one
MatthewSZhang Apr 11, 2025
340bc3c
TST add equivalence check for sample weights
MatthewSZhang Apr 11, 2025
be0dc25
Merge pull request #76 from MatthewSZhang/sw-test
MatthewSZhang Apr 11, 2025
3aecd2b
FEAT add param fit_intercept for NARX
MatthewSZhang Apr 17, 2025
55f6e35
Merge pull request #78 from MatthewSZhang/test-print
MatthewSZhang Apr 17, 2025
93a60cb
TST test printed message
MatthewSZhang May 6, 2025
5d24418
MNT fix pytest on win
MatthewSZhang May 6, 2025
3cd37be
MNT specify pixi reinstall -e
MatthewSZhang May 6, 2025
4f993dd
MNT use pip force-reinstall replacing pixi reinstall
MatthewSZhang May 6, 2025
594a660
MNT add -Csetup-args=--vsenv for pixi reinstall
MatthewSZhang May 6, 2025
c939d8c
Merge pull request #79 from MatthewSZhang/test-print
MatthewSZhang May 6, 2025
4006c59
FEAT add mask_missing_values in utils
MatthewSZhang May 8, 2025
a88a460
Merge pull request #81 from MatthewSZhang/missing-values
MatthewSZhang May 8, 2025
bd893cb
MNT black to ruff
MatthewSZhang May 15, 2025
6cb7173
CI build-sdist should after test
MatthewSZhang May 15, 2025
bc9fdf4
Merge pull request #83 from MatthewSZhang/ruff-formatter
MatthewSZhang May 15, 2025
bd1a21c
MNT add codespell
MatthewSZhang May 15, 2025
67a7af8
Merge pull request #85 from MatthewSZhang/codespell
MatthewSZhang May 15, 2025
20c3780
DOC add pca plot for data pruning example
MatthewSZhang May 16, 2025
3fddec5
Merge pull request #86 from MatthewSZhang/prune-pca
MatthewSZhang May 16, 2025
c249e29
DOC remove as_frame to avoide readthedocs install pandas
MatthewSZhang May 16, 2025
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
5 changes: 5 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Checklist

- [ ] Used a personal fork to propose changes
- [ ] A reference to a related issue:
- [ ] A description of the changes
27 changes: 23 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,29 @@ jobs:
call-test:
uses: ./.github/workflows/test.yml
secrets: inherit

build-sdist:
runs-on: ubuntu-latest
needs: call-test
steps:
- uses: actions/checkout@v4
- uses: prefix-dev/[email protected]
with:
environments: dev
cache: true
- name: Re-install local
run: |
pixi reinstall -e dev --frozen fastcan
- name: Build SDist
run: |
pixi run build-sdist
- name: Store artifacts
uses: actions/upload-artifact@v4
with:
name: cibw-sdist
path: dist/*.tar.gz

build:
build-wheels:
strategy:
fail-fast: false
matrix:
Expand All @@ -22,7 +43,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Build wheels
uses: pypa/cibuildwheel@v2.22.0
uses: pypa/cibuildwheel@v2.23.3
env:
CIBW_BUILD: cp3*-*
CIBW_SKIP: pp* *i686* *musllinux* *-macosx_universal2 *-manylinux_ppc64le *-manylinux_s390x
Expand All @@ -31,8 +52,6 @@ jobs:
CIBW_ARCHS_MACOS: x86_64 arm64
CIBW_ARCHS_WINDOWS: auto64
CIBW_BEFORE_ALL_LINUX: yum install -y ninja-build python3-devel
CIBW_BEFORE_ALL_WINDOWS: choco install ninja
CIBW_BEFORE_ALL_MACOS: brew install ninja
# Needed on Windows CI to compile with Visual Studio compiler
# otherwise Meson detects a MINGW64 platform and use MINGW64
# toolchain
Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/static.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Static

on:
workflow_call:

jobs:
static:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: prefix-dev/[email protected]
with:
environments: static
cache: true

- name: Re-install local
run: |
pixi reinstall -e static --frozen fastcan

- name: Linter
run: |
pixi run lint
- name: Lint Cython
run: |
pixi run cython-lint
- name: Formatter
run: |
pixi run fmt
- name: Type check
run: |
pixi run type
- name: Spell check
run: |
pixi run spell
43 changes: 19 additions & 24 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,30 @@ on:
branches: ["*.X"]

jobs:
call-lint:
uses: ./.github/workflows/static.yml

test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
- uses: prefix-dev/[email protected].3
- uses: prefix-dev/[email protected].8
with:
environments: default
environments: dev
cache: true

- name: Re-install local
run: |
pixi run rebuild
# Needed on Windows CI to compile with Visual Studio compiler
# otherwise Meson detects a MINGW64 platform and use MINGW64
# toolchain
pixi reinstall -e dev --frozen fastcan -- -Csetup-args=--vsenv

- name: Lint with ruff
run: |
pixi run lint
- name: Lint with cython-lint
run: |
pixi run cython-lint
- name: Format with black
run: |
pixi run fmt
- name: Type check with mypy
run: |
pixi run type
- name: Test with pytest
run: |
pixi run test
Expand All @@ -42,19 +40,16 @@ jobs:
run: |
pixi run doc
CMD=doctest pixi run doc
- name: Test nogil
run: |
pixi run nogil-eta
- name: Test coverage
if: runner.os == 'Linux'
shell: bash
run: |
FMT=xml pixi run test-coverage
- name: Upload coverage reports to Codecov
if: runner.os == 'Linux'
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Build SDist
run: |
pixi run build-sdist
- name: Store artifacts
uses: actions/upload-artifact@v4
with:
name: cibw-sdist
path: dist/*.tar.gz
2 changes: 1 addition & 1 deletion doc/multioutput.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ MIMO (Multi-Input Multi-Output) data. For classification, it can be used for
multilabel data. Actually, for multiclass classification, which has one output with
multiple categories, multioutput feature selection can also be useful. The multiclass
classification can be converted to multilabel classification by one-hot encoding
target ``y``. The cannonical correaltion coefficient between the features ``X`` and the
target ``y``. The canonical correaltion coefficient between the features ``X`` and the
one-hot encoded target ``y`` has equivalent relationship with Fisher's criterion in
LDA (Linear Discriminant Analysis) [1]_. Applying :class:`FastCan` to the converted
multioutput data may result in better accuracy in the following classification task
Expand Down
2 changes: 1 addition & 1 deletion doc/narx.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ It should also be noted the different types of predictions in model training.
ARX and OE model
----------------

To better understant the two types of training, it is helpful to know two linear time series model structures,
To better understand the two types of training, it is helpful to know two linear time series model structures,
i.e., `ARX (AutoRegressive eXogenous) model <https://www.mathworks.com/help/ident/ref/arx.html>`_ and
`OE (output error) model <https://www.mathworks.com/help/ident/ref/oe.html>`_.

Expand Down
2 changes: 1 addition & 1 deletion doc/ols_and_omp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The detailed difference between OLS and OMP can be found in [3]_.
Here, let's briefly compare the three methods.


Assume we have a feature matrix :math:`X_s \in \mathbb{R}^{N\times t}`, which constains
Assume we have a feature matrix :math:`X_s \in \mathbb{R}^{N\times t}`, which contains
:math:`t` selected features, and a target vector :math:`y \in \mathbb{R}^{N\times 1}`.
Then the residual :math:`r \in \mathbb{R}^{N\times 1}` of the least-squares can be
found by
Expand Down
4 changes: 2 additions & 2 deletions doc/pruning.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ should be selected, as any additional samples can be represented by linear combi
Therefore, the number to select has to be set to small.

To solve this problem, we use :func:`minibatch` to loose the redundancy check of :class:`FastCan`.
The original :class:`FastCan` checks the redunancy within :math:`X_s \in \mathbb{R}^{n\times t}`,
The original :class:`FastCan` checks the redundancy within :math:`X_s \in \mathbb{R}^{n\times t}`,
which contains :math:`t` selected samples and n features,
and the redunancy within :math:`Y \in \mathbb{R}^{n\times m}`, which contains :math:`m` atoms :math:`y_i`.
and the redundancy within :math:`Y \in \mathbb{R}^{n\times m}`, which contains :math:`m` atoms :math:`y_i`.
:func:`minibatch` ranks samples with multiple correlation coefficients between :math:`X_b \in \mathbb{R}^{n\times b}` and :math:`y_i`,
where :math:`b` is batch size and :math:`b <= t`, instead of canonical correlation coefficients between :math:`X_s` and :math:`Y`,
which is used in :class:`FastCan`.
Expand Down
2 changes: 1 addition & 1 deletion examples/plot_fisher.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

.. currentmodule:: fastcan

In this examples, we will demonstrate the cannonical correaltion coefficient
In this examples, we will demonstrate the canonical correaltion coefficient
between the features ``X`` and the one-hot encoded target ``y`` has equivalent
relationship with Fisher's criterion in LDA (Linear Discriminant Analysis).
"""
Expand Down
10 changes: 5 additions & 5 deletions examples/plot_intuitive.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
# the predicted target by a linear regression model) and the target to describe its
# usefulness, the results are shown in the following figure. It can be seen that
# Feature 2 is the most useful and Feature 8 is the second. However, does that mean
# that the total usefullness of Feature 2 + Feature 8 is the sum of their R-squared
# that the total usefulness of Feature 2 + Feature 8 is the sum of their R-squared
# scores? Probably not, because there may be redundancy between Feature 2 and Feature 8.
# Actually, what we want is a kind of usefulness score which has the **superposition**
# property, so that the usefullness of each feature can be added together without
# property, so that the usefulness of each feature can be added together without
# redundancy.

import matplotlib.pyplot as plt
Expand Down Expand Up @@ -125,7 +125,7 @@ def plot_bars(ids, r2_left, r2_selected):
# Select the third feature
# ------------------------
# Again, let's compute the R-squared between Feature 2 + Feature 8 + Feature i and
# the target, and the additonal R-squared contributed by the rest of the features is
# the target, and the additional R-squared contributed by the rest of the features is
# shown in following figure. It can be found that after selecting Features 2 and 8, the
# rest of the features can provide a very limited contribution.

Expand All @@ -145,8 +145,8 @@ def plot_bars(ids, r2_left, r2_selected):
# at the RHS of the dashed lines. The fast computational speed is achieved by
# orthogonalization, which removes the redundancy between the features. We use the
# orthogonalization first to makes the rest of features orthogonal to the selected
# features and then compute their additonal R-squared values. ``eta-cosine`` uses
# the samilar idea, but has an additonal preprocessing step to compress the features
# features and then compute their additional R-squared values. ``eta-cosine`` uses
# the similar idea, but has an additional preprocessing step to compress the features
# :math:`X \in \mathbb{R}^{N\times n}` and the target
# :math:`X \in \mathbb{R}^{N\times n}` to :math:`X_c \in \mathbb{R}^{(m+n)\times n}`
# and :math:`Y_c \in \mathbb{R}^{(m+n)\times m}`.
Expand Down
11 changes: 7 additions & 4 deletions examples/plot_narx.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,14 @@
# In the printed NARX model, it is found that :class:`FastCan` selects the correct
# terms and the coefficients are close to the true values.

from fastcan.narx import NARX, print_narx
from fastcan.narx import NARX, print_narx, tp2fd

# Convert poly_ids and time_shift_ids to feat_ids and delay_ids
feat_ids, delay_ids = tp2fd(time_shift_ids, selected_poly_ids)

narx_model = NARX(
time_shift_ids=time_shift_ids,
poly_ids=selected_poly_ids,
feat_ids=feat_ids,
delay_ids=delay_ids,
)

narx_model.fit(X, y)
Expand All @@ -145,7 +148,7 @@
auto_narx_model = make_narx(
X=X,
y=y,
n_features_to_select=4,
n_terms_to_select=4,
max_delay=3,
poly_degree=2,
verbose=0,
Expand Down
17 changes: 10 additions & 7 deletions examples/plot_narx_msa.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# Nonlinear system
# ----------------
#
# `Duffing equation <https://en.wikipedia.org/wiki/Duffing_equation>` is used to
# `Duffing equation <https://en.wikipedia.org/wiki/Duffing_equation>`_ is used to
# generate simulated data. The mathematical model is given by
#
# .. math::
Expand Down Expand Up @@ -82,15 +82,18 @@ def auto_duffing_equation(y, t):
dur = 10
n_samples = 1000

rng = np.random.default_rng(12345)
e_train = rng.normal(0, 0.0002, n_samples)
e_test = rng.normal(0, 0.0002, n_samples)
t = np.linspace(0, dur, n_samples)

sol = odeint(duffing_equation, [0.6, 0.8], t)
u_train = 2.5 * np.cos(2 * np.pi * t).reshape(-1, 1)
y_train = sol[:, 0]
y_train = sol[:, 0] + e_train

sol = odeint(auto_duffing_equation, [0.6, -0.8], t)
sol = odeint(duffing_equation, [0.6, -0.8], t)
u_test = 2.5 * np.cos(2 * np.pi * t).reshape(-1, 1)
y_test = sol[:, 0]
y_test = sol[:, 0] + e_test

# %%
# One-step-head VS. multi-step-ahead NARX
Expand All @@ -105,12 +108,12 @@ def auto_duffing_equation(y, t):

from fastcan.narx import make_narx

max_delay = 2
max_delay = 3

narx_model = make_narx(
X=u_train,
y=y_train,
n_features_to_select=10,
n_terms_to_select=5,
max_delay=max_delay,
poly_degree=3,
verbose=0,
Expand Down Expand Up @@ -159,7 +162,7 @@ def plot_prediction(ax, t, y_true, y_pred, title):
narx_model = make_narx(
X=u_all,
y=y_all,
n_features_to_select=10,
n_terms_to_select=5,
max_delay=max_delay,
poly_degree=3,
verbose=0,
Expand Down
Loading