qml.QNSPSAOptimizer¶
- class QNSPSAOptimizer(stepsize=0.001, regularization=0.001, finite_diff_step=0.01, resamplings=1, blocking=True, history_length=5, seed=None)[source]¶
Bases:
object
Quantum natural SPSA (QNSPSA) optimizer. QNSPSA is a second-order SPSA algorithm, which updates the ansatz parameters with the following equation:
x(t+1)=x(t)−ηˆg−1(x(t))^∇f(x(t)),where f(x) is the objective function with input parameters x, while ∇f is the gradient, g is the second-order Fubini-Study metric tensor. With QNSPSA algorithm, both the gradient and the metric tensor are estimated stochastically, with ^∇f and ˆg. This stochastic approach requires only a fixed number of circuit executions per optimization step, independent of the problem size. This preferred scaling makes it a promising candidate for the optimization tasks for high-dimensional ansatzes. On the other hand, the introduction of the Fubini-Study metric into the optimization helps to find better minima and allows for faster convergence.
The gradient is estimated similarly as the SPSA optimizer, with a pair of perturbations:
^∇f(x)=^∇f(x,h)≈12ϵ(f(x+ϵh)−f(x−ϵh)),where ϵ is the finite-difference step size specified by the user, and h is a randomly sampled direction vector to perform the perturbation.
The Fubini-Study metric tensor is estimated with another two pairs of perturbations along randomly sampled directions h1 and h2:
ˆg(x)=ˆg(x,h1,h2)≈δF8ϵ2(h1h2⊺where F(\mathbf{x}', \mathbf{x}) = \bigr\rvert\langle \phi(\mathbf{x}') | \phi(\mathbf{x}) \rangle \bigr\rvert ^ 2 measures the state overlap between \phi(\mathbf{x}') and \phi(\mathbf{x}), where \phi is the parametrized ansatz. The finite difference \delta F is computed from the two perturbations:
\delta F = F(\mathbf{x, \mathbf{x} + \epsilon \mathbf{h}_1} + \epsilon \mathbf{h}_2) - F (\mathbf{x, \mathbf{x} + \epsilon \mathbf{h}_1}) - F(\mathbf{x, \mathbf{x} - \epsilon \mathbf{h}_1} + \epsilon \mathbf{h}_2) + F(\mathbf{x, \mathbf{x} - \epsilon \mathbf{h}_1}).For more details, see:
Julien Gacon, Christa Zoufal, Giuseppe Carleo, and Stefan Woerner. “Simultaneous Perturbation Stochastic Approximation of the Quantum Fisher Information.” Quantum, 5, 567, 2021.
You can also find a walkthrough of the implementation in this tutorial.
Examples:
For VQE/VQE-like problems, the objective function can be defined within a qnode:
>>> num_qubits = 2 >>> dev = qml.device("default.qubit", wires=num_qubits) >>> @qml.qnode(dev) ... def cost(params): ... qml.RX(params[0], wires=0) ... qml.CRY(params[1], wires=[0, 1]) ... return qml.expval(qml.Z(0) @ qml.Z(1))
Once constructed, the qnode can be passed directly to the
step
orstep_and_cost
function of the optimizer.>>> from pennylane import numpy as np >>> params = np.random.rand(2) >>> opt = QNSPSAOptimizer(stepsize=5e-2) >>> for i in range(51): >>> params, loss = opt.step_and_cost(cost, params) >>> if i % 10 == 0: ... print(f"Step {i}: cost = {loss:.4f}") Step 0: cost = 0.9987 Step 10: cost = 0.9841 Step 20: cost = 0.8921 Step 30: cost = 0.0910 Step 40: cost = -0.9369 Step 50: cost = -0.9984
- Keyword Arguments
stepsize (float) – the user-defined hyperparameter \eta for learning rate (default: 1e-3)
regularization (float) – regularization term \beta to the Fubini-Study metric tensor for numerical stability (default: 1e-3)
finite_diff_step (float) – step size \epsilon to compute the finite difference gradient and the Fubini-Study metric tensor (default: 1e-2)
resamplings (int) – the number of samples to average for each parameter update (default: 1)
blocking (boolean) – when set to be True, the optimizer only accepts updates that lead to a loss value no larger than the loss value before update, plus a tolerance. The tolerance is set with the hyperparameter
history_length
. Theblocking
option is observed to help the optimizer to converge significantly faster (default: True)history_length (int) – when
blocking
is True, the tolerance is set to be the average of the cost values in the lasthistory_length
steps (default: 5)seed (int) – seed for the random sampling (default: None)
Methods
step
(cost, *args, **kwargs)Update trainable arguments with one step of the optimizer.
step_and_cost
(cost, *args, **kwargs)Update trainable parameters with one step of the optimizer and return the corresponding objective function value after the step.
- step(cost, *args, **kwargs)[source]¶
Update trainable arguments with one step of the optimizer.
Note
When blocking is set to be True,
step
callsstep_and_cost
on the backend, as loss measurements are required by the algorithm in this scenario.- Parameters
cost (QNode) – the QNode wrapper for the objective function for optimization
args – variable length argument list for qnode
kwargs – variable length of keyword arguments for the qnode
- Returns
the new variable values after step-wise update x^{(t+1)}
- Return type
pnp.ndarray
- step_and_cost(cost, *args, **kwargs)[source]¶
Update trainable parameters with one step of the optimizer and return the corresponding objective function value after the step.
- Parameters
cost (QNode) – the QNode wrapper for the objective function for optimization
args – variable length argument list for qnode
kwargs – variable length of keyword arguments for the qnode
- Returns
the new variable values x^{(t+1)} and the objective function output prior to the step
- Return type
(np.array, float)