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

Classifiers #447

Merged
merged 34 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
152559e
port classifiers
Edoardo-Pedicillo Jul 18, 2023
4209b80
fix fit and plot functions
Edoardo-Pedicillo Jul 18, 2023
c85c36e
update runcard with hpars
Edoardo-Pedicillo Jul 19, 2023
d3e66b7
clean code
Edoardo-Pedicillo Jul 19, 2023
288f5a5
use scikit neural network
Edoardo-Pedicillo Jul 19, 2023
8666cc4
fix dumping models
Edoardo-Pedicillo Jul 20, 2023
4e8ccf4
fix contour plot colors
Edoardo-Pedicillo Jul 20, 2023
c8215b0
fix test
Edoardo-Pedicillo Jul 20, 2023
47e7ded
use cumulative
Edoardo-Pedicillo Jul 24, 2023
aa9b0c1
fix resonator_frequency
Edoardo-Pedicillo Jul 24, 2023
cb2e11d
clean code
Edoardo-Pedicillo Jul 24, 2023
00713f4
fix tests
Edoardo-Pedicillo Jul 24, 2023
a805892
remove plot functions
Edoardo-Pedicillo Jul 24, 2023
4cf4beb
remove load_qubit
Edoardo-Pedicillo Jul 24, 2023
12072bf
fix tests
Edoardo-Pedicillo Jul 24, 2023
8d5d5bd
add classifiers test
Edoardo-Pedicillo Jul 24, 2023
a83455b
delete unused dumping functions
Edoardo-Pedicillo Jul 24, 2023
67b4de9
Merge branch 'classifiers' of github.com:qiboteam/qibocal into classi…
Edoardo-Pedicillo Jul 24, 2023
926157d
remove comment
Edoardo-Pedicillo Jul 25, 2023
c3dd684
benchmark plots optional
Edoardo-Pedicillo Jul 26, 2023
99a865c
avoid plotting benchmarks if one model is trained
Edoardo-Pedicillo Jul 26, 2023
ad75927
add more tests
Edoardo-Pedicillo Jul 26, 2023
3afc3da
Update src/qibocal/protocols/characterization/classification.py
Edoardo-Pedicillo Aug 16, 2023
774fd43
Merge branch 'main' into classifiers
Edoardo-Pedicillo Aug 16, 2023
1b0ed76
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 16, 2023
8c904bd
remove qubit
Edoardo-Pedicillo Aug 16, 2023
f95f61b
lower opacity
Edoardo-Pedicillo Aug 16, 2023
1aabfc9
use pretty names
Edoardo-Pedicillo Aug 16, 2023
ca23b80
fix pretty_names
Edoardo-Pedicillo Aug 16, 2023
cdba268
not printing table
Edoardo-Pedicillo Aug 16, 2023
ffd3853
update actions_qq.yml
Edoardo-Pedicillo Aug 16, 2023
b3bef4d
fix table
Edoardo-Pedicillo Aug 16, 2023
a253082
add show_contour param
Edoardo-Pedicillo Aug 17, 2023
93f721c
delete show_conour and use pretty names in the subplots' titles
Edoardo-Pedicillo Aug 21, 2023
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 runcards/actions_qq.yml
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,9 @@ actions:
# priority: 0
# operation: single_shot_classification
# parameters:
# nshots: 10
# nshots: 2000
# classifiers_list: ["qubit_fit", "naive_bayes", "qblox_fit"]
# savedir: results


# - id: allXY
Expand Down
Empty file.
42 changes: 42 additions & 0 deletions src/qibocal/fitting/classifier/ada_boost.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import numpy as np
from sklearn.ensemble import AdaBoostClassifier
from sklearn.model_selection import GridSearchCV, RepeatedStratifiedKFold

from . import scikit_utils


def constructor(hyperpars):
r"""Return the model class.

Args:
hyperparams: Model hyperparameters.
"""
return AdaBoostClassifier().set_params(**hyperpars)


def hyperopt(x_train, y_train, _path):
r"""Perform an hyperparameter optimization and return the hyperparameters.

Args:
x_train: Training inputs.
y_train: Training outputs.
_path (path): Model save path.

Returns:
Dictionary with model's hyperparameters.
"""
clf = AdaBoostClassifier()
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
space = {}
space["n_estimators"] = np.linspace(10, 200, num=20).astype("int")
space["learning_rate"] = np.linspace(0.1, 1, num=10)
space["algorithm"] = ["SAMME", "SAMME.R"]
search = GridSearchCV(clf, space, scoring="accuracy", n_jobs=-1, cv=cv)
_ = search.fit(x_train, y_train)

return search.best_params_


normalize = scikit_utils.scikit_normalize
dump = scikit_utils.scikit_dump
predict_from_file = scikit_utils.scikit_predict
27 changes: 27 additions & 0 deletions src/qibocal/fitting/classifier/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import numpy as np
from sklearn.model_selection import train_test_split


def generate_models(data, qubit, test_size=0.25):
r"""Extract from data the values stored
in the keys `i` and `q` and split them in training and test sets.

Args:
data (DataFrame): Qubit's info.
test_size (float | Optional): The proportion of the dataset to include in the train split.

Returns:

- x_train: Training inputs.
- y_train: Training outputs.
- x_test: Test inputs.
- y_test: Test outputs.
"""
qubit_data = data.data[qubit]
return train_test_split(
np.array(qubit_data[["i", "q"]].tolist())[:, :],
np.array(qubit_data[["state"]].tolist())[:, 0],
test_size=test_size,
random_state=0,
shuffle=True,
)
34 changes: 34 additions & 0 deletions src/qibocal/fitting/classifier/gaussian_process.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from sklearn.gaussian_process import GaussianProcessClassifier
from sklearn.gaussian_process.kernels import RBF

from . import scikit_utils


def constructor(hyperparams):
r"""Return the model class.

Args:
hyperparams: Model hyperparameters.
"""
return GaussianProcessClassifier(1.0 * RBF(1.0)).set_params(**hyperparams)


def hyperopt(_x_train, _y_train, _path):
r"""Perform an hyperparameter optimization and return the hyperparameters.

Args:
_x_train: Training inputs.
_y_train: Training outputs.
_path (path): Model save path.

Returns:
Dictionary with model's hyperparameters.
"""
# Build the best model
model = GaussianProcessClassifier(1.0 * RBF(1.0))
return model.get_params()


normalize = scikit_utils.scikit_normalize
dump = scikit_utils.scikit_dump
predict_from_file = scikit_utils.scikit_predict
34 changes: 34 additions & 0 deletions src/qibocal/fitting/classifier/linear_svm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from sklearn.svm import SVC

from . import scikit_utils

REG_PARAM = 0.025


def constructor(hyperpars):
r"""Return the model class.

Args:
hyperparams: Model hyperparameters.
"""
return SVC(kernel="linear", C=REG_PARAM).set_params(**hyperpars)


def hyperopt(_x_train, _y_train, _path):
r"""Perform an hyperparameter optimization and return the hyperparameters.

Args:
_x_train: Training inputs.
_y_train: Training outputs.
_path (path): Model save path.

Returns:
Dictionary with model's hyperparameters.
"""
model = SVC(kernel="linear", probability=True, C=REG_PARAM)
return model.get_params()


normalize = scikit_utils.scikit_normalize
dump = scikit_utils.scikit_dump
predict_from_file = scikit_utils.scikit_predict
32 changes: 32 additions & 0 deletions src/qibocal/fitting/classifier/naive_bayes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from sklearn.naive_bayes import GaussianNB

from . import scikit_utils


def constructor(hyperpars):
r"""Return the model class.

Args:
hyperparams: Model hyperparameters.
"""
return GaussianNB().set_params(**hyperpars)


def hyperopt(_x_train, _y_train, _path):
r"""Perform an hyperparameter optimization and return the hyperparameters.

Args:
_x_train: Training inputs.
_y_train: Training outputs.
_path (path): Model save path.

Returns:
Dictionary with model's hyperparameters.
"""
model = GaussianNB()
return model.get_params()


normalize = scikit_utils.scikit_normalize
dump = scikit_utils.scikit_dump
predict_from_file = scikit_utils.scikit_predict
43 changes: 43 additions & 0 deletions src/qibocal/fitting/classifier/nn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import numpy as np
from sklearn.model_selection import GridSearchCV, RepeatedStratifiedKFold
from sklearn.neural_network import MLPClassifier

from . import scikit_utils


def constructor(hyperpars):
r"""Return the model class.

Args:
hyperparams: Model hyperparameters.
"""
return MLPClassifier().set_params(**hyperpars)


def hyperopt(x_train, y_train, _path):
r"""Perform an hyperparameter optimization and return the hyperparameters.

Args:
x_train: Training inputs.
y_train: Training outputs.
_path (path): Model save path.

Returns:
Dictionary with model's hyperparameters.
"""
clf = MLPClassifier()
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
space = {}
space["hidden_layer_sizes"] = [(16, 16), (16, 32), (16, 64)]
space["learning_rate_init"] = np.linspace(1e-4, 1e-2, num=3)
space["activation"] = ["logistic", "tanh", "relu"]
space["solver"] = ["lbfgs", "sgd", "adam"]
search = GridSearchCV(clf, space, scoring="accuracy", n_jobs=-1, cv=cv)
_ = search.fit(x_train, y_train)

return search.best_params_


normalize = lambda x: x
dump = scikit_utils.scikit_dump
predict_from_file = scikit_utils.scikit_predict
61 changes: 61 additions & 0 deletions src/qibocal/fitting/classifier/qblox_fit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from dataclasses import dataclass

import numpy as np
import numpy.typing as npt

from . import qubit_fit as qfit


def constructor(_hyperparams):
r"""Return the model class.

Args:
_hyperparams: Model hyperparameters.
"""
return QbloxFit()


def hyperopt(_x_train, _y_train, _path):
r"""Perform an hyperparameter optimization and return the hyperparameters.

Args:
x_train: Training inputs.
y_train: Training outputs.
path (path): Model save path.

Returns:
Dictionary with model's hyperparameters.
"""
return {}


normalize = lambda x: x
dump = qfit.dump
predict_from_file = qfit.predict_from_file


@dataclass
class QbloxFit:
r"""This class deploys the Qblox qubit state classifier described
in the [documentation](https://qblox-qblox-instruments.readthedocs-hosted.com/en/master/tutorials/conditional_playback.html#Measure-qubit-histogram).

Args:
threshold (float): Classifier's threshold.
angle (float): Rotational angle.

"""

threshold: float = 0.0
angle: float = 0.0

def fit(self, iq_coordinates, states: list):
state1 = [complex(*i) for i in iq_coordinates[(states == 1)]]
state0 = [complex(*i) for i in iq_coordinates[(states == 0)]]
self.angle = np.mod(-np.angle(np.mean(state1) - np.mean(state0)), 2 * np.pi)
self.threshold = (
np.exp(1j * self.angle) * (np.mean(state1) + np.mean(state0))
).real / 2

def predict(self, inputs: npt.NDArray):
inputs = np.array([complex(*i) for i in inputs])
return ((np.exp(1j * self.angle) * inputs).real > self.threshold).astype(int)
Loading