{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Variational quantum classifier\n", "\n", "- Trains a `VQCClassifier` on a synthetic dataset, on the `torch` backend.\n", "- Then `VQCRegressor`, the same circuit read as a value." ] }, { "cell_type": "markdown", "id": "6e675f82", "metadata": {}, "source": [ "### 1. Data\n", "\n", "- `make_classification`, 200 samples, 4 features, 2 classes.\n", "- `normalize=\"minmax\"` is fit on the train split only.\n", "- `AngleEmbedding` prescaling maps it to [0, pi] during `setup()`." ] }, { "cell_type": "code", "id": "4b9f82c6", "metadata": { "ExecuteTime": { "end_time": "2026-09-19T10:49:39.432753753Z", "start_time": "2026-09-19T10:49:39.403662618Z" } }, "source": [ "import numpy as np\n", "from sklearn.datasets import make_classification\n", "\n", "X, y = make_classification(\n", " n_samples=200,\n", " n_features=4,\n", " n_informative=4,\n", " n_redundant=0,\n", " n_classes=2,\n", " random_state=42,\n", ")" ], "outputs": [], "execution_count": 9 }, { "cell_type": "code", "id": "de5f8343", "metadata": { "ExecuteTime": { "end_time": "2026-09-19T10:49:39.511200937Z", "start_time": "2026-09-19T10:49:39.462107284Z" } }, "source": [ "from pyqit import DataModule, set_backend\n", "\n", "set_backend(\"torch\")\n", "\n", "dm = DataModule(\n", " X=X,\n", " y=y,\n", " normalize=\"minmax\",\n", " batch_size=16,\n", " split=(0.7, 0.15, 0.15),\n", " seed=42,\n", ")" ], "outputs": [], "execution_count": 10 }, { "cell_type": "markdown", "id": "db59580f", "metadata": {}, "source": [ "### 2. Model and training\n", "\n", "- 4 qubits, 3 layers, `SELAnsatz`, `AngleEmbedding`.\n", "- 15 epochs at lr 0.05.\n", "- `fit` returns a `TrainingHistory`." ] }, { "cell_type": "code", "id": "2ed25f29", "metadata": { "ExecuteTime": { "end_time": "2026-09-19T10:49:41.931095401Z", "start_time": "2026-09-19T10:49:39.525389444Z" } }, "source": [ "from pyqit import Trainer\n", "from pyqit.ansatzes import SELAnsatz\n", "from pyqit.core import AngleEmbedding\n", "from pyqit.models import VQCClassifier\n", "\n", "# Initialize the VQC\n", "model = VQCClassifier(\n", " n_qubits=4,\n", " n_layers=3,\n", " n_classes=2,\n", " ansatz=SELAnsatz,\n", " encoder=AngleEmbedding,\n", ")\n", "\n", "# Set up the Trainer\n", "trainer = Trainer(max_epochs=15, learning_rate=0.05)\n", "\n", "history = trainer.fit(model, datamodule=dm)" ], "outputs": [ { "data": { "text/plain": [ "\u001b[1;36m \u001b[0m\u001b[1;36mParameter \u001b[0m\u001b[1;36m \u001b[0m\u001b[1;36m \u001b[0m\u001b[1;36mValue \u001b[0m\u001b[1;36m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mModel Name \u001b[0m\u001b[2m \u001b[0m\u001b[1m \u001b[0m\u001b[1mVQCClassifier \u001b[0m\u001b[1m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mBackend \u001b[0m\u001b[2m \u001b[0m\u001b[1m \u001b[0m\u001b[1mTorch \u001b[0m\u001b[1m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mQubits \u001b[0m\u001b[2m \u001b[0m\u001b[1m \u001b[0m\u001b[1m4 \u001b[0m\u001b[1m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mAnsatz \u001b[0m\u001b[2m \u001b[0m\u001b[1m \u001b[0m\u001b[1mSELAnsatz \u001b[0m\u001b[1m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mEncoder \u001b[0m\u001b[2m \u001b[0m\u001b[1m \u001b[0m\u001b[1mAngleEmbedding\u001b[0m\u001b[1m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mTrainable Params \u001b[0m\u001b[2m \u001b[0m\u001b[1m \u001b[0m\u001b[1m36 \u001b[0m\u001b[1m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mDevice \u001b[0m\u001b[2m \u001b[0m\u001b[1m \u001b[0m\u001b[1mdefault.qubit \u001b[0m\u001b[1m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mDiff Method \u001b[0m\u001b[2m \u001b[0m\u001b[1m \u001b[0m\u001b[1mbackprop \u001b[0m\u001b[1m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mOptimizer \u001b[0m\u001b[2m \u001b[0m\u001b[1m \u001b[0m\u001b[1mADAM \u001b[0m\u001b[1m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mLearning Rate \u001b[0m\u001b[2m \u001b[0m\u001b[1m \u001b[0m\u001b[1m0.05 \u001b[0m\u001b[1m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mTrain / Val Samples \u001b[0m\u001b[2m \u001b[0m\u001b[1m \u001b[0m\u001b[1m140 / 30 \u001b[0m\u001b[1m \u001b[0m\n" ], "text/html": [ "
Parameter Value \n", " Model Name VQCClassifier \n", " Backend Torch \n", " Qubits 4 \n", " Ansatz SELAnsatz \n", " Encoder AngleEmbedding \n", " Trainable Params 36 \n", " Device default.qubit \n", " Diff Method backprop \n", " Optimizer ADAM \n", " Learning Rate 0.05 \n", " Train / Val Samples 140 / 30 \n", "\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "\n" ], "text/html": [ "
\n",
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"GPU available: True (cuda), used: False\n",
"TPU available: False, using: 0 TPU cores\n",
"/home/aryan/PyQit/.venv/lib/python3.12/site-packages/lightning/pytorch/trainer/setup.py:175: GPU available but not used. You can set it by doing `Trainer(accelerator='gpu')`.\n",
"💡 Tip: For seamless cloud logging and experiment tracking, try installing [litlogger](https://pypi.org/project/litlogger/) to enable LitLogger, which logs metrics and artifacts automatically to the Lightning Experiments platform.\n",
"`Trainer(limit_val_batches=1.0)` was configured so 100% of the batches will be used..\n"
]
},
{
"data": {
"text/plain": [
"Output()"
],
"application/vnd.jupyter.widget-view+json": {
"version_major": 2,
"version_minor": 0,
"model_id": "25c7c799264945e595bd01c9c6c86c5a"
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"/home/aryan/PyQit/.venv/lib/python3.12/site-packages/lightning/pytorch/utilities/_pytree.py:21: \n",
"`isinstance(treespec, LeafSpec)` is deprecated, use `isinstance(treespec, TreeSpec) and treespec.is_leaf()` \n",
"instead.\n"
],
"text/html": [
"/home/aryan/PyQit/.venv/lib/python3.12/site-packages/lightning/pytorch/utilities/_pytree.py:21: \n",
"`isinstance(treespec, LeafSpec)` is deprecated, use `isinstance(treespec, TreeSpec) and treespec.is_leaf()` \n",
"instead.\n",
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"/home/aryan/PyQit/.venv/lib/python3.12/site-packages/lightning/pytorch/trainer/connectors/data_connector.py:434: \n",
"The 'val_dataloader' does not have many workers which may be a bottleneck. Consider increasing the value of the \n",
"`num_workers` argument` to `num_workers=15` in the `DataLoader` to improve performance.\n"
],
"text/html": [
"/home/aryan/PyQit/.venv/lib/python3.12/site-packages/lightning/pytorch/trainer/connectors/data_connector.py:434: \n",
"The 'val_dataloader' does not have many workers which may be a bottleneck. Consider increasing the value of the \n",
"`num_workers` argument` to `num_workers=15` in the `DataLoader` to improve performance.\n",
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"/home/aryan/PyQit/.venv/lib/python3.12/site-packages/lightning/pytorch/trainer/connectors/data_connector.py:434: \n",
"The 'train_dataloader' does not have many workers which may be a bottleneck. Consider increasing the value of the \n",
"`num_workers` argument` to `num_workers=15` in the `DataLoader` to improve performance.\n"
],
"text/html": [
"/home/aryan/PyQit/.venv/lib/python3.12/site-packages/lightning/pytorch/trainer/connectors/data_connector.py:434: \n",
"The 'train_dataloader' does not have many workers which may be a bottleneck. Consider increasing the value of the \n",
"`num_workers` argument` to `num_workers=15` in the `DataLoader` to improve performance.\n",
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"`Trainer.fit` stopped: `max_epochs=15` reached.\n"
]
},
{
"data": {
"text/plain": [],
"text/html": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\u001b[1;32m[\u001b[0m\u001b[1;32mTrainer\u001b[0m\u001b[1;32m]\u001b[0m Training complete.\n"
],
"text/html": [
"[Trainer] Training complete.\n",
"\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"execution_count": 11
},
{
"cell_type": "markdown",
"id": "778213e8",
"metadata": {},
"source": [
"### 3. Loss curve\n",
"\n",
"- `history.as_dict()` returns the per-epoch metrics."
]
},
{
"cell_type": "code",
"id": "28db8a54",
"metadata": {
"ExecuteTime": {
"end_time": "2026-09-19T10:49:42.046318124Z",
"start_time": "2026-09-19T10:49:41.937691322Z"
}
},
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"# Extract metrics from the history\n",
"train_loss = history.as_dict()[\"train_loss\"]\n",
"val_loss = history.as_dict()[\"val_loss\"]\n",
"epochs = range(1, len(train_loss) + 1)\n",
"\n",
"plt.figure(figsize=(8, 5))\n",
"plt.plot(epochs, train_loss, label=\"Train Loss\", marker=\"o\")\n",
"plt.plot(epochs, val_loss, label=\"Validation Loss\", marker=\"o\")\n",
"plt.title(\"VQC Training History\")\n",
"plt.xlabel(\"Epoch\")\n",
"plt.ylabel(\"Loss\")\n",
"plt.legend()\n",
"plt.grid(True)\n",
"plt.show()"
],
"outputs": [
{
"data": {
"text/plain": [
"