Skip to content

Commit bf573bc

Browse files
Merge pull request #10 from MatthewSZhang/docs
DOC add examples
2 parents 10a32a9 + 36a9c99 commit bf573bc

22 files changed

+2640
-936
lines changed

.readthedocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ python:
1111
install:
1212
- method: pip
1313
path: .
14-
extra_requirements: [doc]
14+
extra_requirements: [docs]

README.rst

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
FastCan: A Fast Canonical-Correlation-Based Feature Selection Method
2-
====================================================================
1+
FastCan: A Fast Canonical-Correlation-Based Feature Selection Algorithm
2+
=======================================================================
33
|conda| |Codecov| |CI| |Doc| |PythonVersion| |PyPi| |Black| |ruff| |pixi|
44

55
.. |conda| image:: https://img.shields.io/conda/vn/conda-forge/fastcan.svg
@@ -29,6 +29,18 @@ FastCan: A Fast Canonical-Correlation-Based Feature Selection Method
2929
.. |pixi| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/prefix-dev/pixi/main/assets/badge/v0.json&style=flat-square
3030
:target: https://pixi.sh
3131

32+
FastCan is a feature selection method, which has following advantages:
33+
34+
#. Extremely **fast**. See :ref:`sphx_glr_auto_examples_plot_speed.py`.
35+
36+
#. Support unsupervised feature selection. See :ref:`Unsupervised feature selection <unsupervised>`.
37+
38+
#. Support multioutput feature selection. See :ref:`Multioutput feature selection <multioutput>`.
39+
40+
#. Skip redundant features. See :ref:`Feature redundancy <redundancy>`.
41+
42+
#. Evalaute relative usefulness of features. See :ref:`sphx_glr_auto_examples_plot_intuitive.py`.
43+
3244

3345
Installation
3446
------------
@@ -41,25 +53,22 @@ Or via conda-forge:
4153

4254
* Run ``conda install -c conda-forge fastcan``
4355

44-
Examples
45-
--------
56+
Getting Started
57+
---------------
4658
>>> from fastcan import FastCan
47-
>>> X = [[ 0.87, -1.34, 0.31 ],
48-
... [-2.79, -0.02, -0.85 ],
49-
... [-1.34, -0.48, -2.55 ],
50-
... [ 1.92, 1.48, 0.65 ]]
51-
>>> y = [0, 1, 0, 1]
52-
>>> selector = FastCan(n_features_to_select=2, verbose=0).fit(X, y)
53-
>>> selector.get_support()
54-
array([ True, True, False])
59+
>>> X = [[1, 0], [0, 1]]
60+
>>> y = [1, 0]
61+
>>> FastCan(verbose=0).fit(X, y).get_support()
62+
array([ True, False])
5563

64+
Check :ref:`User Guild <user_guide>` and :ref:`Examples <examples>` for more information.
5665

5766
Citation
5867
--------
5968

6069
FastCan is a Python implementation of the following papers.
6170

62-
If you use the `h-correlation` algorithm in your work please cite the following reference:
71+
If you use the `h-correlation` method in your work please cite the following reference:
6372

6473
.. code:: bibtex
6574
@@ -76,7 +85,7 @@ If you use the `h-correlation` algorithm in your work please cite the following
7685
keywords = {Feature selection, Orthogonal least squares, Canonical correlation analysis, Linear discriminant analysis, Multi-label, Multivariate time series, Feature interaction},
7786
}
7887
79-
If you use the `eta-cosine` algorithm in your work please cite the following reference:
88+
If you use the `eta-cosine` method in your work please cite the following reference:
8089

8190
.. code:: bibtex
8291

doc/conf.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
"sphinx.ext.napoleon",
4141
# Link to other project's documentation (see mapping below)
4242
"sphinx.ext.intersphinx",
43+
"sphinx_gallery.gen_gallery",
44+
"sphinx_design",
4345
]
4446

4547
# List of patterns, relative to source directory, that match files and
@@ -67,14 +69,7 @@
6769
"sklearn": ("https://scikit-learn.org/stable", None),
6870
}
6971

70-
# add substitutions that should be available in every file
71-
rst_prolog = """
72-
.. |numpy_dtype| replace:: numpy data type
73-
.. _numpy_dtype: https://numpy.org/doc/stable/user/basics.types.html
74-
75-
.. |sklearn_cython_dtype| replace:: sklearn cython data type
76-
.. _sklearn_cython_dtype: https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_typedefs.pxd
77-
78-
.. |sphinx_link| replace:: rst Markup Spec
79-
.. _sphinx_link: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html
80-
"""
72+
sphinx_gallery_conf = {
73+
"examples_dirs": ["../examples"],
74+
"gallery_dirs": ["auto_examples"],
75+
}

doc/index.rst

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,24 @@
1313

1414

1515
API Reference
16-
~~~~~~~~~~~~~
16+
-------------
1717
.. autosummary::
1818
:toctree: generated/
1919

2020
FastCan
2121
ssc
22+
ols
2223

24+
Useful Links
25+
------------
26+
.. toctree::
27+
:maxdepth: 2
2328

24-
...................
29+
User Guild <user_guide>
30+
Examples <auto_examples/index>
31+
32+
API Compatibility
33+
-----------------
2534

2635
The API of this package is align with scikit-learn.
2736

doc/multioutput.rst

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
.. currentmodule:: fastcan
2+
3+
.. _multioutput:
4+
5+
==============================
6+
Multioutput feature selection
7+
==============================
8+
9+
We can use :class:`FastCan` to handle multioutput feature selection, which means
10+
target ``y`` can be a matrix. For regression, :class:`FastCan` can be used for
11+
MIMO (Multi-Input Multi-Output) data. For classification, it can be used for
12+
multilabel data. Actually, for multiclass classification, which has one output with
13+
multiple categories, multioutput feature selection can also be useful. The multiclass
14+
classification can be converted to multilabel classification by one-hot encoding
15+
target ``y``. The cannonical correaltion coefficient between the features ``X`` and the
16+
one-hot encoded target ``y`` has equivalent relationship with Fisher's criterion in
17+
LDA (Linear Discriminant Analysis) [1]_. Applying :class:`FastCan` to the converted
18+
multioutput data may result in better accuracy in the following classification task
19+
than applying it directly to the original single-label data. See Figure 5 in [2]_.
20+
21+
Relationship on multiclass data
22+
-------------------------------
23+
Assume the feature matrix is :math:`X \in \mathbb{R}^{N\times n}`, the multiclass
24+
target vector is :math:`y \in \mathbb{R}^{N\times 1}`, and the one-hot encoded target
25+
matrix is :math:`Y \in \mathbb{R}^{N\times m}`. Then, the Fisher's criterion for
26+
:math:`X` and :math:`y` is denoted as :math:`J` and the canonical correaltion
27+
coefficient between :math:`X` and :math:`Y` is denoted as :math:`R`. The relationship
28+
between :math:`J` and :math:`R` is given by
29+
30+
.. math::
31+
J = \frac{R^2}{1-R^2}
32+
33+
or
34+
35+
.. math::
36+
R^2 = \frac{J}{1+J}
37+
38+
It should be noted that the number of the Fisher's criterion and the canonical
39+
correaltion coefficient is not only one. The number of the non-zero canonical
40+
correlation coefficients is no more than :math:`\min (n, m)`, and each canonical correlation
41+
coefficient is one-to-one correspondence to each Fisher's criterion.
42+
43+
.. rubric:: References
44+
45+
.. [1] `"Orthogonal least squares based fast feature selection for
46+
linear classification" <https://doi.org/10.1016/j.patcog.2021.108419>`_
47+
Zhang, S., & Lang, Z. Q. Pattern Recognition, 123, 108419 (2022).
48+
49+
.. [2] `"Canonical-correlation-based fast feature selection for structural
50+
health monitoring" <https://doi.org/10.1016/j.ymssp.2024.111895>`_
51+
Zhang, S., Wang, T., Worden, K., Sun L., & Cross, E. J.
52+
Mechanical Systems and Signal Processing, 223, 111895 (2025).
53+
54+
.. rubric:: Examples
55+
56+
* See :ref:`sphx_glr_auto_examples_plot_fisher.py` for an example of
57+
the equivalent relationship between CCA and LDA on multiclass data.

doc/ols_and_omp.rst

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
.. currentmodule:: fastcan
2+
3+
.. _ols_omp:
4+
5+
===========================
6+
Comparison with OLS and OMP
7+
===========================
8+
9+
:class:`FastCan` has a close relationship with Orthogonal Least Squares (OLS) [1]_
10+
and Orthogonal Matching Pursuit (OMP) [2]_.
11+
The detailed difference between OLS and OMP can be found in [3]_.
12+
Here, let's briefly compare the three methods.
13+
14+
15+
Assume we have a feature matrix :math:`X_s \in \mathbb{R}^{N\times t}`, which constains
16+
:math:`t` selected features, and a target vector :math:`y \in \mathbb{R}^{N\times 1}`.
17+
Then the residual :math:`r \in \mathbb{R}^{N\times 1}` of the least-squares can be
18+
found by
19+
20+
.. math::
21+
r = y - X_s \beta \;\; \text{where} \;\; \beta = (X_s^\top X_s)^{-1}X_s^\top y
22+
23+
When evaluating a new candidate feature :math:`x_i \in \mathbb{R}^{N\times 1}`
24+
25+
* for OMP, the feature which maximizes :math:`r^\top x_i` will be selected,
26+
* for OLS, the feature which maximizes :math:`r^\top w_i` will be selected, where
27+
:math:`w_i \in \mathbb{R}^{N\times 1}` is the projection of :math:`x_i` on the
28+
orthogonal subspace so that it is orthogonal to :math:`X_s`, i.e.,
29+
:math:`X_s^\top w_i = \mathbf{0} \in \mathbb{R}^{t\times 1}`,
30+
* for :class:`FastCan` (h-correlation algorithm), it is almost same as OLS, but the
31+
difference is that in :class:`FastCan`, :math:`X_s`, :math:`y`, and :math:`x_i`
32+
are centered (i.e., zero mean in each column) before the selection.
33+
34+
The small difference makes the feature ranking criterion of :class:`FastCan` is
35+
equivalent to the sum of squared canonical correlation coefficients, which gives
36+
it the following advantages over OLS and OMP:
37+
38+
* Affine invariance: if features are polluted by affine transformation, i.e., scaled
39+
and/or added some constants, the selection result given by :class:`FastCan` will be
40+
unchanged. See :ref:`sphx_glr_auto_examples_plot_affinity.py`.
41+
* Multioutput: as :class:`FastCan` use canonical correlation for feature ranking, it is
42+
naturally support feature seleciton on dataset with multioutput.
43+
44+
45+
.. rubric:: References
46+
47+
.. [1] `"Orthogonal least squares methods and their application to non-linear
48+
system identification" <https://doi.org/10.1080/00207178908953472>`_ Chen, S.,
49+
Billings, S. A., & Luo, W. International Journal of control, 50(5),
50+
1873-1896 (1989).
51+
52+
.. [2] `"Matching pursuits with time-frequency dictionaries"
53+
<https://doi.org/10.1109/78.258082>`_ Mallat, S. G., & Zhang, Z.
54+
IEEE Transactions on signal processing, 41(12), 3397-3415 (1993).
55+
56+
.. [3] `"On the difference between Orthogonal Matching Pursuit and Orthogonal Least
57+
Squares" <https://eprints.soton.ac.uk/142469/1/BDOMPvsOLS07.pdf>`_ Blumensath, T.,
58+
& Davies, M. E. Technical report, University of Edinburgh, (2007).

doc/redundancy.rst

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
.. currentmodule:: fastcan
2+
3+
.. _redundancy:
4+
5+
==================
6+
Feature redundancy
7+
==================
8+
9+
:class:`FastCan` can effectively skip the linearly redundant features.
10+
Here a feature :math:`x_r\in \mathbb{R}^{N\times 1}` is linearly
11+
redundant to a set of features :math:`X\in \mathbb{R}^{N\times n}` means that
12+
:math:`x_r` can be obtained from an affine transformation of :math:`X`, given by
13+
14+
.. math::
15+
x_r = Xa + b
16+
17+
where :math:`a\in \mathbb{R}^{n\times 1}` and :math:`b\in \mathbb{R}^{N\times 1}`.
18+
In other words, the feature can be acquired by a linear transformation of :math:`X`,
19+
i.e. :math:`Xa`, and a translation, i.e. :math:`+b`.
20+
21+
This capability of :class:`FastCan` is benefited from the
22+
`Modified Gram-Schmidt <https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process>`_,
23+
which gives large rounding-errors when linearly redundant features appears.
24+
25+
.. rubric:: References
26+
27+
* `"Canonical-correlation-based fast feature selection for structural
28+
health monitoring" <https://doi.org/10.1016/j.ymssp.2024.111895>`_
29+
Zhang, S., Wang, T., Worden, K., Sun L., & Cross, E. J.
30+
Mechanical Systems and Signal Processing, 223, 111895 (2025).
31+
32+
.. rubric:: Examples
33+
34+
* See :ref:`sphx_glr_auto_examples_plot_redundancy.py` for an example of
35+
feature selection on datasets with redundant features.

doc/unsupervised.rst

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
.. currentmodule:: fastcan
2+
3+
.. _unsupervised:
4+
5+
==============================
6+
Unsupervised feature selection
7+
==============================
8+
9+
We can use :class:`FastCan` to do unsupervised feature selection.
10+
The unsupervised application of :class:`FastCan` tries to select features, which
11+
maximize the sum of the squared canonical correlation (SSC) with the principal
12+
components (PCs) acquired from PCA (principal component analysis) of the feature
13+
matrix :math:`X`. See the example below.
14+
15+
>>> from sklearn.decomposition import PCA
16+
>>> from sklearn import datasets
17+
>>> from fastcan import FastCan
18+
>>> iris = datasets.load_iris()
19+
>>> X = iris["data"]
20+
>>> pca = PCA(n_components=2)
21+
>>> X_pcs = pca.fit_transform(X)
22+
>>> selector = FastCan(n_features_to_select=2, verbose=0).fit(X, X_pcs[:, :2])
23+
>>> selector.indices_
24+
array([2, 1], dtype=int32)
25+
26+
.. note::
27+
There is no guarantee that this unsupervised :class:`FastCan` will select
28+
the optimal subset of the features, which has the highest SSC with PCs.
29+
Because :class:`FastCan` selects features in a greedy manner, which may lead to
30+
suboptimal results.
31+
32+
.. rubric:: References
33+
34+
* `"Automatic Selection of Optimal Structures for Population-Based
35+
Structural Health Monitoring" <https://doi.org/10.1007/978-3-031-34946-1_10>`_
36+
Wang, T., Worden, K., Wagg, D.J., Cross, E.J., Maguire, A.E., Lin, W.
37+
In: Conference Proceedings of the Society for Experimental Mechanics Series.
38+
Springer, Cham. (2023).

doc/user_guide.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.. _user_guide:
2+
3+
==========
4+
User Guide
5+
==========
6+
7+
.. toctree::
8+
:numbered:
9+
:maxdepth: 1
10+
11+
unsupervised.rst
12+
multioutput.rst
13+
redundancy.rst
14+
ols_and_omp.rst

examples/README.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.. _examples:
2+
3+
Examples
4+
========
5+
6+
Below is a gallery of examples.

0 commit comments

Comments
 (0)