# QML

The `qml` package is the scikit-learn side of the library for quantum machine learning (QML). It holds kernel support vector machines (SVMs) and quantum reservoir estimators. Everything here follows the scikit-learn interface, with `fit(X, y)`, `predict(X)` and `score(X, y)`, and runs without PyTorch.

**Install:** the `qml` extra (`pip install eigenkit[qml]`) installs scikit-learn, and not PyTorch. The estimators run on the built-in NumPy simulator. To run them on another backend, install its extra and pass `provider=`, for example `eigenkit[pennylane]` and `provider="pennylane"`.

## QSVC

`QSVC` is the quantum support vector classifier. It passes the quantum kernel matrix to scikit-learn's `SVC(kernel="precomputed")`.

```python
from eigenkit import QSVC
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"]

model = QSVC(feature_map="AngleCNOT", reps=2, C=1.0)
model.fit(X_train, y_train)
predictions = model.predict(X_test)
```

The accepted `feature_map` values, what `reps` does, and how the kernel value is computed are explained in [Quantum Kernels](https://docs.kit.eigenorbit.com/user-guide/kernels/index.md). The defaults of `QSVC`, `feature_map="Angle"` and `reps=1`, differ from those of `QuantumKernel` (`"AngleCNOT"` and `reps=2`).

Any other kernel, such as a custom map, a trained map, or a kernel on hardware, is passed whole with `kernel=`. `feature_map`, `reps` and `provider` are then ignored, and the fitted copy of the kernel is `model.kernel_`. `scale` multiplies the inputs before they are encoded, so this bandwidth can be tuned like `C`:

```python
from eigenkit import QuantumKernel

kernel = QuantumKernel(n_features=X_train.shape[1], feature_map="AngleCNOT", reps=2)
model = QSVC(kernel=kernel, scale=0.5).fit(X_train, y_train)
margins = model.decision_function(X_test)
```

`decision_function(X)` returns the margins of the SVM. `probability=True` enables `predict_proba` through a sigmoid calibration, as in `CalibratedClassifierCV(SVC(), ensemble=False)`. The predictions still come from the plain `SVC`.

## QSVR

`QSVR` is the quantum support vector regressor. It works like `QSVC`, but it passes the kernel matrix to scikit-learn's `SVR(kernel="precomputed")`.

```python
from eigenkit import QSVR
from eigenkit.datasets import load_dataset

data = load_dataset("concrete")
X_reg, y_reg = data["X_train"][:100], data["y_train"][:100]

model = QSVR(feature_map="Angle", reps=1, C=1.0, epsilon=0.1)
model.fit(X_reg, y_reg)
```

## Use inside a scikit-learn Pipeline

The kernel estimators can also be the last step of a scikit-learn `Pipeline`. When you tune them with `GridSearchCV`, prefix each parameter with the name of the step, including the bandwidth `scale`:

```python
from sklearn.datasets import make_moons
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from eigenkit import QSVC

X, y = make_moons(n_samples=40, noise=0.1, random_state=0)

search = GridSearchCV(
    Pipeline(
        [
            ("scale", StandardScaler()),
            (
                "qsvc",
                QSVC(
                    feature_map="Angle",
                    reps=1,
                    C=1.0,
                    probability=False,
                ),
            ),
        ]
    ),
    param_grid={
        "qsvc__C": [0.1, 1.0, 10.0],
        "qsvc__feature_map": ["Angle", "AngleCNOT"],
        "qsvc__scale": [0.5, 1.0],
    },
    scoring="accuracy",
    cv=3,
)

search.fit(X, y)
predictions = search.predict(X[:5])
```

## Quantum reservoir computing

`QuantumReservoirClassifier` and `QuantumReservoirRegressor` use a quantum circuit as a fixed dynamical system that is *not trained*, called the **reservoir**. They train only a cheap linear **readout** on the features that the reservoir produces. The weights of the circuit are drawn once from `random_state` and then frozen, so there is no gradient descent and no PyTorch. Fitting solves a ridge or logistic regression in closed form.

The data is a batch of sequences. `X` has shape `(n_sequences, n_timesteps, n_features)`, and `y` has shape `(n_sequences, n_timesteps)`, with one target per time step.

```python
import numpy as np
from eigenkit import Encoding, Variational
from eigenkit import QuantumReservoirRegressor

rng = np.random.default_rng(0)
X = rng.uniform(-1, 1, size=(40, 50, 3))
y = np.zeros((40, 50))
y[:, 1:] = X[:, :-1, 0]  # predict the previous step's first channel

reservoir = QuantumReservoirRegressor(
    blocks=[Encoding(in_features=3, rotation="RY"), Variational(depth=3, rotation="RY")],
    state_policy="leaky",
    leak=0.5,  # fading memory
    features="probabilities",
    washout=5,
)
reservoir.fit(X, y)
print(reservoir.predict(X).shape)  # (40, 50)
```

`QuantumReservoirClassifier` takes the same arguments, with one exception. It accepts integer or label targets, reads out through a logistic model, and adds `predict_proba`. The exception is the regularisation of the readout: the `ridge` of the regressor (`float`, default `1e-06`) becomes `C` on the classifier (`float`, default `1.0`). `C` is the inverse of the regularisation strength, so a larger `C` means *less* regularisation.

| Parameter      | Type               | Default   | Description                                                                                                                       |
| -------------- | ------------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `blocks`       | `list[Block]`      | Required  | The frozen reservoir circuit.                                                                                                     |
| `state_policy` | `str`              | `"carry"` | One of `"carry"`, `"leaky"` or `"stateless"`.                                                                                     |
| `window`       | `int`              | `1`       | The number of time steps encoded per step with `"stateless"`. The circuit must then encode `window * n_features` inputs.          |
| `leak`         | `float`            | `1.0`     | The mixing rate for `"leaky"`. At `1.0`, it is the same as `"carry"`.                                                             |
| `features`     | `str \| list[str]` | `"z"`     | One of `"z"`, `"probabilities"` or `"amplitudes"`, a Hamiltonian string such as `"0.5 Z0 X1 - 0.3 Y0"`, or a list of observables. |
| `ridge`        | `float`            | `1e-06`   | The regularisation of the linear readout.                                                                                         |
| `washout`      | `int`              | `0`       | The number of first time steps dropped when the readout is fitted. Predictions are still produced for every time step.            |
| `weight_scale` | `float`            | `1.0`     | The scale of the frozen weights that are drawn. Larger values give more energetic dynamics.                                       |
| `provider`     | `ProviderSpec`     | `"numpy"` | The backend, with the same options as `Circuit(provider=...)`.                                                                    |
| `random_state` | `int \| None`      | `42`      | The seed of the frozen weights. The reservoir is random, but fixed.                                                               |

Fading memory matters

A purely unitary carry (`state_policy="carry"`, the default) preserves the norm, but it tends to scramble the history into a form that a linear readout cannot recover. So it often has little memory that can be used. Some dissipation is what makes a reservoir work in practice: `"leaky"` with a `leak` of about `0.3` to `0.7` is usually the right starting point for temporal tasks. The [memory capacity example](https://docs.kit.eigenorbit.com/examples/reservoir-memory/index.md) shows this directly.

The layers under these wrappers, which are the driver, the policy classes, the feature extractors and the readout, are documented in [Reservoir Computing](https://docs.kit.eigenorbit.com/user-guide/reservoir/index.md).

## API reference

### `eigenkit.qml.QSVC`

Bases: `BaseQuantumClassifier`

Quantum support vector classifier (QSVC).

It computes a quantum kernel matrix from a fidelity circuit, and then uses `SVC(kernel="precomputed")` from scikit-learn.

Parameters:

| Name           | Type            | Description                                                                                                                                                                                                                                                                                    | Default                                                                                                                                                              |
| -------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `feature_map`  | `str`           | The feature map. It is "Angle" (angle encoding into a product state) or "AngleCNOT" (angle encoding with ladders of controlled-NOT (CNOT) gates). Default: "Angle". It is ignored when kernel is given.                                                                                        | `'Angle'`                                                                                                                                                            |
| `reps`         | `int`           | The number of repetitions of the feature map. Default: 1. It is ignored when kernel is given.                                                                                                                                                                                                  | `1`                                                                                                                                                                  |
| `C`            | `float`         | The regularisation parameter of the support vector machine. Default: 1.0.                                                                                                                                                                                                                      | `1.0`                                                                                                                                                                |
| `probability`  | `bool`          | If True, the model gives Platt-scaled probabilities. If False (the default), predict_proba is unavailable. The calibration is a sigmoid fitted by cross-validation on the training kernel, as in CalibratedClassifierCV(SVC(), ensemble=False). The predictions still come from the plain SVC. | `False`                                                                                                                                                              |
| `provider`     | `ProviderSpec`  | The backend. It takes the same options as Circuit(provider=...). Any backend with a statevector or a zero_state_probability method works, including Qiskit Runtime and IQM hardware. Default: "numpy". It is ignored when kernel is given.                                                     | `'numpy'`                                                                                                                                                            |
| `random_state` | \`int           | None\`                                                                                                                                                                                                                                                                                         | The seed.                                                                                                                                                            |
| `kernel`       | \`QuantumKernel | None\`                                                                                                                                                                                                                                                                                         | A QuantumKernel to use instead of building one from feature_map, reps and provider. It can be a custom kernel, a trained kernel or a hardware kernel. Default: None. |
| `scale`        | `float`         | The bandwidth. The inputs are multiplied by it before they reach the kernel, so it can be tuned with GridSearchCV. Default: 1.0.                                                                                                                                                               | `1.0`                                                                                                                                                                |

Example

```python
import numpy as np
from eigenkit import QSVC, Encoding, QuantumKernel, Variational

rng = np.random.default_rng(0)
X_train, X_test = rng.uniform(0, np.pi, (8, 4)), rng.uniform(0, np.pi, (3, 4))
y_train = np.array([0, 1] * 4)

model = QSVC(feature_map="AngleCNOT", reps=2)
model.fit(X_train, y_train)
predictions = model.predict(X_test)

# Any kernel works, including custom and trained ones.
my_map = [Encoding(in_features=4), Variational(depth=1)]
model = QSVC(kernel=QuantumKernel(n_features=4, feature_map=my_map))
```

#### `__sklearn_is_fitted__()`

Return True when the wrapped scikit-learn `SVC` has been fitted.

#### `decision_function(X)`

Return the signed distance of each sample to the separating hyperplane.

Parameters:

| Name | Type      | Description                                    | Default    |
| ---- | --------- | ---------------------------------------------- | ---------- |
| `X`  | `ndarray` | The samples, of shape (n_samples, n_features). | *required* |

Returns:

| Type      | Description                                                                           |
| --------- | ------------------------------------------------------------------------------------- |
| `ndarray` | An array of shape (n_samples,) for two classes, and (n_samples, n_classes) otherwise. |

#### `fit(X, y)`

Fit the classifier on training data.

Parameters:

| Name | Type      | Description                                    | Default    |
| ---- | --------- | ---------------------------------------------- | ---------- |
| `X`  | `ndarray` | The samples, of shape (n_samples, n_features). | *required* |
| `y`  | `ndarray` | The class labels, of shape (n_samples,).       | *required* |

Returns:

| Type   | Description                                   |
| ------ | --------------------------------------------- |
| `QSVC` | This estimator, so that calls can be chained. |

#### `predict(X)`

Predict the class labels of `X`.

Parameters:

| Name | Type      | Description                                    | Default    |
| ---- | --------- | ---------------------------------------------- | ---------- |
| `X`  | `ndarray` | The samples, of shape (n_samples, n_features). | *required* |

Returns:

| Type      | Description                     |
| --------- | ------------------------------- |
| `ndarray` | One prediction for each sample. |

#### `predict_proba(X)`

Predict the probability of each class. It requires `probability=True`.

Parameters:

| Name | Type      | Description                                    | Default    |
| ---- | --------- | ---------------------------------------------- | ---------- |
| `X`  | `ndarray` | The samples, of shape (n_samples, n_features). | *required* |

Returns:

| Type      | Description                                                                                     |
| --------- | ----------------------------------------------------------------------------------------------- |
| `ndarray` | The probabilities, of shape (n_samples, n_classes), with the columns in the order of classes\_. |

Raises:

| Type         | Description                                      |
| ------------ | ------------------------------------------------ |
| `ValueError` | If the model was created with probability=False. |

### `eigenkit.qml.QSVR`

Bases: `BaseQuantumRegressor`

Quantum support vector regressor (QSVR).

It is the regression counterpart of QSVC. It uses `SVR(kernel="precomputed")` from scikit-learn on the quantum kernel matrix.

Parameters:

| Name           | Type            | Description                                                                                                                                                                                             | Default                                                                                            |
| -------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `feature_map`  | `str`           | The feature map. It is "Angle" (angle encoding into a product state) or "AngleCNOT" (angle encoding with ladders of controlled-NOT (CNOT) gates). Default: "Angle". It is ignored when kernel is given. | `'Angle'`                                                                                          |
| `reps`         | `int`           | The number of repetitions of the feature map. Default: 1. It is ignored when kernel is given.                                                                                                           | `1`                                                                                                |
| `C`            | `float`         | The regularisation parameter of the support vector regressor. Default: 1.0.                                                                                                                             | `1.0`                                                                                              |
| `epsilon`      | `float`         | The width of the epsilon-insensitive tube. Default: 0.1.                                                                                                                                                | `0.1`                                                                                              |
| `provider`     | `ProviderSpec`  | The backend. It takes the same options as Circuit(provider=...). Default: "numpy". It is ignored when kernel is given.                                                                                  | `'numpy'`                                                                                          |
| `random_state` | \`int           | None\`                                                                                                                                                                                                  | The seed.                                                                                          |
| `kernel`       | \`QuantumKernel | None\`                                                                                                                                                                                                  | A QuantumKernel to use instead of building one from feature_map, reps and provider. Default: None. |
| `scale`        | `float`         | The bandwidth. The inputs are multiplied by it before they reach the kernel. Default: 1.0.                                                                                                              | `1.0`                                                                                              |

Example

```python
import numpy as np
from eigenkit import QSVR

rng = np.random.default_rng(0)
X_train, X_test = rng.uniform(0, np.pi, (8, 2)), rng.uniform(0, np.pi, (3, 2))
y_train = np.sin(X_train).sum(axis=1)

model = QSVR(feature_map="Angle", reps=1)
model.fit(X_train, y_train)
predictions = model.predict(X_test)
```

#### `__sklearn_is_fitted__()`

Return True when the wrapped scikit-learn `SVR` has been fitted.

#### `fit(X, y)`

Fit the regressor on training data.

Parameters:

| Name | Type      | Description                                    | Default    |
| ---- | --------- | ---------------------------------------------- | ---------- |
| `X`  | `ndarray` | The samples, of shape (n_samples, n_features). | *required* |
| `y`  | `ndarray` | The float targets, of shape (n_samples,).      | *required* |

Returns:

| Type   | Description                                   |
| ------ | --------------------------------------------- |
| `QSVR` | This estimator, so that calls can be chained. |

#### `predict(X)`

Predict continuous targets for `X`.

Parameters:

| Name | Type      | Description                                    | Default    |
| ---- | --------- | ---------------------------------------------- | ---------- |
| `X`  | `ndarray` | The samples, of shape (n_samples, n_features). | *required* |

Returns:

| Type      | Description                     |
| --------- | ------------------------------- |
| `ndarray` | One prediction for each sample. |

### `eigenkit.qml.QuantumReservoirClassifier`

Bases: `_ReservoirMixin`, `BaseQuantumClassifier`

Quantum reservoir classifier: a fixed random reservoir and a logistic readout.

It uses the same reservoir as QuantumReservoirRegressor. The readout is a scikit-learn `LogisticRegression` on the features of each timestep. `y` holds integer or label targets, of shape `(n_sequences, n_timesteps)`.

Parameters:

| Name           | Type           | Description                                                                                                                                                                                                                                                   | Default                                                                                                                    |
| -------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `blocks`       | `list`         | The architecture of the reservoir circuit, a list of blocks that is assembled once. Its n_inputs must match the policy: F for the policies that carry the state, and window * F for state_policy="stateless", where F is the number of features per timestep. | *required*                                                                                                                 |
| `state_policy` | `str`          | "carry" (the unitary of the circuit carries the state from one step to the next), "stateless" (each step starts from                                                                                                                                          | 0…0⟩ and encodes a sliding window of inputs), or "leaky" (the carried state is mixed with a reset state and renormalised). |
| `window`       | `int`          | The length of the sliding window, for state_policy="stateless".                                                                                                                                                                                               | `1`                                                                                                                        |
| `leak`         | `float`        | The mixing coefficient alpha, for state_policy="leaky".                                                                                                                                                                                                       | `1.0`                                                                                                                      |
| `features`     | `FeaturesSpec` | The features read from the reservoir. It is "z" (the value of ⟨Z⟩ on each qubit, the default), "probabilities", "amplitudes", a Pauli or Hamiltonian string (for example "0.5 Z0 X1 - 0.3 Y0"), or a list of such strings, to read out any observables.       | `'z'`                                                                                                                      |
| `C`            | `float`        | The inverse regularisation strength of the logistic readout, passed to scikit-learn. Smaller values regularise more. This is the only argument that the regressor does not have: there, the readout is a ridge regression controlled by ridge.                | `1.0`                                                                                                                      |
| `washout`      | `int`          | The number of timesteps dropped from the fit of the readout. They are not dropped from the predictions.                                                                                                                                                       | `0`                                                                                                                        |
| `weight_scale` | `float`        | The standard deviation of the sampled reservoir weights.                                                                                                                                                                                                      | `1.0`                                                                                                                      |
| `provider`     | `ProviderSpec` | The backend, which must give access to the statevector. Default: "numpy".                                                                                                                                                                                     | `'numpy'`                                                                                                                  |
| `random_state` | \`int          | None\`                                                                                                                                                                                                                                                        | The seed of the fixed reservoir weights.                                                                                   |

#### `__sklearn_is_fitted__()`

Return True when the readout has been fitted.

#### `fit(X, y)`

Fit the estimator on `X` and `y`.

Parameters:

| Name | Type      | Description                                                                              | Default    |
| ---- | --------- | ---------------------------------------------------------------------------------------- | ---------- |
| `X`  | `ndarray` | The sequences, of shape (n_sequences, n_timesteps, n_features). A 2-D array is rejected. | *required* |
| `y`  | `ndarray` | One target for each timestep, of shape (n_sequences, n_timesteps).                       | *required* |

Returns:

| Type                           | Description                                   |
| ------------------------------ | --------------------------------------------- |
| `'QuantumReservoirClassifier'` | This estimator, so that calls can be chained. |

#### `predict(X)`

Predict a label for every timestep of every sequence in `X`.

Parameters:

| Name | Type      | Description                                                                              | Default    |
| ---- | --------- | ---------------------------------------------------------------------------------------- | ---------- |
| `X`  | `ndarray` | The sequences, of shape (n_sequences, n_timesteps, n_features). A 2-D array is rejected. | *required* |

Returns:

| Type      | Description                                                |
| --------- | ---------------------------------------------------------- |
| `ndarray` | The predicted labels, of shape (n_sequences, n_timesteps). |

#### `predict_proba(X)`

Predict the class probabilities for every timestep of every sequence in `X`.

Parameters:

| Name | Type      | Description                                                                              | Default    |
| ---- | --------- | ---------------------------------------------------------------------------------------- | ---------- |
| `X`  | `ndarray` | The sequences, of shape (n_sequences, n_timesteps, n_features). A 2-D array is rejected. | *required* |

Returns:

| Type      | Description                                                                                                      |
| --------- | ---------------------------------------------------------------------------------------------------------------- |
| `ndarray` | The probabilities, of shape (n_sequences, n_timesteps, n_classes), with the last axis in the order of classes\_. |

#### `score(X, y)`

Score the estimator on `X` against `y`.

Parameters:

| Name | Type      | Description                                                                              | Default    |
| ---- | --------- | ---------------------------------------------------------------------------------------- | ---------- |
| `X`  | `ndarray` | The sequences, of shape (n_sequences, n_timesteps, n_features). A 2-D array is rejected. | *required* |
| `y`  | `ndarray` | One target for each timestep, of shape (n_sequences, n_timesteps).                       | *required* |

Returns:

| Type    | Description                                                             |
| ------- | ----------------------------------------------------------------------- |
| `float` | The accuracy of the predictions, over every timestep of every sequence. |

### `eigenkit.qml.QuantumReservoirRegressor`

Bases: `_ReservoirMixin`, `BaseQuantumRegressor`

Quantum reservoir regressor: a fixed random reservoir and a ridge readout.

Parameters:

| Name           | Type           | Description                                                                                                                                                                                                                                                   | Default                                                                                                                    |
| -------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `blocks`       | `list`         | The architecture of the reservoir circuit, a list of blocks that is assembled once. Its n_inputs must match the policy: F for the policies that carry the state, and window * F for state_policy="stateless", where F is the number of features per timestep. | *required*                                                                                                                 |
| `state_policy` | `str`          | "carry" (the unitary of the circuit carries the state from one step to the next), "stateless" (each step starts from                                                                                                                                          | 0…0⟩ and encodes a sliding window of inputs), or "leaky" (the carried state is mixed with a reset state and renormalised). |
| `window`       | `int`          | The length of the sliding window, for state_policy="stateless".                                                                                                                                                                                               | `1`                                                                                                                        |
| `leak`         | `float`        | The mixing coefficient alpha, for state_policy="leaky".                                                                                                                                                                                                       | `1.0`                                                                                                                      |
| `features`     | `FeaturesSpec` | The features read from the reservoir. It is "z" (the value of ⟨Z⟩ on each qubit, the default), "probabilities", "amplitudes", a Pauli or Hamiltonian string (for example "0.5 Z0 X1 - 0.3 Y0"), or a list of such strings, to read out any observables.       | `'z'`                                                                                                                      |
| `ridge`        | `float`        | The strength of the L2 penalty of the linear readout, which is solved in closed form.                                                                                                                                                                         | `1e-06`                                                                                                                    |
| `washout`      | `int`          | The number of timesteps dropped from the fit of the readout. They are not dropped from the predictions.                                                                                                                                                       | `0`                                                                                                                        |
| `weight_scale` | `float`        | The standard deviation of the sampled reservoir weights.                                                                                                                                                                                                      | `1.0`                                                                                                                      |
| `provider`     | `ProviderSpec` | The backend, which must give access to the statevector. Default: "numpy".                                                                                                                                                                                     | `'numpy'`                                                                                                                  |
| `random_state` | \`int          | None\`                                                                                                                                                                                                                                                        | The seed of the fixed reservoir weights.                                                                                   |

#### `__sklearn_is_fitted__()`

Return True when the readout has been fitted.

#### `fit(X, y)`

Fit the estimator on `X` and `y`.

Parameters:

| Name | Type      | Description                                                                                                                      | Default    |
| ---- | --------- | -------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `X`  | `ndarray` | The sequences, of shape (n_sequences, n_timesteps, n_features). A 2-D array is rejected.                                         | *required* |
| `y`  | `ndarray` | One target for each timestep, of shape (n_sequences, n_timesteps), or (n_sequences, n_timesteps, n_outputs) for several outputs. | *required* |

Returns:

| Type                          | Description                                   |
| ----------------------------- | --------------------------------------------- |
| `'QuantumReservoirRegressor'` | This estimator, so that calls can be chained. |

#### `predict(X)`

Predict a value for every timestep of every sequence in `X`.

Parameters:

| Name | Type      | Description                                                                              | Default    |
| ---- | --------- | ---------------------------------------------------------------------------------------- | ---------- |
| `X`  | `ndarray` | The sequences, of shape (n_sequences, n_timesteps, n_features). A 2-D array is rejected. | *required* |

Returns:

| Type      | Description                                                                                                                          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `ndarray` | The predictions, of shape (n_sequences, n_timesteps), or (n_sequences, n_timesteps, n_outputs) when the targets had several outputs. |

#### `score(X, y)`

Score the estimator on `X` against `y`.

Parameters:

| Name | Type      | Description                                                                              | Default    |
| ---- | --------- | ---------------------------------------------------------------------------------------- | ---------- |
| `X`  | `ndarray` | The sequences, of shape (n_sequences, n_timesteps, n_features). A 2-D array is rejected. | *required* |
| `y`  | `ndarray` | One target for each timestep, of shape (n_sequences, n_timesteps).                       | *required* |

Returns:

| Type    | Description                                                                                    |
| ------- | ---------------------------------------------------------------------------------------------- |
| `float` | The coefficient of determination R² of the predictions, over every timestep of every sequence. |
