Lesson 55 · 150 min · advanced
Capstone: Data Re-uploading Hybrid Classifier
The capstone puts the Stage 4 toolkit into one workflow: design, train and evaluate a two-qubit data re-uploading classifier for points inside or outside a circle. The lesson proves that uploads of give a Fourier series with frequencies in . It derives the mean-squared-error gradient through the exact parameter-shift rule and the cost of circuit evaluations per epoch, writes out Adam, and states the generalisation bound of Caro et al. (2022). It then measures how accuracy depends on depth and initialisation, and how the gradient variance behaves on two qubits.
Prerequisites: The Parameter-Shift Rule, Barren Plateaus, End-to-End Quantum-Kernel SVM
Objectives and key results
Define the two-qubit re-uploading classifier, show with the Heisenberg picture which weights and which uploads actually reach the observable , and compute its output for one layer.
Prove that re-uploads of give with , and verify the bound numerically with a 2-D discrete Fourier transform.
Derive the gradient of the mean squared error through the two-term parameter-shift rule for and weights, count circuit evaluations per epoch, and write the Adam update with bias correction.
State the generalisation bound of Caro et al., evaluate it for the lab, and compare it with the measured train/test gap for several depths and initialisations.
Derive the 2-design value of the gradient variance on two qubits, compare it with Monte-Carlo estimates for , and explain why this model has no barren plateau.
- formula · Spectrum of the re-uploading classifier
- formula · MSE gradient by the parameter-shift rule
- algorithm · Adam
- theorem · Generalisation (Caro et al. 2022)
- formula · Gradient variance under a 2-design
The capstone problem#
Stage 4 built a variational classifier piece by piece: a feature map followed by a trainable ansatz and a measured observable (VQC architecture), exact gradients from the parameter-shift rule, an understanding of when gradients vanish (barren plateaus), and the train/test protocol of the quantum-kernel pipeline. The capstone combines these on a task that a linear model cannot solve: classifying points of the unit square by whether they lie inside a circle. The model is the data re-uploading classifier of Pérez-Salinas et al. (2020), which feeds the same input into the circuit again in every layer.
Definition
Circle dataset
Draw points with coordinates from mulberry32(7), uniform on , and label them if and otherwise. The disc has area ; of the points lie inside. The first points ( inside) form the training set, the last ( inside) the held-out test set. This is circleDataset(7, 200) in lib/qml.
Definition
Two-qubit data re-uploading classifier
For a depth and weights , , , layer applies in time order The model output and prediction are with counted as wrong. There are weights and gates. This is dataReuploadingClassifier(L); the lab grades templates .
Circuit · 2 qubits
The classifier with the first held-out point (label ) encoded and the lab's trained weights (rounded to four decimals) bound to numbers. Here , so the probability of an even-parity outcome ( or ) is and the point is classified as inside.
- |00⟩0.2977
- |01⟩0.1885
- |10⟩0.1561
- |11⟩0.3577
Which weights reach the observable
(a) For every , does not depend on , , or on the last upload . (b) For , : the output does not depend on at all. (c) For , does not depend on either, so only of the weights are trainable in effect, and is uploaded effective times.
Proof (6 steps)
- Step 1:On the CNOT maps , so picks up the sign of the control, and is unchanged. The CNOT is its own inverse, so pulling the observable back through the last gate turns into .
- Step 2:The remaining gates of layer factorise into a qubit- part (the upload of , , ) and a qubit- part . removes the qubit- part, and the last gate on qubit , , commutes with . This proves (a).
- Step 3:With , , , and . The two qubit- rotations and combine to .
- Step 4:The observable seen by the state entering layer . For that state is , with and , hence . This proves (b): one layer can only cut the square into stripes parallel to the axis.
- Step 5:For , pull back through the CNOT of layer : on the target commutes with the CNOT. Both terms act on qubit as or .
- Step 6:The rotations , act on qubit only and change and but not the qubit- factors. The next gate back, , commutes with and , so it drops out. This proves (c); for the live weights number .
∎
The engine treats all weights alike, and the lab requires all of them, but the four dead ones have identically vanishing gradients. The TypeScript cell at the end finds exactly these four with the shift rule. The proposition explains the poor results below, about held-out accuracy: a stripe cannot capture a disc.
Re-uploading and the Fourier spectrum#
The angle-encoding lesson showed that a model with uploads of a single-qubit rotation is a trigonometric polynomial of degree (Schuld, Sweke & Meyer 2021). We now prove the two-feature version for our classifier, in the units of the encoding angle .
Fourier spectrum of the re-uploading classifier
For every and there are -independent coefficients with has elements, and is fixed by real numbers ( for ). By the proposition on dead weights, whenever .
Proof (8 steps)
- Step 1:The upload is generated by , whose eigenvalues are with the eigenvectors of .
- Step 2:Spectral decomposition on each qubit, and the tensor product of the two uploads.
- Step 3:Insert the decomposition for each of the uploads. The vectors do not depend on .
- Step 4:The bra carries the conjugate phases. Each difference lies in .
- Step 5:A sum of terms in . Collecting all terms with the same defines as a sum of the -independent matrix elements, which proves the expansion.
- Step 6:The exponentials are orthonormal on the period square , so the coefficients are unique.
- Step 7:is Hermitian, so is real. In particular is real, and the other coefficients come in conjugate pairs, so real numbers determine .
- Step 8:By part (a) of the proposition, deleting the last upload of does not change the output. Applied to the circuit , which uploads only times, the argument above gives frequencies . Since the coefficients are unique, whenever .
∎
Numerical check. A trigonometric polynomial with is reproduced exactly by its samples on an grid of when , because no two frequencies in range alias. For and the weights (order ), an discrete Fourier transform gives coefficients of size at most for every : the model has no frequency beyond . Only of the allowed coefficients are non-zero, at and . The restriction of is part (a) of the proposition. The even values of come from the two layers: at the output is a product of two factors of first degree in . For and random weights the count is , and , so at depth the classifier has active Fourier coefficients controlled by live weights. A disc is not a finite Fourier series, so deeper models approximate its boundary better, but each extra layer also adds weights to train.
The widget shows the one-qubit version from the angle-encoding lesson: five uploads and random trainable layers give a spectrum in . Lower the number of layers and the highest available frequency drops with it.
Quick check
How many frequency vectors does the theorem allow for the lab's reference depth , before taking the dead upload into account?
Loss, exact gradients and Adam#
The MSE gradient through the parameter-shift rule
- Step 1:The mean squared error on the training points. Its minimum would require exactly; in practice it pushes towards , i.e. points away from the decision boundary .
- Step 2:Chain rule. The loss is classical post-processing, so only needs the circuit.
- Step 3:Each weight occurs in exactly one gate, with coefficient . Split the circuit at that gate: is the state just before it, and is pulled back through all later gates (Heisenberg picture). Neither depends on .
- Step 4:Insert with , , then , , . This uses only , so it holds for and alike. Hence with constants .
- Step 5:and ; the constant cancels. The two-term rule is exact, not a finite-difference approximation, as proved for general Pauli rotations in the parameter-shift lesson.
- Step 6:One unshifted evaluation gives for the loss, and two shifted evaluations per weight give the gradient.
- Step 7:The cost of the lab's reference run. Skipping the four dead weights would give per epoch. On hardware each evaluation is itself an average over shots, so the gradient becomes a sum of noisy estimates.
Adam (Kingma & Ba 2015)
- Step 1:Full-batch gradient at step , computed with the shift rule.
- Step 2:Exponential moving averages of the gradient (first moment) and of its componentwise square (second moment).
- Step 3:Unroll the recursion from and take expectations under the assumption (geometric sum). The averages are biased towards for small .
- Step 4:Dividing by removes the bias, by the previous line and its analogue for .
- Step 5:Componentwise update with the lab's hyper-parameters. For a gradient of constant sign, , so each step moves a weight by about , whatever the size of the gradient. Rescaling by leaves the steps unchanged up to .
The workbench trains the classifier in your browser with exactly these formulas: initial weights from mulberry32(seed), the shift-rule gradient and Adam. Per epoch it shows the loss, the training and test accuracy, the gradient norm and the decision map over the unit square, with the true circle drawn on top.
Quick check
You choose the template and train on all points with your own two-term shift rule, differentiating every weight. How many circuit evaluations does one epoch cost?
Generalisation, depth and restarts#
Theorem (Caro, Huang, Cerezo, Sharma, Sornborger, Cincio and Coles, 2022; statement only). Let a quantum machine-learning model contain trainable local gates, and let it be trained on points drawn i.i.d. from a distribution , with a bounded loss . For the trained weights define the generalisation error , the expected loss minus the training loss . Then, with probability at least over the training set, where hides logarithmic factors. The bound depends on the number of trainable gates, not on the -dimensional Hilbert space.
For the lab, and give , and with the logarithm . The constants are not specified, so these numbers describe scaling, not a guarantee: four times more data halves the bound, twice as many gates raise it by . Measured with the – loss, the gaps between training and held-out accuracy of the runs below are , and , far below , as is typical for worst-case bounds.
Depth and initialisation. The table reports the engine's trainVQC with exactly the lab's recipe (MSE, Adam with , epochs, initial weights from mulberry32(seed), the first points for training, the last for testing). The , seed run is the lab's reference solution, weight for weight.
| weights | train accuracy (seeds 0 / 1 / 2) | held-out accuracy | final training MSE | |
|---|---|---|---|---|
| 1 | 4 | 0.68 / 0.69 / 0.71 | 0.58 / 0.58 / 0.59 | 0.9235 / 0.9231 / 0.9240 |
| 2 | 8 | 0.89 / 0.88 / 0.89 | 0.81 / 0.83 / 0.83 | 0.4005 / 0.3972 / 0.3971 |
| 3 | 12 | 0.85 / 0.92 / 0.93 | 0.77 / 0.80 / 0.85 | 0.4583 / 0.3555 / 0.4031 |
| 4 | 16 | 0.93 / 0.99 / 0.96 | 0.89 / 0.90 / 0.82 | 0.2979 / 0.2605 / 0.2671 |
| 5 | 20 | 0.98 / 1.00 / 0.98 | 0.90 / 0.96 / 0.91 | 0.2086 / 0.2168 / 0.2123 |
One layer gives a stripe classifier, as proved above. Two layers already reach –. Three layers are not reliably better than two: two of the three runs end below , in poorer local minima of a non-convex landscape. With , all three initialisations exceed , and the training accuracy reaches –. A practical recipe is to run several restarts and keep the run with the lowest final training loss. That selects seed for (held-out ), seed for () and seed for (). The lowest training loss does not always give the best test score (, seed reaches ), but choosing by the held-out score would turn the test set into training data and invalidate it as an estimate.
The second workbench trains for epochs from seed , the run of the table. Change the seed to see the spread between initialisations, then switch on the depth comparison below. It trains with the same settings and draws the final training and test accuracy per depth.
Quick check
You trained five restarts of your classifier. Which run should you submit?
Gradient variance: no barren plateau on two qubits#
The barren-plateau lesson showed that for random deep circuits the variance of a gradient component decays exponentially with the number of qubits. Our model has only two qubits. As a diagnostic we compute the variance, over random initialisations , of at the fixed point . This is the weight furthest from the readout. We first derive the value expected when the rest of the circuit is a unitary 2-design.
Variance of a first-layer gradient under a 2-design
- Step 1:, is the state just before the gate (after the two uploads), and is the rest of the circuit.
- Step 2:Differentiate: . is Hermitian and traceless.
- Step 3:For drawn from a unitary 1-design, . The gradient has mean zero.
- Step 4:The second-moment (Weingarten) formula for a 2-design. As a check, gives on both sides. Both operators here are traceless.
- Step 5:Expand the square. For a pure state, , and . The two uploads and keep qubit in the -plane of the Bloch sphere, so .
- Step 6:With . For qubits and a Pauli-string observable the same computation decays exponentially in ; this is the barren plateau. At it is a constant.
Measured. Sample variance over 5000 initialisations (mulberry32(55)), shift-rule derivative at :
| 1 | 2 | 3 | 4 | 5 | 6 | 8 | 12 | |
|---|---|---|---|---|---|---|---|---|
| variance | 0.0000 | 0.1251 | 0.1161 | 0.1131 | 0.1234 | 0.1260 | 0.1332 | 0.1291 |
The statistical standard error is about –. At the derivative vanishes identically: is a dead weight (part (a) of the proposition). From on, the variance stays between and , and at and it agrees with the 2-design value within two standard errors. Shallow circuits are not yet 2-designs, so their values differ by up to . Deeper circuits converge to , a constant set by the two-qubit dimension. Depth therefore costs no gradient signal here, and the trainability problems seen in the table are local minima, not a plateau. On qubits the same diagnostic would fall like , which is why the barren-plateau lesson recommends local costs and shallow, structured circuits.
Putting it together#
The TypeScript cell evaluates the lab's reference model (weights rounded to four decimals) on both data sets. It compares a hand-written two-term shift rule with the engine's vqcGradient and lists the weights with zero gradient. It finally prints the cost per epoch with and without them.
import { expectationValue } from '@/lib/quantum-simulator';
import { circleDataset, dataReuploadingClassifier, reuploadingSpectrum, vqcAccuracy, vqcGradient } from '@/lib/qml';
// The lab's reference model: L = 5 layers, weights rounded to 4 decimals.
const w: Record<string, number> = {
w_0_0_0: 2.968, w_0_0_1: -0.3193, w_0_1_0: 4.9431, w_0_1_1: 4.8684, w_1_0_0: 6.2012, w_1_0_1: 0.8796, w_1_1_0: 4.2054,
w_1_1_1: 5.906, w_2_0_0: 2.7566, w_2_0_1: 6.5819, w_2_1_0: 1.3577, w_2_1_1: 3.6023, w_3_0_0: 1.1035, w_3_0_1: 2.5368,
w_3_1_0: 2.8377, w_3_1_1: 1.3038, w_4_0_0: 3.0734, w_4_0_1: 0.4233, w_4_1_0: 1.973, w_4_1_1: 4.8199,
};
const model = dataReuploadingClassifier(5);
const { X, y } = circleDataset(7, 200);
const Xtr = X.slice(0, 100), ytr = y.slice(0, 100), Xte = X.slice(100), yte = y.slice(100);
console.log('gates ' + model.template.ops.length + ', weights P = ' + model.weightParams.length + ', frequencies per feature: ' + reuploadingSpectrum(5).join(' '));
console.log('train accuracy ' + vqcAccuracy(model, Xtr, ytr, w).toFixed(2) + ', held-out accuracy ' + vqcAccuracy(model, Xte, yte, w).toFixed(2));
// f and its gradient at the first held-out point: our own two-term shift rule against the engine.
const x = Xte[0];
const f = (weights: Record<string, number>) => expectationValue(model.template, model.observable, { x0: x[0], x1: x[1], ...weights });
const own: Record<string, number> = {};
for (const k of model.weightParams) own[k] = 0.5 * (f({ ...w, [k]: w[k] + Math.PI / 2 }) - f({ ...w, [k]: w[k] - Math.PI / 2 }));
const engine = vqcGradient(model, x, w);
const maxDiff = Math.max(...model.weightParams.map((k) => Math.abs(own[k] - engine[k])));
console.log('f(x) = ' + f(w).toFixed(10) + ' at x = (' + x[0].toFixed(4) + ', ' + x[1].toFixed(4) + '), label ' + yte[0]);
console.log('df/dw_2_1_0 = ' + own.w_2_1_0.toFixed(10) + ', max |own shift rule - engine| < 1e-12: ' + (maxDiff < 1e-12));
console.log('weights with zero gradient: ' + model.weightParams.filter((k) => Math.abs(own[k]) < 1e-12).join(', '));
const M = 100, P = model.weightParams.length;
console.log('evaluations per epoch M(2P + 1) = ' + M * (2 * P + 1) + ', without the 4 dead weights ' + M * (2 * (P - 4) + 1));Expected output
gates 35, weights P = 20, frequencies per feature: -5 -4 -3 -2 -1 0 1 2 3 4 5 train accuracy 1.00, held-out accuracy 0.96 f(x) = 0.3108423695 at x = (0.3174, 0.2596), label 1 df/dw_2_1_0 = 0.2058330341, max |own shift rule - engine| < 1e-12: true weights with zero gradient: w_3_0_1, w_4_0_0, w_4_0_1, w_4_1_1 evaluations per epoch M(2P + 1) = 4100, without the 4 dead weights 3300
The NumPy cell rebuilds the classifier from matrices and regenerates the data set with a port of mulberry32. It checks the shift rule against a central difference and the dead weights, and computes the Fourier coefficients of an model with np.fft.fft2.
import numpy as np
# The two-qubit data re-uploading classifier with 4 x 4 matrices (qubit 0 = most significant bit).
Z = np.diag([1.0, -1.0])
ZZ = np.kron(Z, Z)
CNOT = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]], dtype=complex)
def ry(t):
return np.array([[np.cos(t / 2), -np.sin(t / 2)], [np.sin(t / 2), np.cos(t / 2)]], dtype=complex)
def rz(t):
return np.diag([np.exp(-0.5j * t), np.exp(0.5j * t)])
def f(x, w): # w[l, q, 0] is the R_Y weight, w[l, q, 1] the R_Z weight of qubit q in layer l
psi = np.zeros(4, dtype=complex)
psi[0] = 1
for wl in w:
psi = np.kron(ry(np.pi * x[0]), ry(np.pi * x[1])) @ psi # upload x0 and x1
psi = np.kron(rz(wl[0, 1]) @ ry(wl[0, 0]), rz(wl[1, 1]) @ ry(wl[1, 0])) @ psi
psi = CNOT @ psi
return float(np.real(np.vdot(psi, ZZ @ psi)))
# Port of mulberry32 and circleDataset(7, 200): label +1 inside (x0 - 1/2)^2 + (x1 - 1/2)^2 < 0.15.
def mulberry32(seed):
a = seed & 0xFFFFFFFF
def imul(u, v):
return (u * v) & 0xFFFFFFFF
def r():
nonlocal a
a = (a + 0x6D2B79F5) & 0xFFFFFFFF
t = imul(a ^ (a >> 15), 1 | a)
t = ((t + imul(t ^ (t >> 7), 61 | t)) & 0xFFFFFFFF) ^ t
return (t ^ (t >> 14)) / 4294967296
return r
r = mulberry32(7)
X = np.array([[r(), r()] for _ in range(200)])
y = np.where((X[:, 0] - 0.5) ** 2 + (X[:, 1] - 0.5) ** 2 < 0.15, 1, -1)
# The lab's reference weights (L = 5), rounded to 4 decimals.
w5 = np.array([2.968, -0.3193, 4.9431, 4.8684, 6.2012, 0.8796, 4.2054, 5.906, 2.7566, 6.5819,
1.3577, 3.6023, 1.1035, 2.5368, 2.8377, 1.3038, 3.0734, 0.4233, 1.973, 4.8199]).reshape(5, 2, 2)
acc = lambda rows: np.mean([np.sign(f(X[m], w5)) == y[m] for m in rows])
x = X[100]
print(f"first held-out point {np.round(x, 4).tolist()} (label {y[100]:+d}): f = {f(x, w5):+.10f}")
print(f"train accuracy {acc(range(100)):.2f}, held-out accuracy {acc(range(100, 200)):.2f}")
def shifted(idx, s):
w = w5.copy()
w[idx] += s
return f(x, w)
psr = 0.5 * (shifted((2, 1, 0), np.pi / 2) - shifted((2, 1, 0), -np.pi / 2))
fd = (shifted((2, 1, 0), 1e-6) - shifted((2, 1, 0), -1e-6)) / 2e-6
print(f"df/dw_2_1_0: shift rule {psr:+.10f}, central difference {fd:+.6f}")
dead = [(3, 0, 1), (4, 0, 0), (4, 0, 1), (4, 1, 1)]
print("shifting w_3_0_1, w_4_0_0, w_4_0_1, w_4_1_1 by 1 leaves f unchanged:", max(abs(shifted(i, 1.0) - f(x, w5)) for i in dead) < 1e-12)
# Fourier coefficients of an L = 2 model: exact 2-D DFT on an 8 x 8 grid of the period square [0, 2)^2.
w2 = np.array([0.3, 1.1, -0.7, 2.0, 0.5, -1.4, 0.9, 0.2]).reshape(2, 2, 2)
N = 8
F = np.array([[f((2 * a / N, 2 * b / N), w2) for b in range(N)] for a in range(N)])
C = np.fft.fft2(F) / N**2 # C[p, q] = c_(p, q), frequency indices taken mod N
k = np.fft.fftfreq(N, 1 / N).astype(int)
outside = max(abs(C[i, j]) for i in range(N) for j in range(N) if max(abs(k[i]), abs(k[j])) > 2)
support = sorted((int(k[i]), int(k[j])) for i in range(N) for j in range(N) if abs(C[i, j]) > 1e-9)
print(f"L = 2: every |c_omega| with max(|omega_0|, |omega_1|) > 2 is below 1e-12: {outside < 1e-12}")
print(f"non-zero coefficients: {len(support)} at {support}")
print(f"c_(1,2) = {C[1, 2].real:+.6f}{C[1, 2].imag:+.6f}i, c_(-1,-2) = {C[-1, -2].real:+.6f}{C[-1, -2].imag:+.6f}i")Expected output
first held-out point [0.3174, 0.2596] (label +1): f = +0.3108423695 train accuracy 1.00, held-out accuracy 0.96 df/dw_2_1_0: shift rule +0.2058330341, central difference +0.205833 shifting w_3_0_1, w_4_0_0, w_4_0_1, w_4_1_1 by 1 leaves f unchanged: True L = 2: every |c_omega| with max(|omega_0|, |omega_1|) > 2 is below 1e-12: True non-zero coefficients: 9 at [(-1, -2), (-1, 0), (-1, 2), (0, -2), (0, 0), (0, 2), (1, -2), (1, 0), (1, 2)] c_(1,2) = +0.109698+0.059928i, c_(-1,-2) = +0.109698-0.059928i
The lab. You write trainCapstone: choose the depth , implement the shift rule and the optimiser, and return the weights. The grader classifies held-out points it never sends to the browser and requires an accuracy of at least . Per the table, with Adam passes from all three tested initialisations, while usually does not.
References
- A. Pérez-Salinas, A. Cervera-Lierta, E. Gil-Fuster and J. I. Latorre, Data re-uploading for a universal quantum classifier, Quantum 4, 226 (2020).doi:10.22331/q-2020-02-06-226
- M. Schuld, R. Sweke and J. J. Meyer, Effect of data encoding on the expressive power of variational quantum-machine-learning models, Physical Review A 103, 032430 (2021).doi:10.1103/PhysRevA.103.032430
- M. C. Caro, H.-Y. Huang, M. Cerezo, K. Sharma, A. Sornborger, L. Cincio and P. J. Coles, Generalization in quantum machine learning from few training data, Nature Communications 13, 4919 (2022).doi:10.1038/s41467-022-32550-3
- K. Mitarai, M. Negoro, M. Kitagawa and K. Fujii, Quantum circuit learning, Physical Review A 98, 032309 (2018).doi:10.1103/PhysRevA.98.032309
- D. P. Kingma and J. Ba, Adam: A method for stochastic optimization, 3rd International Conference on Learning Representations (ICLR 2015), arXiv:1412.6980.arxiv.org
- J. R. McClean, S. Boixo, V. N. Smelyanskiy, R. Babbush and H. Neven, Barren plateaus in quantum neural network training landscapes, Nature Communications 9, 4812 (2018).doi:10.1038/s41467-018-07090-4
Hands-on labs
Capstone: train a data re-uploading classifier on the circle
1 step · auto-gradedOpen labThe capstone of the course: train the two-qubit data re-uploading classifier of the lesson to tell points inside a circle from points outside it. Your TypeScript function receives labelled training points, chooses the depth , computes the gradient with your own parameter-shift rule, runs an optimiser of your choice and returns the trained weights. The grader binds them into the chosen circuit and classifies held-out points by ; at least must be correct.