I am having trouble trying to make a QML model that is within a Qiskit runtime session. The motivation for trying to do it in a session is because with a real QML example (not the toy case below) it was estimated to take 9 days for one iteration with queue times. And with the version of pennylane-qiskit I am using I cannot use this for some reason: from pennylane_qiskit import qiskit_session
. Any suggestions on what to do would be greatly appreciated.
#!/usr/bin/env python
# coding: utf-8
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
import numpy as np
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import joblib
import click
import json
import time
import os
import itertools
import collections.abc
import pandas as pd
import pennylane as qml
from tqdm import tqdm
from qiskit_ibm_runtime import QiskitRuntimeService, Session
os.environ["OMP_NUM_THREADS"] = "12"
# Set random seed for reproducibility
np.random.seed(42)
torch.manual_seed(42)
generator = np.random.default_rng(12958234)
# Synthetic data
X=generator.uniform(-1, 1, (100,5))
y=generator.uniform(-1, 1, (100,))
X_train, X_test, y_train, y_test = X[:80,:],X[80:,:],y[:80],y[80:]
print(X_train.shape,X_test.shape)
# Define custom Dataset
class RegressionDataset(Dataset):
def __init__(self, features, targets):
self.X = torch.from_numpy(features).float()
self.y = torch.from_numpy(targets).float()
def __len__(self):
return len(self.X)
def __getitem__(self, idx):
return self.X[idx], self.y[idx]
# Create DataLoaders
batch_size = 32 * 8
train_dataset = RegressionDataset(X_train, y_train)
test_dataset = RegressionDataset(X_test, y_test)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
# Initial ize device and circuit
num_qubits=5
re_upload_depth=1
n_layers=1
service = QiskitRuntimeService(channel="ibm_quantum", instance='totally_real_instance')
_backend = service.least_busy(operational=True, simulator=False, min_num_qubits=num_qubits)
dev = qml.device("qiskit.remote", wires=num_qubits, backend=_backend,shots=1024,session=Session(backend=_backend))
# Qulacs simulator
# dev = qml.device("qulacs.simulator", wires=num_qubits)
# Simple circuit
@qml.qnode(dev, interface="torch")
def circuit(inputs, weights):
for i in range(re_upload_depth):
qml.AngleEmbedding(inputs, wires=range(num_qubits))
qml.BasicEntanglerLayers(weights, wires=range(num_qubits))
return qml.expval(qml.PauliZ(0))
# Initialize pytorch model
weight_shapes = {"weights": (n_layers, num_qubits)}
print(weight_shapes)
qlayer = qml.qnn.TorchLayer(circuit, weight_shapes)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = torch.nn.Sequential(*[qlayer]).to(device)
print(model)
# Define loss and optimizer
criterion = nn.MSELoss()
learning_rate = 0.001
optimizer = optim.Adam(qlayer.parameters(), lr=learning_rate)
# Training loop
epochs = 10
train_losses = []
test_losses = []
for epoch in tqdm(range(epochs)):
model.train()
running_loss = 0.0
for batch_X, batch_y in train_loader:
optimizer.zero_grad()
batch_X=batch_X.to(device)
batch_y=batch_y.to(device)
outputs = model(batch_X)
loss = criterion(outputs, batch_y)
loss.backward()
optimizer.step()
running_loss += loss.item() * batch_X.size(0)
epoch_loss = running_loss / len(train_loader.dataset)
train_losses.append(epoch_loss)
# Evaluation on test set
model.eval()
test_running_loss = 0.0
with torch.no_grad():
for batch_X, batch_y in test_loader:
outputs = model(batch_X)
loss = criterion(outputs, batch_y)
test_running_loss += loss.item() * batch_X.size(0)
test_epoch_loss = test_running_loss / len(test_loader.dataset)
test_losses.append(test_epoch_loss)
if (epoch+1) % 1 == 0 or epoch == 0:
print(f"Epoch [{epoch+1}/{epochs}] - Train Loss: {epoch_loss:.4f} - Test Loss: {test_epoch_loss:.4f}")
# Evaluation
model.eval()
predictions = []
actuals = []
with torch.no_grad():
for batch_X, batch_y in train_loader:
outputs = model(batch_X)
predictions.extend(outputs.squeeze().tolist())
actuals.extend(batch_y.squeeze().tolist())
mse = mean_squared_error(actuals, predictions)
mae = mean_absolute_error(actuals, predictions)
r2 = r2_score(actuals, predictions)
print(f"\nTest MSE: {mse:.4f}")
print(f"Test MAE: {mae:.4f}")
print(f"Test R$^2$: {r2:.4f}")
Here is the error message:
File "$HOME/BSE5_real/min_ex.py", line 146, in <module>
outputs = model(batch_X)
^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1553, in _wrapped_call_impl
return self._call_impl(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1562, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/torch/nn/modules/container.py", line 219, in forward
input = module(input)
^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1553, in _wrapped_call_impl
return self._call_impl(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/torch/nn/modules/module.py", line 1562, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane/qnn/torch.py", line 404, in forward
results = self._evaluate_qnode(inputs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane/qnn/torch.py", line 430, in _evaluate_qnode
res = self.qnode(**kwargs)
^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane/workflow/qnode.py", line 1020, in __call__
return self._impl_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane/workflow/qnode.py", line 1008, in _impl_call
res = self._execution_component(args, kwargs, override_shots=override_shots)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane/workflow/qnode.py", line 957, in _execution_component
res = qml.execute(
^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane/workflow/execution.py", line 771, in execute
results = ml_boundary_execute(tapes, execute_fn, jpc, device=device)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane/workflow/interfaces/torch.py", line 236, in execute
return ExecuteTapes.apply(kwargs, *parameters)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane/workflow/interfaces/torch.py", line 89, in new_apply
flat_out = orig_apply(out_struct_holder, *inp)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/torch/autograd/function.py", line 574, in apply
return super().apply(*args, **kwargs) # type: ignore[misc]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane/workflow/interfaces/torch.py", line 93, in new_forward
out = orig_fw(ctx, *inp)
^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane/workflow/interfaces/torch.py", line 158, in forward
res = tuple(kwargs["execute_fn"](ctx.tapes))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane/workflow/execution.py", line 212, in inner_execute
results = device.execute(transformed_tapes, execution_config=execution_config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane_qiskit/qiskit_device.py", line 66, in execute
results = tracked_execute(self, circuits, execution_config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane/devices/modifiers/simulator_tracking.py", line 30, in execute
results = untracked_execute(self, circuits, execution_config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane_qiskit/qiskit_device.py", line 590, in execute
with execute_circuits(session) as results:
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/contextlib.py", line 137, in __enter__
return next(self.gen)
^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane_qiskit/qiskit_device.py", line 585, in execute_circuits
results.append(execute_fn(circ, session))
^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/pennylane_qiskit/qiskit_device.py", line 656, in _execute_estimator
result = estimator.run(
^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/qiskit_ibm_runtime/estimator.py", line 191, in run
coerced_pubs = [EstimatorPub.coerce(pub, precision) for pub in pubs]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/qiskit/primitives/containers/estimator_pub.py", line 162, in coerce
return cls(
^^^^
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/qiskit/primitives/containers/estimator_pub.py", line 85, in __init__
self.validate()
File "$HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages/qiskit/primitives/containers/estimator_pub.py", line 188, in validate
raise ValueError(
ValueError: The number of qubits of the circuit (127) does not match the number of qubits of the (0,)-th observable (5).
Here is the qml.about()
information:
Name: PennyLane
Version: 0.38.0
Summary: PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
Home-page: https://github.com/PennyLaneAI/pennylane
Author:
Author-email:
License: Apache License 2.0
Location: $HOME/miniconda3/envs/qml_min/lib/python3.12/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, packaging, pennylane-lightning, requests, rustworkx, scipy, toml, typing-extensions
Required-by: PennyLane-qiskit, pennylane-qulacs, PennyLane_Lightning
Platform info: Linux-6.10.12-amd64-x86_64-with-glibc2.40
Python version: 3.12.4
Numpy version: 1.26.4
Scipy version: 1.14.1
Installed devices:
- qulacs.simulator (pennylane-qulacs-0.36.0.post0)
- default.clifford (PennyLane-0.38.0)
- default.gaussian (PennyLane-0.38.0)
- default.mixed (PennyLane-0.38.0)
- default.qubit (PennyLane-0.38.0)
- default.qubit.autograd (PennyLane-0.38.0)
- default.qubit.jax (PennyLane-0.38.0)
- default.qubit.legacy (PennyLane-0.38.0)
- default.qubit.tf (PennyLane-0.38.0)
- default.qubit.torch (PennyLane-0.38.0)
- default.qutrit (PennyLane-0.38.0)
- default.qutrit.mixed (PennyLane-0.38.0)
- default.tensor (PennyLane-0.38.0)
- null.qubit (PennyLane-0.38.0)
- lightning.qubit (PennyLane_Lightning-0.38.0)
- qiskit.aer (PennyLane-qiskit-0.38.1)
- qiskit.basicaer (PennyLane-qiskit-0.38.1)
- qiskit.basicsim (PennyLane-qiskit-0.38.1)
- qiskit.remote (PennyLane-qiskit-0.38.1)