## `eigenkit.torch.estimators.hqnc`

## `eigenkit.torch.estimators.hqnc.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 in_features.                                                                                                       |
| `n_qubits`         | \`int                        | None\`                                                                                   | The number of qubits in each circuit. It defaults to in_quantum.                                                                                                                       |
| `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.                                                                                                        |
| `layer_type`       | `str`                        | The quantum layer. It is one of "Basic", "Reupload" and "Ensemble".                      | `'Basic'`                                                                                                                                                                              |
| `enc_rotation`     | \`Literal['RX', 'RY', 'RZ']  | None\`                                                                                   | The encoding rotation: "RX", "RY", "RZ" or None.                                                                                                                                       |
| `var_rotation`     | \`Literal['RX', 'RY', 'RZ']  | None\`                                                                                   | The variational rotation of the "basic" ansatz: "RX", "RY", "RZ" or None.                                                                                                              |
| `variational_type` | \`Literal['basic', 'strong'] | None\`                                                                                   | The type of variational block: "basic", "strong" or None.                                                                                                                              |
| `basis`            | \`Literal['X', 'Y', 'Z']     | None\`                                                                                   | The measurement basis: "X", "Y", "Z" or None. For these four arguments, None means "use the default of the layer named by layer_type", which is where each of these values is decided. |
| `provider`         | `ProviderSpec`               | The backend. It takes the same options as Circuit(provider=...).                         | `'numpy'`                                                                                                                                                                              |
| `lr`               | `float`                      | The learning rate of the optimiser.                                                      | `0.01`                                                                                                                                                                                 |
| `optimizer`        | `str`                        | The name of the optimiser. The supported names are "adam", "adamw", "rmsprop" and "sgd". | `'adam'`                                                                                                                                                                               |
| `optimizer_kwargs` | \`dict                       | None\`                                                                                   | Extra keyword arguments passed to the optimiser.                                                                                                                                       |
| `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.                                                                                                                                        |

Attributes:

| Name                 | Type | Description                                                                                  |
| -------------------- | ---- | -------------------------------------------------------------------------------------------- |
| `train_losses_`      |      | The average cross-entropy loss of each epoch, set by fit().                                  |
| `validation_losses_` |      | The validation cross-entropy loss of each epoch, set by fit() when validation data is given. |

Example

```python
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)
```

### `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 (n_samples, in_features).                                                            | *required*                                                                      |
| `y`     | `ndarray` | The class labels, of shape (n_samples,). They can be of any type that scikit-learn's LabelEncoder accepts. | *required*                                                                      |
| `X_val` | \`ndarray | None\`                                                                                                     | Optional validation samples, used to compute the validation loss of each epoch. |
| `y_val` | \`ndarray | None\`                                                                                                     | Optional validation labels, used to compute the validation loss of each epoch.  |

Returns:

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

Raises:

| Type         | Description                             |
| ------------ | --------------------------------------- |
| `ValueError` | If X does not have in_features columns. |

### `load(path, *, provider=None)`

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.                 |
| `provider` | \`ProviderSpec | None\`      | A provider that replaces the saved one. |

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. BaseQuantumEstimator.load() accepts any class. |

### `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, 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 (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\_. |

### `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 .eigenkit is added when it is missing. |
