I am having trouble reading the optimiser documentation. I am trying to understand what the individual outputs of the step_and_cost and step functions are, however the documentation is not as easy to understand as I would like it to be. So here please ask what are the individual outputs of the step_and_cost and step functions and what data types. Also is it possible to read the gradient of each step, I failed to read the gradient of pennylane.
Hey @RX1! Thanks for the feedback
Let’s look at an example. I’ve taken some of this code from our qubit rotation demo. I’ll define the usual things first (a differentiable function that relies on the output of a quantum circuit):
import pennylane as qml
from pennylane import numpy as np
dev1 = qml.device("lightning.qubit", wires=1)
@qml.qnode(dev1)
def circuit(params):
qml.RX(params[0], wires=0)
qml.RY(params[1], wires=0)
return qml.expval(qml.PauliZ(0))
def cost(x):
return circuit(x)
init_params = np.array([0.011, 0.012], requires_grad=True)
print(cost(init_params))
0.9998675058299389
According to the documentation, opt.step
will just give you the parameters back as an output:
params = init_params
opt = qml.GradientDescentOptimizer(stepsize=0.4)
for _ in range(3):
params = opt.step(cost, params)
print(params)
[0.01539959 0.01679959]
[0.02155832 0.02351832]
[0.03017859 0.03292259]
opt.step_and_cost
behaves somewhat similarly to opt.step
, but outputs the cost function’s value before the parameters were updated.
params = init_params
opt = qml.GradientDescentOptimizer(stepsize=0.4)
for _ in range(3):
params, cost_val = opt.step_and_cost(cost, params)
print(params, cost_val)
[0.01539959 0.01679959] 0.9998675058299389
[0.02155832 0.02351832] 0.9997403354524409
[0.03017859 0.03292259] 0.9994911497625389
If you had multiple individual parameters in your circuit like the example below, then your output would correspond as follows
@qml.qnode(dev1)
def circuit(param1, param2):
qml.RX(param1, wires=0)
qml.RY(param2, wires=0)
return qml.expval(qml.PauliZ(0))
def cost(x1, x2):
return circuit(x1, x2)
init_x1, init_x2 = np.array([0.011], requires_grad=True), np.array([0.012], requires_grad=True)
print(cost(init_x1, init_x2))
0.9998675058299389
x1, x2 = init_x1, init_x2
opt = qml.GradientDescentOptimizer(stepsize=0.4)
for _ in range(3):
x1, x2 = opt.step(cost, x1, x2)
print(x1, x2)
[0.01539959] [0.01679959]
[0.02155832] [0.02351832]
[0.03017859] [0.03292259]
and with opt.step_and_cost
, you just need to make sure that your parameters are inside of a tuple — the output of step_and_cost
is still two things: your parameters and the cost function’s value before the parameters were updated.
x1, x2 = init_x1, init_x2
opt = qml.GradientDescentOptimizer(stepsize=0.4)
for _ in range(3):
(x1, x2), cost_val = opt.step_and_cost(cost, x1, x2)
print(x1, x2, cost_val)
[0.01539959] [0.01679959] 0.9998675058299389
[0.02155832] [0.02351832] 0.9997403354524409
[0.03017859] [0.03292259] 0.9994911497625389
Also is it possible to read the gradient of each step, I failed to read the gradient of pennylane.
It sure is! I encourage you to check out this section of the qubit rotation demo.
Hope this helps!