Diagnostics#
A barren plateau is a circuit whose gradients vanish as it widens, which leaves
the optimizer nothing to follow. check_barren_plateau() samples gradients
at uniformly random weights and compares their variance against a theoretical
floor, so you can find out before spending the compute rather than after.
Run it as a pre-flight check:
import pyqit
trainer = pyqit.Trainer(max_epochs=50, check_bp=True, bp_samples=200)
history = trainer.fit(model, dm)
Or call it directly when you want the BPResult without training:
from pyqit.utils.diagnostic import check_barren_plateau
result = check_barren_plateau(model, dm, num_samples=200)
BP Diagnostic Result : BARREN PLATEAU
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓
┃ Metric / Layer ┃ Value ┃ Status ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩
│ Qubits │ 4 │ │
│ Samples │ 200 │ │
│ Circuit Executions │ 200 │ │
│ Expected Variance │ 1.56e-02 │ Baseline │
│ Quantum Variance │ 3.74e-03 │ BARREN PLATEAU │
├─────────────────────────────┼──────────┼────────────────┤
│ Layer: main_circuit.weights │ 0.240x │ ← plateau │
└─────────────────────────────┴──────────┴────────────────┘
Reading the baseline#
The floor depends on how much of the circuit you measure. A local cost, meaning
fewer measured wires than qubits, uses 1 / 2 ** n_qubits. A global cost uses
1 / (3 * 4 ** (n_qubits - 1)), which shrinks much faster. Classifier models
scale the baseline further through their bp_scale_factor tag.
Only circuit weights are drawn at random. Classical weights, such as a
regressor’s output scale or the dense layers of a hybrid, are held at their
current values, so the reported variance is the circuit’s and not the product
of the circuit’s gradient with a random scale. Their own gradients are still
collected and reported as classical_variance. A jointly trained
QuantumPipeline is sampled the same way, with the
floor taken from its one trainable quantum stage.
Each sample costs one gradient, and what a gradient costs depends on the device.
Under backprop it is one circuit execution. Under parameter-shift, which
shot-based devices and hardware use, it is 1 + 2 * n_params. The result
counts the executions the device ran and reports them as n_executions, so
you know what bp_samples bought. The table renders through rich when it is
installed and falls back to ASCII when it is not.