Barren Plateaus#

Overview#

Barren plateaus are the greatest difficulties in the gradient-based optimization for a large family of random parameterized quantum circuits (PQC). The gradients vanish almost everywhere. In this example, we will show barren plateaus in quantum neural networks (QNNs).

Setup#

[1]:
import numpy as np
import tensorflow as tf
import tensorcircuit as tc

tc.set_backend("tensorflow")
tc.set_dtype("complex64")

Rx = tc.gates.rx
Ry = tc.gates.ry
Rz = tc.gates.rz

Parameters#

[2]:
n = 4  # The number of qubits
nlayers = 1  # The number of circuit layers
ncircuits = 3  # The number of circuits with different initial parameters
ntrials = 2  # The number of random circuits with different structures

Generating QNN#

[3]:
def op_expectation(params, seed, n, nlayers):
    paramsc = tc.backend.cast(params, dtype="float32")  # parameters of gates
    seedc = tc.backend.cast(seed, dtype="float32")  # parameters of circuit structure

    c = tc.Circuit(n)
    for i in range(n):
        c.ry(i, theta=np.pi / 4)
    for l in range(nlayers):
        for i in range(n):
            # choose one gate from Rx, Ry, and Rz gates with equal prob=1/3; status is the seed.
            c.unitary_kraus(
                [Rx(paramsc[i, l]), Ry(paramsc[i, l]), Rz(paramsc[i, l])],
                i,
                prob=[1 / 3, 1 / 3, 1 / 3],
                status=seedc[i, l],
            )
        for i in range(n - 1):
            c.cz(i, i + 1)

    return tc.backend.real(
        c.expectation((tc.gates.z(), [0]), (tc.gates.z(), [1]))
    )  # expectations of <Z_0Z_1>
[4]:
# use vmap and vvag to get the expectations of ZZ observable and gradients of different random circuit instances
op_expectation_vmap_vvag = tc.backend.jit(
    tc.backend.vmap(
        tc.backend.vvag(op_expectation, argnums=0, vectorized_argnums=0),
        vectorized_argnums=1,
    )
)

Batch Variance Computation#

[5]:
seed = tc.array_to_tensor(
    np.random.uniform(low=0.0, high=1.0, size=[ntrials, n, nlayers]), dtype="float32"
)
params = tc.array_to_tensor(
    np.random.uniform(low=0.0, high=2 * np.pi, size=[ncircuits, n, nlayers]),
    dtype="float32",
)

e, grad = op_expectation_vmap_vvag(
    params, seed, n, nlayers
)  # the expectations of ZZ observable and gradients of different random circuits

grad_var = tf.math.reduce_std(tf.math.reduce_std(grad, axis=0), axis=0)[
    0, 0
]  # the gradient variance of the first parameter
print("The variance of the gradients is:", grad_var.numpy())
The variance of the gradients is: 0.19805922

Results#

The gradient variances in QNNs (\(nlayers=50\), \(ntrials=20\), \(ncircuits=20\)). The landscape become exponentially barren with increasing qubit number.

barren.jpg