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

Proposal : Quantum Autoencoder #280

Merged
merged 30 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5f4d629
Feat/qae (#36)
gcattan May 17, 2024
04ebbe8
Update examples/ERP/autoencoders_example.py
gcattan May 23, 2024
38aacef
Update examples/ERP/autoencoders_example.py
gcattan May 23, 2024
5043bc2
Update examples/ERP/autoencoders_example.py
gcattan May 23, 2024
69ce45b
Update pyriemann_qiskit/autoencoders.py
gcattan May 23, 2024
17a7bd0
Update pyriemann_qiskit/utils/preprocessing.py
gcattan May 23, 2024
e7846bb
Update pyriemann_qiskit/utils/filtering.py
gcattan May 23, 2024
260db44
Update pyriemann_qiskit/autoencoders.py
gcattan May 23, 2024
4b2be92
Update pyriemann_qiskit/autoencoders.py
gcattan May 23, 2024
4c5f435
Update pyriemann_qiskit/autoencoders.py
gcattan May 23, 2024
87f15b3
Update pyriemann_qiskit/autoencoders.py
gcattan May 23, 2024
c0c6bf2
Update pyriemann_qiskit/autoencoders.py
gcattan May 23, 2024
4d706bb
Update pyriemann_qiskit/autoencoders.py
gcattan May 23, 2024
03a60ee
Update pyriemann_qiskit/utils/filtering.py
gcattan May 23, 2024
7c633c3
Update pyriemann_qiskit/utils/filtering.py
gcattan May 23, 2024
28d2319
Rename to ChannelSelection
gcattan May 23, 2024
5f6703d
Update pyriemann_qiskit/utils/filtering.py
gcattan May 23, 2024
5011d9d
Update pyriemann_qiskit/utils/filtering.py
gcattan May 23, 2024
96f1b53
Update pyriemann_qiskit/utils/filtering.py
gcattan May 23, 2024
5b1641b
Update pyriemann_qiskit/utils/preprocessing.py
gcattan May 23, 2024
f34829e
replace n_times -> n_samples
gcattan May 23, 2024
afca272
replace n_trials by n_matrices
gcattan May 23, 2024
beb424c
apply review comment marked as outdated by GH
gcattan May 23, 2024
58c675c
fix example
gcattan May 23, 2024
ae96b1e
don't plot example as Hinss2021 is still on MOABB dev
gcattan May 23, 2024
1462160
remove unused alias for identitiy gate
gcattan May 24, 2024
daf9975
Update pyriemann_qiskit/utils/filtering.py
gcattan May 24, 2024
fd69c38
Update pyriemann_qiskit/autoencoders.py
gcattan May 24, 2024
0de3531
Update pyriemann_qiskit/autoencoders.py
gcattan May 24, 2024
529196e
Update pyriemann_qiskit/utils/filtering.py
gcattan May 24, 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
ChannelSelection

Mean
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
195 changes: 195 additions & 0 deletions examples/ERP/noplot_autoencoders_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
"""
===============================================================================
Quantum autoencoder for signal denoising
===============================================================================
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)

import logging
import warnings

from matplotlib import pyplot as plt
from moabb import set_log_level
from moabb.datasets import Hinss2021
from moabb.evaluations import CrossSessionEvaluation
from moabb.paradigms import RestingStateToP300Adapter
from pyriemann.estimation import Covariances
from pyriemann.tangentspace import TangentSpace
from qiskit_algorithms.optimizers import COBYLA
import seaborn as sns
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.pipeline import make_pipeline

from pyriemann_qiskit.autoencoders import BasicQnnAutoencoder
from pyriemann_qiskit.utils.filtering import ChannelSelection
from pyriemann_qiskit.utils.preprocessing import Vectorizer, Devectorizer

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(
ChannelSelection(n_channels=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(
ChannelSelection(n_channels=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