I am trying to implement the example in https://pennylane.ai/qml/demos/tutorial_data_reuploading_classifier.html with QNGOptimizer
because I learned that QNGOptimizer
is faster. Then I got the error, The QNG optimizer supports single QNodes or ExpvalCost
objects as objective functions. Alternatively, the metric tensor can directly be provided to the step()
method of the optimizer, using the metric_tensor_fn
argument.
By searching the doc and forum, I also learn that QNGOptimizer
cannot work with hybrid cost function.
The cost function in the tutorial is
def cost(params, x, y, state_labels=None):
"""Cost function to be minimized.
Args:
params (array[float]): array of parameters
x (array[float]): 2-d array of input vectors
y (array[float]): 1-d array of targets
state_labels (array[float]): array of state representations for labels
Returns:
float: loss value to be minimized
"""
# Compute prediction for each input in data batch
loss = 0.0
dm_labels = [density_matrix(s) for s in state_labels]
for i in range(len(x)):
f = qcircuit(params, x[i], dm_labels[y[i]])
loss = loss + (1 - f) ** 2
return loss / len(x)
In terms of this cost function, does it mean there are 2 Qnodes considering the two types of observable?
Also, could you shed light on combing data_reuploading_classifier
with QNGOptimizer
?
Thank you in advance.
Ban
One idea is that I should change the circuit from
@qml.qnode(dev, diff_method='adjoint')
def qcircuit(params, x, y):
"""A variational quantum circuit representing the Universal classifier.
Args:
params (array[float]): array of parameters
x (array[float]): single input vector
y (array[float]): single output state density matrix
Returns:
float: fidelity between output state and input
"""
for p in params:
qml.Rot(*x, wires=0)
qml.Rot(*p, wires=0)
return qml.expval(qml.Hermitian(y, wires=[0]))
to
@qml.qnode(dev, diff_method='adjoint')
def qcircuit(params, x, y):
"""A variational quantum circuit representing the Universal classifier.
Args:
params (array[float]): array of parameters
x (array[float]): single input vector
y (array[float]): single output state density matrix
Returns:
float: fidelity between output state and input
"""
for p in params:
qml.Rot(*x, wires=0)
qml.Rot(*p, wires=0)
return qml.expval(qml.PauliZ(wires=[0]))
And then redefine the cost function.
Do you think it is feasible?
Hi @Ban_Wong, welcome to the Forum!
It’s a strong claim to say that the QNG Optimizer will always be faster. This is probably not the case. However it’s interesting exploring whether or not it’s faster for this particular application.
In the case of the data reuploading classifier demo there’s a single qnode so this is not the source of the problem.
If you change the return to use a PauliZ instead of using the Hermitian of the density matrix y, you will notice that your code won’t train.
The real issue is that the return function of your qnode changes with each iteration because it’s tied to y. This is why the error message is that you have multiple qnodes.
If you go to the documentation for the QNG Optimizer you will find that the suggestion is to use qml.metric_tensor
(note that ExpvalCost is deprecated). However you may need to do a lot of workarounds to get this to work.
It probably won’t be an easy fix so maybe instead of using the QNG Optimizer you can keep using the Adam Optimizer.
I hope this will be helpful for you.