# QNGOptimizer with Variational Classifiers

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.