Estimators
eigenkit includes quantum estimators that are compatible with sklearn and built on
PyTorch. They are hybrid classifiers and regressors, their recurrent versions,
wrappers around your own networks, and adapters for time series. Every estimator
follows the standard sklearn interface, fit(X, y), predict(X) and score(X, y),
and works with GridSearchCV, Pipeline, clone and the rest of sklearn. Import
them from the top level: from eigenkit import HQNC.
Install: these estimators need the torch extra
(pip install eigenkit[torch]). They run on the built-in NumPy simulator. Another
backend needs its own extra, for example eigenkit[pennylane] for
provider="pennylane".
You can save a fitted model to a .eigenkit bundle, which is a zip file, and
load it again with save() and load(), or with load_model(). See
Model persistence for the format of the bundle, the
supported classes, and how the benchmark uses save_dir.
How to get the trained network: model_
fit() trains a deep copy of the network, so it never changes the module that
you gave to the estimator. After training, the object that you passed to
GenericClassifier(model=...) therefore still has its initial weights, whatever
the network did. This comes from the copy, and says nothing about the model.
model_ returns the network that was actually trained. It exists on every
estimator that trains a PyTorch network (all the estimators of this page except
the time-series wrappers), and it raises NotFittedError before fit().
from torch import nn
from eigenkit import Basic, GenericClassifier
from eigenkit.datasets import load_dataset
data = load_dataset("iris")
X_train, y_train = data["X_train"], data["y_train"]
layer = Basic(n_qubits=4, depth=2)
clf = GenericClassifier(model=nn.Sequential(layer, nn.Linear(4, 3)), in_features=4)
clf.fit(X_train, y_train)
layer.state_dict() # unchanged, this object never trained
clf.model_[0].state_dict() # the trained weights
Classifiers
HQNC uses the PyTorch loss CrossEntropyLoss, and train_losses_ stores the
cross-entropy of each epoch. When you pass validation data with
fit(..., X_val=..., y_val=...), validation_losses_ stores the matching
validation curve. n_classes is optional on every classifier of this section. If
you leave it out, the set of labels is inferred from y when you call fit().
The examples of this section use the built-in iris dataset. It has 4 features
and 3 classes, which is what the constructors below are sized for:
from eigenkit.datasets import load_dataset
data = load_dataset("iris")
X_train, y_train = data["X_train"], data["y_train"]
X_test, y_test = data["X_test"], data["y_test"]
HQNC
HQNC is the hybrid quantum neural network classifier. It places a quantum layer
in a small nn.Sequential pipeline, and trains the whole pipeline together with
the cross-entropy loss.
from eigenkit import HQNC
model = HQNC(
in_features=4,
depth=2,
n_classes=3,
epochs=30,
)
model.fit(X_train, y_train)
predictions = model.predict(X_test)
print(model.score(X_test, y_test)) # accuracy
print(model.train_losses_) # per-epoch loss
You choose the quantum layer with layer_type:
layer_type |
Quantum layer | Notes |
|---|---|---|
"Basic" (default) |
One encoding block and one variational block. | It needs n_qubits == in_quantum. |
"Reupload" |
Standard data reuploading. | It needs n_qubits == in_quantum. |
"Ensemble" |
N independent circuits. |
It needs n_qubits to divide in_quantum. |
Note: if n_qubits and in_quantum differ for Basic or Reupload, a linear
adapter Linear(in_features, n_qubits) is added in front automatically, and a
UserWarning is raised.
enc_rotation, var_rotation, variational_type and basis are passed to that
layer unchanged. Their default is None, which means "the value that the layer you
named uses". So the architecture that an estimator builds is the one that the
layer page describes, and if you build it yourself from that page, you
get the same model. Pass any of these four arguments to replace the default of the
layer.
# Ensemble of 4-qubit circuits over 16 features.
model = HQNC(in_features=16, n_qubits=4, layer_type="Ensemble", depth=2)
RecurrentHQNC
RecurrentHQNC is a hybrid classifier for sequences. An encoder that is a
recurrent neural network (RNN), of type "rnn", "gru" or "lstm", reads the
sequence and passes the encoded vector to a quantum layer like the one of HQNC.
The whole model is trained together, with one optimiser and one loss, so the RNN
and the quantum block are updated at the same time.
X must be 3-D, with shape (n_samples, seq_len, seq_feature_dim). By default,
only the last time step of the RNN goes to the quantum block. To flatten the whole
sequence instead, set rnn_return_last_timestep=False and also give
sequence_length.
import numpy as np
from eigenkit import RecurrentHQNC
X = np.random.randn(32, 10, 4).astype(np.float32)
y = np.where(X[:, -1, 0] > 0, "up", "down")
model = RecurrentHQNC(
seq_feature_dim=4,
rnn_type="gru",
rnn_hidden_dim=16,
depth=2,
epochs=30,
)
model.fit(X, y)
predictions = model.predict(X)
probabilities = model.predict_proba(X)
The quantum layer takes the same arguments as in HQNC: layer_type,
n_qubits, enc_rotation, var_rotation, variational_type and basis. See the table of layer_type values of HQNC above. The
other options of the RNN are rnn_num_layers, rnn_dropout and
rnn_bidirectional.
CustomQuantumClassifier
CustomQuantumClassifier builds its architecture from any list of blocks. Use it
when none of the layer_type presets fits:
from eigenkit import (
Encoding,
Variational,
StrongVariational,
all_z,
)
from eigenkit import CustomQuantumClassifier
blocks = [
Encoding(in_features=4, rotation="RY"),
StrongVariational(depth=2),
Variational(depth=1, rotation="RX"),
]
model = CustomQuantumClassifier(
blocks=blocks,
observables=all_z(4),
n_classes=2,
epochs=30,
)
# This estimator is configured for two classes, so keep iris labels 0 and 1.
binary = y_train < 2
model.fit(X_train[binary], y_train[binary])
predictions = model.predict(X_test)
observables= accepts the same forms as Circuit(observables=...) (see
Observables). When the number of features of the data differs
from the input size of the circuit, an nn.Linear adapter is added in front
automatically. The input size of the circuit is inferred from the first Encoding
or Reuploading block.
Regressors
The examples of this section use the built-in concrete dataset. It has 8
features and a continuous target. The examples use only part of the data, so that
they run quickly:
from eigenkit.datasets import load_dataset
data = load_dataset("concrete")
X_train, y_train = data["X_train"][:200], data["y_train"][:200]
X_test, y_test = data["X_test"][:50], data["y_test"][:50]
HQNR
HQNR is the regression version of HQNC. Its output is a single neuron, trained
with the regression loss that you choose.
from eigenkit import HQNR
model = HQNR(in_features=8, depth=2, epochs=50)
model.fit(X_train, y_train)
predictions = model.predict(X_test)
print(model.score(X_test, y_test)) # R^2
It takes the same layer_type and n_qubits arguments as HQNC.
You choose the loss with loss_func: "mse", "mae" or "huber".
RecurrentHQNR
RecurrentHQNR is a hybrid regressor for sequences. An RNN encoder, of type
"rnn", "gru" or "lstm", reads the sequence and passes the encoded vector to a
quantum layer like the one of HQNR. The whole model is trained together, with one
optimiser and one loss, so the RNN and the quantum block are updated at the same
time.
X must be 3-D, with shape (n_samples, seq_len, seq_feature_dim). By default,
only the last time step of the RNN goes to the quantum block. To flatten the whole
sequence instead, set rnn_return_last_timestep=False and also give
sequence_length.
import numpy as np
from eigenkit import RecurrentHQNR
X = np.random.randn(32, 10, 4).astype(np.float32)
last = X[:, -1, :]
y = (
0.5 * last[:, 0]
+ 0.3 * np.sin(last[:, 1])
+ 0.2 * np.cos(2 * np.pi * last[:, 2])
+ 0.1 * last[:, 3] * last[:, 0]
).astype(np.float32)
model = RecurrentHQNR(
seq_feature_dim=4,
rnn_type="gru",
rnn_hidden_dim=16,
depth=2,
epochs=30,
)
model.fit(X, y)
predictions = model.predict(X)
CustomQuantumRegressor
CustomQuantumRegressor is the regression version of CustomQuantumClassifier. It
builds the circuit from a list of blocks, and adds a Linear head with a single
neuron, trained with the regression loss that you choose.
Generic estimators
GenericClassifier and GenericRegressor are wrappers, compatible with sklearn, that train any torch.nn.Module through the standard fit and predict interface. HQNC and HQNR build the architecture of the model for you. The generic estimators instead expect a complete network, output head included, so you have full control over the architecture.
Pre-trained weights and the behaviour of fit()
fit() does not start from pre-trained weights. It copies the nn.Module, and then calls reset_parameters() on every submodule that has this method (such as nn.Linear and the quantum layers of eigenkit), seeded with random_state. So the weights of these layers are drawn again before training, even if the module that you pass already holds trained weights. Each later call to fit() (for example inside cross-validation, or after clone()) also starts again from new weights, not from the weights of the previous fit(). To keep the trained weights, use the fitted estimator, or save it with save() and load it again with load(), and do not call fit() on it again.
random_state does not reseed your process
Every estimator applies random_state inside fit() and load() on a private
copy of the state of the PyTorch random number generators, that is the generator
of the central processing unit (CPU) and the generator of every CUDA device. Two
runs with the same random_state give the same model, on the CPU and on the
graphics processing unit (GPU), and neither run changes a seed that you set
yourself.
Only model is required. If you leave out in_features (default None), the
number of features is taken from the data. sequence_input (default False) tells
the estimator that X has shape (batch, timesteps, features) instead of
(batch, features). The training arguments are lr (0.01), optimizer
("adam"), optimizer_kwargs (None), epochs (50), batch_size (32),
show_progress (True) and random_state (42). GenericClassifier adds
n_classes, and GenericRegressor adds loss_func, huber_delta and
huber_reduction. None of these arguments is about the circuit, because the network
is yours.
The examples below use moons for the classifier and diabetes for the regressor,
which match the input sizes of their networks:
from eigenkit.datasets import load_dataset
moons = load_dataset("moons")
X_train, y_train = moons["X_train"], moons["y_train"]
X_test, y_test = moons["X_test"], moons["y_test"]
diabetes = load_dataset("diabetes")
X_reg, y_reg = diabetes["X_train"][:200], diabetes["y_train"][:200]
X_reg_test, y_reg_test = diabetes["X_test"][:50], diabetes["y_test"][:50]
GenericClassifier
from torch import nn
from eigenkit import GenericClassifier
from eigenkit import Basic
N_QUBITS, N_CLASSES = 4, 2
clf_net = nn.Sequential(
nn.Linear(2, N_QUBITS),
nn.Tanh(),
Basic(n_qubits=N_QUBITS, depth=2),
nn.Linear(N_QUBITS, N_CLASSES),
)
clf = GenericClassifier(
model=clf_net,
in_features=2,
epochs=30,
lr=0.01,
batch_size=16,
random_state=42,
)
clf.fit(X_train, y_train)
print(clf.score(X_test, y_test)) # accuracy
labels = clf.predict(X_test)
probs = clf.predict_proba(X_test) # shape (n_samples, n_classes)
The forward() method of the network must return logits of shape (batch, n_classes). The wrapper encodes the labels automatically, so y can hold integers, strings or any other hashable labels.
in_features is optional but recommended. When it is set, fit raises an error at once if the shape of the data does not match.
GenericRegressor
from torch import nn
from eigenkit import GenericRegressor
from eigenkit import Basic
N_QUBITS_REG, IN_FEATURES = 6, 10
reg_net = nn.Sequential(
nn.Linear(IN_FEATURES, N_QUBITS_REG),
nn.Tanh(),
Basic(n_qubits=N_QUBITS_REG, depth=2),
nn.Linear(N_QUBITS_REG, 1),
)
reg = GenericRegressor(
model=reg_net,
in_features=IN_FEATURES,
loss_func="mse",
epochs=50,
lr=0.01,
batch_size=32,
random_state=42,
)
reg.fit(X_reg, y_reg)
print(reg.score(X_reg_test, y_reg_test)) # R²
preds = reg.predict(X_reg_test) # float32 array, shape (n_samples,)
The forward() method of the network must return shape (batch,) or (batch, 1). The losses available by name are "mse", "mae" and "huber". Any callable (output, target) -> scalar_tensor is also accepted, but a model trained with a callable loss cannot be saved.
Save and load
Generic estimators use the same .eigenkit bundle format as the other estimators, with one difference: the bundle does not store the architecture. You must pass a module with the same nn.Module structure to .load():
clf.save("clf_hybrid.eigenkit")
clf_net_fresh = nn.Sequential(
nn.Linear(2, N_QUBITS),
nn.Tanh(),
Basic(n_qubits=N_QUBITS, depth=2),
nn.Linear(N_QUBITS, N_CLASSES),
)
clf_loaded = GenericClassifier.load("clf_hybrid.eigenkit", model=clf_net_fresh)
load_model() also works for generic estimators, but the model= argument is required, because the bundle does not store the architecture and it cannot be inferred. If you call either method without model=, it raises SerializationError.
sklearn compatibility
GenericClassifier inherits from ClassifierMixin and GenericRegressor from RegressorMixin, so both work with Pipeline, cross_val_score, GridSearchCV and clone:
from sklearn.base import clone
from sklearn.model_selection import cross_val_score
scores = cross_val_score(clf, X_train, y_train, cv=3, scoring="accuracy")
cloned = clone(clf) # unfitted copy with the same hyperparameters
See the Generic Estimators example for a complete example.
Time series
QuantumTimeSeriesRegressor and QuantumTimeSeriesClassifier wrap an inner
estimator and apply a sliding window to data in time order. Each row of X is one
time step. With a window of length in_size, the inner model receives a 3-D batch
of shape (n_windows, in_size, n_features), and the window that starts at row i
predicts y[i + in_size - 1 + shift]. With autoregressive=True, an extra channel
is added to each time step, and it holds the target value at that step.
For tabular estimators (HQNR, CustomQuantumRegressor, and so on), the wrapper
flattens each window before it calls fit or predict. For RecurrentHQNR and
RecurrentHQNC, and for the generic estimators with sequence_input=True, the
windows stay 3-D, so that the RNN sees the time axis.
import numpy as np
from eigenkit import (
QuantumTimeSeriesRegressor,
RecurrentHQNR,
)
n_feat = 5
window = 10
X = np.random.randn(200, n_feat).astype(np.float32)
y = X[:, 0] + 0.1 * np.random.randn(200).astype(np.float32)
inner = RecurrentHQNR(
seq_feature_dim=n_feat,
rnn_type="gru",
rnn_hidden_dim=16,
depth=2,
)
model = QuantumTimeSeriesRegressor(estimator=inner, in_size=window, shift=1)
model.fit(X, y)
predictions = model.predict(X) # length n_timesteps - in_size - shift + 1
Classification uses the same alignment of the windows:
import numpy as np
from eigenkit import (
QuantumTimeSeriesClassifier,
RecurrentHQNC,
)
n_feat = 5
window = 10
X = np.random.randn(200, n_feat).astype(np.float32)
y = np.where(X[:, 0] > 0, "up", "down")
inner = RecurrentHQNC(
seq_feature_dim=n_feat,
rnn_type="gru",
rnn_hidden_dim=16,
depth=2,
)
model = QuantumTimeSeriesClassifier(estimator=inner, in_size=window, shift=1)
model.fit(X, y)
predictions = model.predict(X) # length n_timesteps - in_size - shift + 1
probabilities = model.predict_proba(X)
Autoregressive mode. Set autoregressive=True to add the past values of the
target to each window, as an extra channel of features. This extra channel counts
as a feature: the inner estimator must be built with
seq_feature_dim = n_feat + 1, and if you reuse the one above, you get
ValueError: Last dimension of X must equal seq_feature_dim=5, got 6. When you
predict, you must pass the known history as y_history:
# The appended target channel makes it n_feat + 1 inputs, so this needs its
# own inner estimator.
inner_ar = RecurrentHQNC(
seq_feature_dim=n_feat + 1,
rnn_type="gru",
rnn_hidden_dim=16,
depth=2,
)
# Fit on the head of the series, predict on the tail.
X_hist, y_hist = X[:150], y[:150]
X_future, y_future = X[150:], y[150:]
model_ar = QuantumTimeSeriesClassifier(
estimator=inner_ar,
in_size=window,
shift=1,
autoregressive=True,
)
model_ar.fit(X_hist, y_hist)
predictions = model_ar.predict(X_future, y_history=y_future)
probabilities = model_ar.predict_proba(X_future, y_history=y_future)
sklearn compatibility
Every algorithm class is a subclass of sklearn.base.BaseEstimator, and stores
each argument of its constructor as an attribute of the same name on self, as
sklearn expects. This is what makes clone, Pipeline, cross_val_score and
GridSearchCV work without extra code.
from sklearn.base import clone
from sklearn.model_selection import cross_val_score
cloned = clone(model)
scores = cross_val_score(model, X, y, cv=5)
from sklearn.model_selection import GridSearchCV
from eigenkit import HQNC
from eigenkit.datasets import load_dataset
iris = load_dataset("iris")
binary = iris["y_train"] < 2 # the estimator below declares two classes
X_iris, y_iris = iris["X_train"][binary], iris["y_train"][binary]
grid = GridSearchCV(
HQNC(in_features=4, n_classes=2),
param_grid={"depth": [1, 2], "epochs": [20, 40]},
cv=3,
)
grid.fit(X_iris, y_iris)
best = grid.best_estimator_
BaseQuantumClassifier inherits from ClassifierMixin, so its score() returns
the accuracy. BaseQuantumRegressor inherits from RegressorMixin, so its
score() returns R².
Import the base classes when you build your own estimators:
Choosing a backend
Every estimator accepts the same provider= argument as Circuit: the name of a
registered backend as a string, a configuration dataclass, or a Backend instance.
from eigenkit import PennyLaneConfig
# String. Requires the matching extra, here `qiskit`.
HQNC(in_features=4, depth=2, provider="qiskit")
# Config: forwards device-level options. Requires the `pennylane` extra.
HQNC(
in_features=4,
depth=2,
provider=PennyLaneConfig(device_name="lightning.qubit", shots=None),
)
API reference
eigenkit.qml.BaseQuantumEstimator
Bases: BaseEstimator, ABC
Base class, compatible with scikit-learn, for all quantum algorithms.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
provider
|
ProviderSpec
|
The backend. It can be a registered name ( |
'numpy'
|
random_state
|
int | None
|
The seed for reproducibility, applied inside |
42
|
fit(X, y)
abstractmethod
Fit the estimator on X and y.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
y
|
ndarray
|
One target for each sample, of shape |
required |
Returns:
| Type | Description |
|---|---|
'BaseQuantumEstimator'
|
This estimator, so that calls can be chained. |
load(path, *, provider=None)
classmethod
Load a fitted model from a .eigenkit bundle.
Load only bundles that you trust. A bundle can contain joblib pickles, and
unpickling runs code, as with torch.load or joblib.load.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
The path of the bundle. |
required |
provider
|
ProviderSpec | None
|
A provider that replaces the saved one. |
None
|
Returns:
| Type | Description |
|---|---|
'BaseQuantumEstimator'
|
The loaded estimator. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the method is called on a subclass and the bundle holds
a different class. |
predict(X)
abstractmethod
Predict a value for every sample in X.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
One prediction for each sample. |
save(path)
Save a fitted model to a .eigenkit bundle.
The bundles of models that hold scikit-learn objects (QSVC, QSVR, the
reservoir estimators and the time-series estimators) contain joblib
pickles, so loading one can run code. Share them only with people who
trust you.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
The path of the bundle. The suffix |
required |
eigenkit.qml.BaseQuantumClassifier
Bases: ClassifierMixin, BaseQuantumEstimator
Base class for quantum classifiers. Its score() returns the accuracy.
predict_proba(X)
Predict the class probabilities.
Subclasses should return the probabilities in the order of classes_,
with shape (n_samples, n_classes). The default implementation raises a
NotImplementedError.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The probabilities, of shape |
eigenkit.qml.BaseQuantumRegressor
Bases: RegressorMixin, BaseQuantumEstimator
Base class for quantum regressors. Its score() returns R².
eigenkit.torch.estimators
The PyTorch estimators: differentiable hybrid quantum-classical models.
The estimator base classes compatible with scikit-learn, the quantum kernels, the
support vector machines and the saving and loading of models are in a separate
package, eigenkit.qml, which does not need PyTorch. The base classes and
load_model are also exported here for convenience, because the hybrid estimators
build on them.
BaseQuantumClassifier
Bases: ClassifierMixin, BaseQuantumEstimator
Base class for quantum classifiers. Its score() returns the accuracy.
predict_proba(X)
Predict the class probabilities.
Subclasses should return the probabilities in the order of classes_,
with shape (n_samples, n_classes). The default implementation raises a
NotImplementedError.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The probabilities, of shape |
BaseQuantumEstimator
Bases: BaseEstimator, ABC
Base class, compatible with scikit-learn, for all quantum algorithms.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
provider
|
ProviderSpec
|
The backend. It can be a registered name ( |
'numpy'
|
random_state
|
int | None
|
The seed for reproducibility, applied inside |
42
|
fit(X, y)
abstractmethod
Fit the estimator on X and y.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
y
|
ndarray
|
One target for each sample, of shape |
required |
Returns:
| Type | Description |
|---|---|
'BaseQuantumEstimator'
|
This estimator, so that calls can be chained. |
load(path, *, provider=None)
classmethod
Load a fitted model from a .eigenkit bundle.
Load only bundles that you trust. A bundle can contain joblib pickles, and
unpickling runs code, as with torch.load or joblib.load.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
The path of the bundle. |
required |
provider
|
ProviderSpec | None
|
A provider that replaces the saved one. |
None
|
Returns:
| Type | Description |
|---|---|
'BaseQuantumEstimator'
|
The loaded estimator. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the method is called on a subclass and the bundle holds
a different class. |
predict(X)
abstractmethod
Predict a value for every sample in X.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
One prediction for each sample. |
save(path)
Save a fitted model to a .eigenkit bundle.
The bundles of models that hold scikit-learn objects (QSVC, QSVR, the
reservoir estimators and the time-series estimators) contain joblib
pickles, so loading one can run code. Share them only with people who
trust you.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
The path of the bundle. The suffix |
required |
BaseQuantumRegressor
Bases: RegressorMixin, BaseQuantumEstimator
Base class for quantum regressors. Its score() returns R².
CustomQuantumClassifier
Bases: ModelAccessMixin, BaseQuantumClassifier
Classifier compatible with scikit-learn, built from your own list of blocks.
Give any sequence of blocks (Encoding, Variational, StrongVariational,
Reuploading, or a custom block from CircuitBuilder.to_block()) and an
observables specification, as for Circuit. The estimator connects them
into a quantum layer followed by a classical nn.Linear head, and trains the
whole model with the cross-entropy loss. When the number of features of the
data differs from the number of inputs that the circuit expects, an
nn.Linear adapter is added in front automatically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
blocks
|
list[Block]
|
The list of blocks, in order. |
required |
observables
|
ObservableLike
|
The observables. It takes the same options as
|
None
|
provider
|
ProviderSpec
|
The backend. Default: |
'numpy'
|
in_features
|
int | None
|
The number of features of the data. If None, it is inferred
from the first |
None
|
n_classes
|
int | None
|
The number of output classes. If None, it is inferred from the training labels. |
None
|
lr
|
float
|
The learning rate of the optimiser. |
0.01
|
optimizer
|
str
|
The name of the optimiser. The supported names are |
'adam'
|
optimizer_kwargs
|
dict | None
|
Extra keyword arguments passed to the optimiser. |
None
|
epochs
|
int
|
The number of training epochs. |
50
|
batch_size
|
int
|
The size of each mini-batch. |
32
|
show_progress
|
bool
|
If True, a tqdm progress bar is shown. |
True
|
random_state
|
int | None
|
The seed. |
42
|
Attributes:
| Name | Type | Description |
|---|---|---|
train_losses_ |
The cross-entropy loss of each epoch, set by |
|
validation_losses_ |
The validation cross-entropy loss of each epoch, set
by |
Example
import numpy as np
from eigenkit import (
CustomQuantumClassifier, Encoding, Variational, all_z,
)
rng = np.random.default_rng(0)
X_train, X_test = rng.uniform(0, np.pi, (20, 4)), rng.uniform(0, np.pi, (5, 4))
y_train = np.array([0, 1] * 10)
blocks = [
Encoding(in_features=4, rotation="RY"),
Variational(depth=2, rotation="RY"),
]
model = CustomQuantumClassifier(
blocks=blocks, observables=all_z(4), epochs=10,
)
model.fit(X_train, y_train)
predictions = model.predict(X_test)
fit(X, y, X_val=None, y_val=None)
Fit the classifier on training data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
y
|
ndarray
|
The class labels, of shape |
required |
X_val
|
ndarray | None
|
Optional validation samples, used to compute the validation loss of each epoch. |
None
|
y_val
|
ndarray | None
|
Optional validation labels, used to compute the validation loss of each epoch. |
None
|
Returns:
| Type | Description |
|---|---|
'CustomQuantumClassifier'
|
This estimator, so that calls can be chained. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
predict(X)
Predict the class labels of X.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
One prediction for each sample. |
predict_proba(X)
Predict the probability of each class, with a softmax over the logits.
It returns a float32 array of shape (n_samples, n_classes).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The probabilities, of shape |
CustomQuantumRegressor
Bases: ModelAccessMixin, BaseQuantumRegressor
Regressor compatible with scikit-learn, built from your own list of blocks.
It is the regression counterpart of
CustomQuantumClassifier.
It wraps your quantum Circuit with an nn.Linear head of one neuron, trained
with the chosen regression loss. An nn.Linear input adapter is added when the
number of features of the data differs from the number of inputs of the
circuit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
blocks
|
list[Block]
|
The list of blocks, in order. |
required |
observables
|
ObservableLike
|
The observables. It takes the same options as
|
None
|
provider
|
ProviderSpec
|
The backend. Default: |
'numpy'
|
in_features
|
int | None
|
The number of features of the data. If None, it is inferred
from the first |
None
|
lr
|
float
|
The learning rate of the optimiser. |
0.01
|
optimizer
|
str
|
The name of the optimiser: |
'adam'
|
optimizer_kwargs
|
dict | None
|
Extra keyword arguments passed to the optimiser. |
None
|
epochs
|
int
|
The number of training epochs. |
50
|
batch_size
|
int
|
The size of each mini-batch. |
32
|
loss_func
|
str
|
The regression loss: |
'mse'
|
huber_delta
|
float
|
The threshold of the Huber loss. |
1.0
|
huber_reduction
|
str
|
The reduction of the Huber loss: |
'mean'
|
show_progress
|
bool
|
If True, a tqdm progress bar is shown. |
True
|
random_state
|
int | None
|
The seed. |
42
|
Attributes:
| Name | Type | Description |
|---|---|---|
train_losses_ |
The training loss of each epoch, set by |
|
validation_losses_ |
The validation loss of each epoch, set by |
fit(X, y, X_val=None, y_val=None)
Fit the regressor on training data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
y
|
ndarray
|
The real-valued targets, of shape |
required |
X_val
|
ndarray | None
|
Optional validation samples, used to compute the validation loss of each epoch. |
None
|
y_val
|
ndarray | None
|
Optional validation targets, used to compute the validation loss of each epoch. |
None
|
Returns:
| Type | Description |
|---|---|
'CustomQuantumRegressor'
|
This estimator, so that calls can be chained. |
predict(X)
Predict the continuous targets of X. It returns a float32 array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
One prediction for each sample. |
GenericClassifier
Bases: ModelAccessMixin, BaseQuantumClassifier
Classifier compatible with scikit-learn that wraps any torch.nn.Module.
You supply a complete model whose forward(X) accepts a float32 tensor of
shape (batch, in_features) and returns logits of shape
(batch, n_classes). For sequence models (for example a long short-term
memory network), set sequence_input=True. The wrapper then passes a 3-D
tensor of shape (batch, seq_len, in_features) as it is, instead of
flattening it.
The wrapper trains with CrossEntropyLoss and encodes the labels
automatically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Module
|
Any |
required |
in_features
|
int | None
|
The expected number of features at each time step (the
last dimension of the input). When it is given, |
None
|
sequence_input
|
bool
|
If |
False
|
n_classes
|
int | None
|
The number of output classes. If |
None
|
lr
|
float
|
The learning rate of the optimiser. |
0.01
|
optimizer
|
str
|
The name of the optimiser: |
'adam'
|
optimizer_kwargs
|
dict | None
|
Extra keyword arguments passed to the constructor of the optimiser. |
None
|
epochs
|
int
|
The number of full passes over the training data. |
50
|
batch_size
|
int
|
The size of each mini-batch. |
32
|
show_progress
|
bool
|
If True, a tqdm progress bar is shown during training. |
True
|
random_state
|
int | None
|
The seed, applied before the first training step. |
42
|
Attributes:
| Name | Type | Description |
|---|---|---|
train_losses_ |
The average cross-entropy loss of each epoch, set by
|
|
validation_losses_ |
The validation cross-entropy loss of each epoch, set
by |
Example
import numpy as np
from torch import nn
from eigenkit.torch.estimators import GenericClassifier
from eigenkit.torch.layers import Basic
rng = np.random.default_rng(0)
X_train, X_test = rng.normal(size=(30, 4)), rng.normal(size=(5, 4))
y_train = np.arange(30) % 3
# A plain PyTorch network, with a head for 3 classes.
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 3))
clf = GenericClassifier(model=net, in_features=4, epochs=20)
clf.fit(X_train, y_train)
labels = clf.predict(X_test)
probs = clf.predict_proba(X_test)
# A quantum layer with a classification head.
q = Basic(n_qubits=4, depth=2)
hybrid = nn.Sequential(q, nn.Linear(4, 3))
clf2 = GenericClassifier(model=hybrid, in_features=4)
accepts_sequence_input
property
Whether the model expects a 3-D input (batch, seq_len, features).
fit(X, y, X_val=None, y_val=None)
Fit the model on training data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
y
|
ndarray
|
The class labels, of shape |
required |
X_val
|
ndarray | None
|
Optional validation samples, used to compute the validation loss of each epoch. |
None
|
y_val
|
ndarray | None
|
Optional validation labels, used to compute the validation loss of each epoch. |
None
|
Returns:
| Type | Description |
|---|---|
'GenericClassifier'
|
This estimator, so that calls can be chained. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
load(path, *, model=None, provider=None)
classmethod
Load a fitted GenericClassifier from a .eigenkit bundle.
The architecture of the model cannot be rebuilt automatically, so you must give it. The saved weights and the label encoder are restored automatically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
The path of the |
required |
model
|
Module | None
|
An |
None
|
provider
|
ProviderSpec | None
|
It is ignored. It is kept so that the signature matches the other estimators. |
None
|
Returns:
| Type | Description |
|---|---|
'GenericClassifier'
|
The loaded estimator. |
Raises:
| Type | Description |
|---|---|
SerializationError
|
If |
TypeError
|
If the bundle holds a different class. |
predict(X)
Predict the class labels of X.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
One prediction for each sample. |
predict_proba(X)
Predict the probability of each class, with a softmax over the logits.
It returns a float32 array of shape (n_samples, n_classes).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The probabilities, of shape |
GenericRegressor
Bases: ModelAccessMixin, BaseQuantumRegressor
Regressor compatible with scikit-learn that wraps any torch.nn.Module.
You supply a complete model whose forward(X) accepts a float32 tensor of
shape (batch, in_features) and returns a tensor of shape (batch, 1) or
(batch,). For sequence models (for example a long short-term memory
network), set sequence_input=True. The wrapper then passes a 3-D tensor of
shape (batch, seq_len, in_features) as it is, instead of flattening it.
The wrapper trains the model with the standard train_loop() of the library,
and returns the predictions as a float32 NumPy array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Module
|
Any |
required |
in_features
|
int | None
|
The expected number of features at each time step (the
last dimension of the input). When it is given, |
None
|
sequence_input
|
bool
|
If |
False
|
loss_func
|
str | Callable
|
The loss: |
'mse'
|
huber_delta
|
float
|
The threshold of the Huber loss. It is ignored for the other losses. |
1.0
|
huber_reduction
|
str
|
The reduction of the Huber loss: |
'mean'
|
lr
|
float
|
The learning rate of the optimiser. |
0.01
|
optimizer
|
str
|
The name of the optimiser: |
'adam'
|
optimizer_kwargs
|
dict | None
|
Extra keyword arguments passed to the constructor of the optimiser. |
None
|
epochs
|
int
|
The number of full passes over the training data. |
50
|
batch_size
|
int
|
The size of each mini-batch. |
32
|
show_progress
|
bool
|
If True, a tqdm progress bar is shown during training. |
True
|
random_state
|
int | None
|
The seed, applied before the first training step. |
42
|
Attributes:
| Name | Type | Description |
|---|---|---|
train_losses_ |
The list of the average loss of each epoch, set by
|
|
validation_losses_ |
The list of the validation loss of each epoch, set by
|
Example
import numpy as np
from torch import nn
from eigenkit.torch.estimators import GenericRegressor
from eigenkit.torch.layers import Basic
rng = np.random.default_rng(0)
X_train, X_test = rng.normal(size=(30, 8)), rng.normal(size=(5, 8))
y_train = X_train.sum(axis=1)
# A plain PyTorch network.
net = nn.Sequential(nn.Linear(8, 16), nn.ReLU(), nn.Linear(16, 1))
reg = GenericRegressor(model=net, in_features=8, epochs=30)
reg.fit(X_train, y_train)
preds = reg.predict(X_test)
# A quantum layer with a classical head.
q = Basic(n_qubits=4, depth=2)
hybrid = nn.Sequential(q, nn.Linear(4, 1))
reg2 = GenericRegressor(model=hybrid, in_features=4)
accepts_sequence_input
property
Whether the model expects a 3-D input (batch, seq_len, features).
fit(X, y, X_val=None, y_val=None)
Fit the model on training data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
y
|
ndarray
|
The real-valued targets, of shape |
required |
X_val
|
ndarray | None
|
Optional validation samples, used to compute the validation loss of each epoch. |
None
|
y_val
|
ndarray | None
|
Optional validation targets, used to compute the validation loss of each epoch. |
None
|
Returns:
| Type | Description |
|---|---|
'GenericRegressor'
|
This estimator, so that calls can be chained. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
load(path, *, model=None, provider=None)
classmethod
Load a fitted GenericRegressor from a .eigenkit bundle.
The architecture of the model cannot be rebuilt automatically, so you must give it. The saved weights are loaded into a copy of it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
The path of the |
required |
model
|
Module | None
|
An |
None
|
provider
|
ProviderSpec | None
|
It is ignored. It is kept so that the signature matches the other estimators. |
None
|
Returns:
| Type | Description |
|---|---|
'GenericRegressor'
|
The loaded estimator. |
Raises:
| Type | Description |
|---|---|
SerializationError
|
If |
TypeError
|
If the bundle holds a different class. |
predict(X)
Predict the continuous targets of X. It returns a float32 array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
One prediction for each sample. |
HQNC
Bases: ModelAccessMixin, BaseQuantumClassifier
Hybrid quantum neural network classifier (HQNC).
The model is MinMaxNorm -> quantum_layer -> nn.Linear(q_out, n_classes). If
the number of features of the data differs from the resolved input size of the
quantum layer (derived from in_quantum, n_qubits and layer_type), an
nn.Linear adapter is added in front automatically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
in_features
|
int
|
The number of input features. |
required |
in_quantum
|
int | None
|
The number of inputs that the quantum layer expects. It
defaults to |
None
|
n_qubits
|
int | None
|
The number of qubits in each circuit. It defaults to
|
None
|
depth
|
int
|
The number of repetitions of the variational layer. |
2
|
n_classes
|
int | None
|
The number of output classes. If None, it is inferred from the training labels. |
None
|
layer_type
|
str
|
The quantum layer. It is one of |
'Basic'
|
enc_rotation
|
Literal['RX', 'RY', 'RZ'] | None
|
The encoding rotation: |
None
|
var_rotation
|
Literal['RX', 'RY', 'RZ'] | None
|
The variational rotation of the |
None
|
variational_type
|
Literal['basic', 'strong'] | None
|
The type of variational block: |
None
|
basis
|
Literal['X', 'Y', 'Z'] | None
|
The measurement basis: |
None
|
provider
|
ProviderSpec
|
The backend. It takes the same options as
|
'numpy'
|
lr
|
float
|
The learning rate of the optimiser. |
0.01
|
optimizer
|
str
|
The name of the optimiser. The supported names are |
'adam'
|
optimizer_kwargs
|
dict | None
|
Extra keyword arguments passed to the optimiser. |
None
|
epochs
|
int
|
The number of training epochs. |
50
|
batch_size
|
int
|
The size of each mini-batch. |
32
|
show_progress
|
bool
|
If True, a tqdm progress bar is shown. |
True
|
random_state
|
int | None
|
The seed for the initialisation of the weights. |
42
|
Attributes:
| Name | Type | Description |
|---|---|---|
train_losses_ |
The average cross-entropy loss of each epoch, set by
|
|
validation_losses_ |
The validation cross-entropy loss of each epoch, set
by |
Example
import numpy as np
from eigenkit.torch.estimators import HQNC
rng = np.random.default_rng(0)
X_train, X_test = rng.normal(size=(30, 4)), rng.normal(size=(5, 4))
y_train = np.arange(30) % 3
model = HQNC(in_features=4, depth=2, n_classes=3)
model.fit(X_train, y_train)
predictions = model.predict(X_test)
__init__(in_features, in_quantum=None, n_qubits=None, depth=2, n_classes=None, layer_type='Basic', enc_rotation=None, var_rotation=None, variational_type=None, basis=None, provider='numpy', lr=0.01, optimizer='adam', optimizer_kwargs=None, epochs=50, batch_size=32, show_progress=True, random_state=42)
Initialise a hybrid quantum neural network classifier (HQNC).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
in_features
|
int
|
The number of input features that |
required |
in_quantum
|
int | None
|
The number of inputs that the quantum layer expects. It
defaults to |
None
|
n_qubits
|
int | None
|
The number of qubits in each circuit. It defaults to
|
None
|
depth
|
int
|
The number of repetitions of the variational layer. |
2
|
n_classes
|
int | None
|
The number of output classes. If |
None
|
layer_type
|
str
|
The family of the quantum layer. It is one of |
'Basic'
|
enc_rotation
|
Literal['RX', 'RY', 'RZ'] | None
|
The encoding rotation: |
None
|
var_rotation
|
Literal['RX', 'RY', 'RZ'] | None
|
The variational rotation of the basic ansatz: |
None
|
variational_type
|
Literal['basic', 'strong'] | None
|
The type of variational block: |
None
|
basis
|
Literal['X', 'Y', 'Z'] | None
|
The measurement basis: |
None
|
provider
|
ProviderSpec
|
The backend. It takes the same options as
|
'numpy'
|
lr
|
float
|
The learning rate of the optimiser. |
0.01
|
optimizer
|
str
|
The name of the optimiser. The supported names are
|
'adam'
|
optimizer_kwargs
|
dict | None
|
Extra keyword arguments passed to the optimiser. |
None
|
epochs
|
int
|
The number of training epochs. |
50
|
batch_size
|
int
|
The size of each mini-batch. |
32
|
show_progress
|
bool
|
If True, a tqdm progress bar is shown during training. |
True
|
random_state
|
int | None
|
The seed for the initialisation of the weights. |
42
|
fit(X, y, X_val=None, y_val=None)
Fit the classifier on training data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
y
|
ndarray
|
The class labels, of shape |
required |
X_val
|
ndarray | None
|
Optional validation samples, used to compute the validation loss of each epoch. |
None
|
y_val
|
ndarray | None
|
Optional validation labels, used to compute the validation loss of each epoch. |
None
|
Returns:
| Type | Description |
|---|---|
HQNC
|
This estimator, so that calls can be chained. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
predict(X)
Predict the class labels of X.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
One prediction for each sample. |
predict_proba(X)
Predict the probability of each class, with a softmax over the logits.
It returns a float32 array of shape (n_samples, n_classes). Each row
sums to 1.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The probabilities, of shape |
HQNR
Bases: ModelAccessMixin, BaseQuantumRegressor
Hybrid quantum neural network regressor (HQNR).
It is the regression counterpart of HQNC. The model is
MinMaxNorm -> quantum_layer -> nn.Linear(q_out, 1). If the number of
features of the data differs from the resolved input size of the quantum
layer, an nn.Linear adapter is added in front automatically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
in_features
|
int
|
The number of input features. |
required |
in_quantum
|
int | None
|
The number of inputs that the quantum layer expects. It
defaults to |
None
|
n_qubits
|
int | None
|
The number of qubits in each circuit. It defaults to
|
None
|
depth
|
int
|
The number of repetitions of the variational layer. |
2
|
layer_type
|
str
|
The quantum layer. It is one of |
'Basic'
|
enc_rotation
|
Literal['RX', 'RY', 'RZ'] | None
|
The encoding rotation: |
None
|
var_rotation
|
Literal['RX', 'RY', 'RZ'] | None
|
The variational rotation of the |
None
|
variational_type
|
Literal['basic', 'strong'] | None
|
The type of variational block: |
None
|
basis
|
Literal['X', 'Y', 'Z'] | None
|
The measurement basis: |
None
|
provider
|
ProviderSpec
|
The backend. It takes the same options as
|
'numpy'
|
lr
|
float
|
The learning rate of the optimiser. |
0.01
|
optimizer
|
str
|
The name of the optimiser. The supported names are |
'adam'
|
optimizer_kwargs
|
dict | None
|
Extra keyword arguments passed to the optimiser. |
None
|
epochs
|
int
|
The number of training epochs. |
50
|
batch_size
|
int
|
The size of each mini-batch. |
32
|
show_progress
|
bool
|
If True, a tqdm progress bar is shown. |
True
|
loss_func
|
str
|
The regression loss: |
'mse'
|
huber_delta
|
float
|
The threshold of the Huber loss. |
1.0
|
huber_reduction
|
str
|
The reduction of the Huber loss: |
'mean'
|
random_state
|
int | None
|
The seed. |
42
|
Attributes:
| Name | Type | Description |
|---|---|---|
train_losses_ |
The training loss of each epoch, set by |
|
validation_losses_ |
The validation loss of each epoch, set by |
Example
fit(X, y, X_val=None, y_val=None)
Fit the regressor on training data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
y
|
ndarray
|
The real-valued targets, of shape |
required |
X_val
|
ndarray | None
|
Optional validation samples, used to compute the validation loss of each epoch. |
None
|
y_val
|
ndarray | None
|
Optional validation targets, used to compute the validation loss of each epoch. |
None
|
Returns:
| Type | Description |
|---|---|
HQNR
|
This estimator, so that calls can be chained. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
predict(X)
Predict the continuous targets of X. It returns a float32 array.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
One prediction for each sample. |
QuantumTimeSeriesClassifier
Bases: BaseQuantumClassifier
Supervised wrapper for time-series classification.
It builds sliding windows over the rows of X (one row for each time step).
Each window has shape (in_size, n_features). Stacked along the batch axis,
they form an array of shape (n_windows, in_size, n_features), ready for
sequence models such as RecurrentHQNC. When autoregressive=True, an extra
last channel holds the target value of each timestep, so each step has
n_features + 1 values. For a window that starts at row i, the
classification target is y[i + in_size - 1 + shift].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
estimator
|
Any
|
The inner estimator. It must have |
required |
in_size
|
int | None
|
The length of the window, in time steps. If None, it is
treated as |
None
|
shift
|
int
|
How many steps after the last timestep of the window the target
is. It must be zero or more. |
1
|
autoregressive
|
bool
|
If True, a channel with |
False
|
Attributes:
| Name | Type | Description |
|---|---|---|
classes_ |
The distinct class labels seen by |
|
train_losses_ |
The training loss of each epoch, copied from the inner
estimator if it has |
Example
import numpy as np
from eigenkit.torch.estimators import (
QuantumTimeSeriesClassifier, RecurrentHQNC,
)
rng = np.random.default_rng(0)
X_train, X_test = rng.normal(size=(40, 4)), rng.normal(size=(15, 4))
y_train = np.arange(40) % 2
inner = RecurrentHQNC(seq_feature_dim=4, rnn_hidden_dim=4, depth=2)
model = QuantumTimeSeriesClassifier(estimator=inner, in_size=10, shift=1)
model.fit(X_train, y_train)
predictions = model.predict(X_test)
output
property
The number of classes.
After fit(), it is the number of classes seen. Before, it is the
n_classes of the inner estimator, or None if it has none.
fit(X, y)
Fit the inner classifier on the windows and their labels.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The features in time order, of shape |
required |
y
|
ndarray
|
The class labels, of shape |
required |
Returns:
| Type | Description |
|---|---|
'QuantumTimeSeriesClassifier'
|
This estimator, so that calls can be chained. |
load(path, *, provider=None, model=None)
classmethod
Load a fitted time-series classifier wrapper from a .eigenkit bundle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
The path of the |
required |
provider
|
ProviderSpec | None
|
An optional provider that replaces the saved one. It is passed to the inner estimator. |
None
|
model
|
Any
|
The |
None
|
Returns:
| Type | Description |
|---|---|
'QuantumTimeSeriesClassifier'
|
The loaded wrapper. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the bundle holds a different class. |
SerializationError
|
If the inner estimator needs |
predict(X, y_history=None)
Predict the class labels of the windows of X.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The features in time order, of shape |
required |
y_history
|
ndarray | None
|
The past class labels, aligned with the rows of |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
The predicted labels, of shape |
predict_proba(X, y_history=None)
Return the estimated class probabilities of the windows of X.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The features in time order, of shape |
required |
y_history
|
ndarray | None
|
The past class labels. It is required when
|
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
A float32 array of shape |
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
If the inner estimator has no |
score(X, y, *, return_dict=False)
Score the estimator on the window targets, aligned as in predict.
By default, it returns the accuracy, for compatibility with scikit-learn
(cross_val_score, GridSearchCV). Pass return_dict=True to get a
dict with accuracy, f1 (weighted), precision (weighted) and
recall (weighted).
Note
When autoregressive=True, the true labels y are used as the
autoregressive history channel (teacher forcing). This is the correct
behaviour for held-out evaluation, but it means that score cannot be
called without the true labels of all the timesteps in X.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
y
|
ndarray
|
One target for each sample, of shape |
required |
return_dict
|
bool
|
If True, every metric is returned in a dict,
instead of the single main score. Default: |
False
|
Returns:
| Type | Description |
|---|---|
float | dict[str, float]
|
The accuracy, or a dict of metrics when |
QuantumTimeSeriesRegressor
Bases: BaseQuantumRegressor
Supervised wrapper with a single output, for time-series regression.
It builds sliding windows over the rows of X (one row for each time step).
Each window has shape (in_size, n_features). Stacked along the batch axis,
they form an array of shape (n_windows, in_size, n_features), ready for
sequence models such as torch.nn.LSTM. When autoregressive=True, an extra
last channel holds the target value of each timestep, so each step has
n_features + 1 values. For a window that starts at row i, the regression
target is y[i + in_size - 1 + shift].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
estimator
|
Any
|
The inner estimator. It must have |
required |
in_size
|
int | None
|
The length of the window, in time steps. If None, it is
treated as |
None
|
shift
|
int
|
How many steps after the last timestep of the window the target
is. It must be zero or more. |
1
|
autoregressive
|
bool
|
If True, a channel with |
False
|
Attributes:
| Name | Type | Description |
|---|---|---|
train_losses_ |
The training loss of each epoch, copied from the inner
estimator if it has |
Example
import numpy as np
from eigenkit.torch.estimators import QuantumTimeSeriesRegressor, RecurrentHQNR
rng = np.random.default_rng(0)
X_train, X_test = rng.normal(size=(40, 3)), rng.normal(size=(15, 3))
y_train = np.sin(np.arange(40) / 4)
# The inner estimator should accept X of shape (batch, in_size, n_features).
inner = RecurrentHQNR(seq_feature_dim=3, rnn_hidden_dim=4, epochs=5)
model = QuantumTimeSeriesRegressor(estimator=inner, in_size=10, shift=1)
model.fit(X_train, y_train)
predictions = model.predict(X_test)
output
property
The number of outputs, which is always 1.
fit(X, y)
Fit the inner estimator on the windows and their targets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The features in time order, of shape |
required |
y
|
ndarray
|
The targets, of shape |
required |
Returns:
| Type | Description |
|---|---|
'QuantumTimeSeriesRegressor'
|
This estimator, so that calls can be chained. |
load(path, *, provider=None, model=None)
classmethod
Load a fitted time-series wrapper from a .eigenkit bundle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
The path of the |
required |
provider
|
ProviderSpec | None
|
An optional provider that replaces the saved one. It is passed to the inner estimator. |
None
|
model
|
Any
|
The |
None
|
Returns:
| Type | Description |
|---|---|
'QuantumTimeSeriesRegressor'
|
The loaded wrapper. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the bundle holds a different class. |
SerializationError
|
If the inner estimator needs |
predict(X, y_history=None)
Predict the regression targets of the windows of X.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The features in time order, of shape |
required |
y_history
|
ndarray | None
|
The past targets, aligned with the rows of |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
The predictions, of shape |
score(X, y, *, return_dict=False)
Score the estimator on the window targets, aligned as in predict.
By default, it returns R², for compatibility with scikit-learn
(cross_val_score, GridSearchCV). Pass return_dict=True to get a
dict with r2, mse, mae, rmse and mape.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The samples, of shape |
required |
y
|
ndarray
|
One target for each sample, of shape |
required |
return_dict
|
bool
|
If True, every metric is returned in a dict,
instead of the single main score. Default: |
False
|
Returns:
| Type | Description |
|---|---|
float | dict[str, float]
|
The |
RecurrentHQNC
Bases: ModelAccessMixin, BaseQuantumClassifier
Hybrid classifier: a recurrent encoder, a quantum layer and a linear class head.
The recurrent encoder is a recurrent neural network (RNN). The estimator
expects 3-D inputs of shape (n_samples, seq_len, seq_feature_dim). By
default, only the last timestep of the RNN output goes to the quantum layer.
Set rnn_return_last_timestep=False, together with sequence_length, to use
the full RNN output (flattened) instead. The quantum part is the same as in
HQNC: MinMaxNorm, the quantum layer and
an nn.Linear head.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seq_feature_dim
|
int
|
The number of features at each time step (the last axis
of |
required |
rnn_type
|
Literal['rnn', 'gru', 'lstm']
|
The type of recurrent layer: |
'gru'
|
rnn_hidden_dim
|
int
|
The hidden size in each direction. |
32
|
rnn_num_layers
|
int
|
The number of stacked RNN layers. |
1
|
rnn_dropout
|
float
|
The dropout between the RNN layers. It applies only if
|
0.0
|
rnn_bidirectional
|
bool
|
If True, the RNN is bidirectional, and its output size doubles. |
False
|
rnn_return_last_timestep
|
bool
|
If True, only the last output step is kept.
Otherwise, the full sequence is flattened, which requires
|
True
|
sequence_length
|
int | None
|
The number of time steps in each sample. It is required
when |
None
|
in_quantum
|
int | None
|
The number of inputs of the quantum layer. It defaults to the
size of the RNN output that reaches the quantum layer: |
None
|
n_qubits
|
int | None
|
The number of qubits in each circuit. It defaults to
|
None
|
depth
|
int
|
The number of repetitions of the variational layer. |
2
|
n_classes
|
int | None
|
The number of output classes. If |
None
|
layer_type
|
str
|
The quantum layer. It is one of |
'Basic'
|
enc_rotation
|
Literal['RX', 'RY', 'RZ'] | None
|
The encoding rotation: |
None
|
var_rotation
|
Literal['RX', 'RY', 'RZ'] | None
|
The variational rotation of the basic ansatz: |
None
|
variational_type
|
Literal['basic', 'strong'] | None
|
The type of variational block: |
None
|
basis
|
Literal['X', 'Y', 'Z'] | None
|
The measurement basis: |
None
|
provider
|
ProviderSpec
|
The backend. It takes the same options as
|
'numpy'
|
lr
|
float
|
The learning rate of the optimiser. |
0.01
|
optimizer
|
str
|
The name of the optimiser. The supported names are |
'adam'
|
optimizer_kwargs
|
dict | None
|
Extra keyword arguments passed to the optimiser. |
None
|
epochs
|
int
|
The number of training epochs. |
50
|
batch_size
|
int
|
The size of each mini-batch. |
32
|
show_progress
|
bool
|
If True, a tqdm progress bar is shown during training. |
True
|
random_state
|
int | None
|
The seed for the initialisation of the weights. |
42
|
Attributes:
| Name | Type | Description |
|---|---|---|
train_losses_ |
The cross-entropy loss of each epoch, set by |
|
validation_losses_ |
The validation cross-entropy loss of each epoch, set
by |
fit(X, y, X_val=None, y_val=None)
Fit the estimator on X and y.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The sequences, of shape
|
required |
y
|
ndarray
|
One label for each sequence, of shape |
required |
X_val
|
ndarray | None
|
Optional validation sequences, of the same
shape as |
None
|
y_val
|
ndarray | None
|
The labels of |
None
|
Returns:
| Type | Description |
|---|---|
RecurrentHQNC
|
This estimator, so that calls can be chained. |
predict(X)
Predict a label for every sample in X.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The sequences, of shape
|
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
One prediction for each sequence, of shape |
predict_proba(X)
Predict the class probabilities of every sample in X.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The sequences, of shape
|
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The probabilities, of shape |
RecurrentHQNR
Bases: ModelAccessMixin, BaseQuantumRegressor
Hybrid regressor: a recurrent encoder, a quantum layer and a linear head.
The recurrent encoder is a recurrent neural network (RNN). The estimator
expects 3-D inputs of shape (n_samples, seq_len, seq_feature_dim). By
default, only the last timestep of the RNN output goes to the quantum layer.
Set rnn_return_last_timestep=False, together with sequence_length, to use
the full RNN output (flattened) instead. The quantum part is the same as in
HQNR: MinMaxNorm, the quantum layer and
an nn.Linear head.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seq_feature_dim
|
int
|
The number of features at each time step (the last axis
of |
required |
rnn_type
|
Literal['rnn', 'gru', 'lstm']
|
The type of recurrent layer: |
'gru'
|
rnn_hidden_dim
|
int
|
The hidden size in each direction. |
32
|
rnn_num_layers
|
int
|
The number of stacked RNN layers. |
1
|
rnn_dropout
|
float
|
The dropout between the RNN layers. It applies only if
|
0.0
|
rnn_bidirectional
|
bool
|
If True, the RNN is bidirectional, and its output size doubles. |
False
|
rnn_return_last_timestep
|
bool
|
If True, only the last output step is kept.
Otherwise, the full sequence is flattened, which requires
|
True
|
sequence_length
|
int | None
|
The number of time steps in each sample. It is required
when |
None
|
in_quantum
|
int | None
|
The number of inputs of the quantum layer. It defaults to the
size of the RNN output that reaches the quantum layer: |
None
|
n_qubits
|
int | None
|
The number of qubits in each circuit. It defaults to
|
None
|
depth
|
int
|
The number of repetitions of the variational layer. |
2
|
layer_type
|
str
|
The quantum layer. It is one of |
'Basic'
|
enc_rotation
|
Literal['RX', 'RY', 'RZ'] | None
|
The encoding rotation: |
None
|
var_rotation
|
Literal['RX', 'RY', 'RZ'] | None
|
The variational rotation of the |
None
|
variational_type
|
Literal['basic', 'strong'] | None
|
The type of variational block: |
None
|
basis
|
Literal['X', 'Y', 'Z'] | None
|
The measurement basis: |
None
|
provider
|
ProviderSpec
|
The backend. It takes the same options as
|
'numpy'
|
lr
|
float
|
The learning rate of the optimiser. |
0.01
|
optimizer
|
str
|
The name of the optimiser. |
'adam'
|
optimizer_kwargs
|
dict | None
|
Extra keyword arguments passed to the optimiser. |
None
|
epochs
|
int
|
The number of training epochs. |
50
|
batch_size
|
int
|
The size of each mini-batch. |
32
|
show_progress
|
bool
|
If True, a tqdm progress bar is shown. |
True
|
loss_func
|
str
|
The regression loss: |
'mse'
|
huber_delta
|
float
|
The threshold of the Huber loss. |
1.0
|
huber_reduction
|
str
|
The reduction of the Huber loss: |
'mean'
|
random_state
|
int | None
|
The seed. |
42
|
Attributes:
| Name | Type | Description |
|---|---|---|
train_losses_ |
The training loss of each epoch, set by |
|
validation_losses_ |
The validation loss of each epoch, set by |
fit(X, y, X_val=None, y_val=None)
Fit the estimator on X and y.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The sequences, of shape
|
required |
y
|
ndarray
|
One target for each sequence, of shape |
required |
X_val
|
ndarray | None
|
Optional validation sequences, of the same
shape as |
None
|
y_val
|
ndarray | None
|
The targets of |
None
|
Returns:
| Type | Description |
|---|---|
RecurrentHQNR
|
This estimator, so that calls can be chained. |
predict(X)
Predict a value for every sample in X.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray
|
The sequences, of shape
|
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
One prediction for each sequence, as a float32 array of shape
|
load_model(path, *, provider=None, model=None)
Load any saved model. The class of the model is read from metadata.json.
Load only bundles that you trust. A bundle can contain joblib pickles, and
unpickling runs code, as with torch.load or joblib.load.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
The path to the |
required |
provider
|
ProviderSpec | None
|
A provider that replaces the saved one. It is passed to the
|
None
|
model
|
Any
|
The |
None
|
Returns:
| Type | Description |
|---|---|
BaseQuantumEstimator
|
The loaded estimator, an instance of the class named in the bundle. |