I want to train the following circuit:
from qiskit.providers.aer.noise import NoiseModel
from qiskit import QuantumCircuit
from qiskit.test.mock import FakeLagos
import pennylane as qml
import pennylane.numpy as np
from sklearn.metrics import accuracy_score
backend = FakeLagos()
noise_model = NoiseModel.from_backend(backend)
def get_qc(state, params):
if type(params) != type(weights):
params = params._value
qc = QuantumCircuit(2)
qc.initialize(state, qc.qubits)
for l in range(3):
for i in range(2):
qc.u(*params[l][i], i)
qc.cx(0, 1)
return qc
dev = qml.device(
"qiskit.aer",
wires=2,
shots=1000,
noise_model=noise_model,
backend="aer_simulator_statevector",
seed_simulator=1,
seed_transpiler=1,
)
@qml.qnode(dev)
def circuit(state, params):
params = params.reshape([3, 2, 3])
qc = get_qc(state, params)
qml.from_qiskit(qc)
return qml.expval(qml.PauliZ(0))
weights = np.random.uniform(-np.pi, np.pi, [3, 2, 3], requires_grad=True)
def all_cost(parameters, x, y):
error = 0
for xi, yi in zip(x, y):
error = error + (yi - circuit(xi, parameters)) ** 2
return error / len(x)
def all_predict(x, parameters):
y = []
for xi in x:
y.append(np.sign(circuit(xi, parameters)))
return np.array(y)
initial_states_train = [[(0.2422281054276611 - 0.06185098981363071j), (-0.4195513856218597 - 0.10712905685563347j),
(-0.4195513856218597 - 0.10712905685563348j), (0.7266843162829835 - 0.1855529694408921j)],
[(0.4844562108553227 - 0.12370197962726152j), (0.48445621085532237 + 0.12370197962726144j),
(0.48445621085532237 + 0.12370197962726144j), (0.48445621085532237 - 0.12370197962726144j)]]
y_train = [-1, -1]
opt = qml.AdamOptimizer(0.1)
for i in range(10):
weights = opt.step(lambda params: all_cost(params, initial_states_train, y_train), weights.ravel())
weights = weights.reshape([3, 2, 3])
print("Scores after training:")
y_predict_train = all_predict(initial_states_train, weights)
print(
"Training Data:",
accuracy_score(y_pred=y_predict_train, y_true=y_train),
)
Here, I am building a circuit using Qiskit and importing it into the QNode using qml.from_qiskit
. The reason for not making the circuit directly in PennyLane is that I want to use qc.initialize
to initialize the system in a given state.
The above is a working example that you can copy and run.
If I run this, the model does not train and I get:
lib\site-packages\autograd\tracer.py:14: UserWarning: Output seems independent of input.
warnings.warn("Output seems independent of input.")
I can run the circuit and optimization directly in Qiskit, where it does work. So the issue seems to be with the PennyLane code.
if type(params) != type(weights):
params = params._value
These lines in the get_qc
function are required as without these I get an error:
raise CircuitError(f"Invalid param type {type(parameter)} for gate {self.name}.")
qiskit.circuit.exceptions.CircuitError: "Invalid param type <class 'autograd.numpy.numpy_boxes.ArrayBox'> for gate u."