Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/qae #36

Merged
merged 36 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
e2dbf3c
add autoencoder based on qiskit-ml example: https://qiskit.org/ecosys…
gcattan Jan 26, 2024
f20c173
set up example with autoencoder.
gcattan Jan 27, 2024
4d6bf09
add dataset from https://zenodo.org/records/5055046 (partially implem…
gcattan Jan 27, 2024
032f7f3
change localisation of the dataset.
gcattan Jan 27, 2024
092540f
apply denoising on raw signal
gcattan Jan 28, 2024
5609426
reduce epoch dimension
gcattan Jan 29, 2024
ddadd12
update pipeline
gcattan Feb 3, 2024
160a8b8
update optimizer
gcattan Mar 22, 2024
c3e86b6
add rs and fix some bugs
gcattan Apr 28, 2024
19db89e
add epochselectchannel
gcattan Apr 28, 2024
d617d7a
doc
gcattan Apr 28, 2024
50bacea
improve code for channel selection
gcattan Apr 28, 2024
bac085f
expose qaoa optimizer
gcattan May 9, 2024
4ccb290
push example
gcattan May 9, 2024
932b745
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 9, 2024
88b83d9
typo in example
gcattan May 9, 2024
1f7e63f
fix Attributes section duplicated
gcattan May 9, 2024
58d1f3f
Merge branch 'main' into feat/qae
gcattan May 16, 2024
743cd00
use moabb Hinss2021
gcattan May 16, 2024
d9f1675
autoencoder.py
gcattan May 16, 2024
6837067
refactor autoencoder, add documentation
gcattan May 16, 2024
1c768c3
Complete documentation
gcattan May 16, 2024
fe418a0
extract devectorizer to preprocessing.py WIP
gcattan May 16, 2024
acd3b68
documentation for devectorizer
gcattan May 17, 2024
4957bad
complete doc for EpochSelectChannel
gcattan May 17, 2024
5a8b4a3
refactor qword example. Do not use xDawn.
gcattan May 17, 2024
590c4f4
fix bug with spatial filter
gcattan May 17, 2024
152151b
add callback parameter
gcattan May 17, 2024
3bd6535
Merge branch 'main' into feat/qae
gcattan May 17, 2024
b1a3fe7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 17, 2024
6654386
typo
gcattan May 17, 2024
b8d179c
flake8
gcattan May 17, 2024
7dbebbb
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 17, 2024
b652891
typo
gcattan May 17, 2024
0c3d304
flake8
gcattan May 17, 2024
65ccb40
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 17, 2024
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
16 changes: 15 additions & 1 deletion doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ Classification
NearestConvexHull


Autoencoders
-------------
.. _autoencoders_api:
.. currentmodule:: pyriemann_qiskit.autoencoders

.. autosummary::
:toctree: generated/
:template: class.rst

BasicQnnAutoencoder


Pipelines
---------
.. _pipelines_api:
Expand Down Expand Up @@ -88,6 +100,8 @@ Preprocessing
:toctree: generated/

NdRobustScaler
Vectorizer
Devectorizer

Filtering
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -99,7 +113,7 @@ Filtering

NoDimRed
NaiveDimRed
Vectorizer
EpochChannelSelection

Mean
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
191 changes: 191 additions & 0 deletions examples/ERP/autoencoders_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
"""
This is a basic example of a quantum autoencoder for signal denoising,
based on [1]_ and [2]_.

There is no particular advantage in using QNN for such a task.

This is experimental and should be used for research purpose only.

"""

# Authors: A. Mostafa, Y. Chauhan, W. Ahmed, and G. Cattan
# License: BSD (3-clause)

from matplotlib import pyplot as plt
import warnings
import seaborn as sns
from moabb import set_log_level
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.pipeline import make_pipeline
from pyriemann.tangentspace import TangentSpace
from moabb.datasets import Hinss2021
from moabb.evaluations import CrossSessionEvaluation
from moabb.paradigms import RestingStateToP300Adapter
from pyriemann_qiskit.autoencoders import BasicQnnAutoencoder
from pyriemann_qiskit.utils.preprocessing import Vectorizer, Devectorizer
from pyriemann_qiskit.utils.filtering import EpochChannelSelection
from pyriemann.estimation import Covariances
from qiskit_algorithms.optimizers import COBYLA

import logging

print(__doc__)

##############################################################################
# getting rid of the warnings about the future

warnings.simplefilter(action="ignore", category=FutureWarning)
warnings.simplefilter(action="ignore", category=RuntimeWarning)

warnings.filterwarnings("ignore")

set_log_level("info")

##############################################################################
# Setting logger level to info, to print the autoencoder trace.

logging.getLogger("root").setLevel(logging.INFO)

##############################################################################
# Initialization
# ----------------
#
# 1) Create paradigm
# 2) Load datasets

events = dict(easy=2, medium=3)
paradigm = RestingStateToP300Adapter(events=events, tmin=0, tmax=0.5)

datasets = [Hinss2021()]

# reduce the number of subjects, the Quantum pipeline takes a lot of time
# if executed on the entire dataset
start_subject, stop_subject = 14, 15
title = "Datasets: "
for dataset in datasets:
title = title + " " + dataset.code
dataset.subject_list = dataset.subject_list[start_subject:stop_subject]

##############################################################################
# We have to do this because the classes are called 'Target' and 'NonTarget'
# but the evaluation function uses a LabelEncoder, transforming them
# to 0 and 1
labels_dict = {"Target": 1, "NonTarget": 0}

##############################################################################
# Define a callback to keep trace of the computed costs.

costs = {}


def fn_callback(iter, cost):
if iter in costs:
costs[iter].append(cost)
else:
costs[iter] = [cost]


##############################################################################
# Create Pipelines
# ----------------
#
# Pipelines must be a dict of sklearn pipeline transformer.

pipelines = {}

# An important limitation is that:
# n_components x n_times = 2 ** (num_latent + num_trash)
n_components, n_times = 8, 64

pipelines["QNN+LDA"] = make_pipeline(
EpochChannelSelection(n_chan=n_components),
Vectorizer(),
# Use COBYLA with only 1 iteration (this is for runnin in Ci/Cd)
BasicQnnAutoencoder(
num_latent=n_components,
num_trash=1,
opt=COBYLA(maxiter=10),
callback=fn_callback,
),
Devectorizer(n_components, n_times),
Covariances(),
TangentSpace(),
LDA(),
)

pipelines["LDA"] = make_pipeline(
EpochChannelSelection(n_chan=n_components),
Vectorizer(),
Devectorizer(n_components, n_times),
Covariances(),
TangentSpace(),
LDA(),
)

##############################################################################
# Run evaluation
# ----------------
#
# Compare the pipeline using a cross-sessions evaluation.

evaluation = CrossSessionEvaluation(
paradigm=paradigm, datasets=datasets, overwrite=True, n_jobs=-1
)

results = evaluation.process(pipelines)

print("Averaging the session performance:")
print(results.groupby("pipeline").mean("score")[["score", "time"]])

# ##############################################################################
# # Plot Results
# # ----------------
# #
# # Here we plot the results to compare two pipelines

fig, ax = plt.subplots(facecolor="white", figsize=[8, 4])

sns.stripplot(
data=results,
y="score",
x="pipeline",
ax=ax,
jitter=True,
alpha=0.5,
zorder=1,
palette="Set1",
)
sns.pointplot(data=results, y="score", x="pipeline", ax=ax, palette="Set1").set(
title=title
)

ax.set_ylabel("ROC AUC")
ax.set_ylim(0.3, 1)

plt.show()

##############################################################################
# Plot the mean cost function

x = []
y = []
for iter in costs.keys():
x.append(iter)
c = costs[iter]
y.append(sum(c) / len(c))

plt.plot(x, y)
plt.xlabel("N of cost evaluation")
plt.ylabel("Cost")
plt.title("Autoencoder Cost")
plt.tight_layout()
plt.show()

###############################################################################
# References
# ----------
# .. [1] \
# https://qiskit-community.github.io/qiskit-machine-learning/tutorials/12_quantum_autoencoder.html
# .. [2] A. Mostafa et al., 2024
# ‘Quantum Denoising in the Realm of Brain-Computer Interfaces: A Preliminary Study’,
# https://hal.science/hal-04501908
4 changes: 2 additions & 2 deletions pyriemann_qiskit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from ._version import __version__
from . import classification, pipelines, ensemble
from . import classification, pipelines, ensemble, autoencoders

__all__ = ["__version__", "classification", "pipelines", "ensemble"]
__all__ = ["__version__", "classification", "pipelines", "ensemble", "autoencoders"]
Loading
Loading