Lesson 53 · 120 min · advanced
Quantum Convolutional Neural Networks
A quantum convolutional neural network (QCNN) processes an -qubit state the way a convolutional network processes an image. Convolution layers apply one shared two-qubit unitary to all neighbouring pairs. Pooling layers measure half of the qubits and rotate their neighbours conditioned on the outcomes. This halves the number of qubits, and after levels a single qubit is read out. The lesson proves, with the deferred-measurement principle and an explicit partial trace, that measurement-based pooling equals a controlled rotation followed by discarding the control. It then counts the shared parameters, relates the architecture to the MERA tensor network read in reverse and to renormalisation, and explains with a light-cone argument why QCNNs avoid barren plateaus (Pesah et al. 2021). Finally it writes the lab's four-qubit QCNN out gate by gate and derives its parameter-shift gradients.
Prerequisites: Strongly Entangling Layers, The Parameter-Shift Rule, Partial Trace & Reduced States
Objectives and key results
Build a QCNN from translation-invariant convolution layers, measurement-based pooling layers and a final readout, and state the symmetry of a brick-wall layer with shared weights.
Prove that measuring a qubit and applying a conditioned rotation to its neighbour gives the same reduced state as a controlled rotation followed by the partial trace over the control.
Derive the shared-weight parameter count and compare it with the parameters of the same network without weight sharing.
Explain the QCNN as a MERA read in reverse, i.e. a sequence of coarse-graining channels, and state the trainability result with its light-cone intuition.
Write the lab's 4-qubit QCNN gate by gate, compute its output for zero weights, and derive which parameter-shift rules give exact gradients for its shared and controlled weights.
- theorem · Pooling by deferred measurement
- formula · Parameter count
- identity · Zero-weight output of the lab QCNN
- theorem · Absence of barren plateaus (Pesah et al. 2021)
- formula · Shift rules for pooling weights
From convolutional networks to QCNNs#
A classical convolutional network rests on three ideas: locality (a filter sees a few neighbouring pixels), weight sharing (the same filter at every position) and pooling (neighbouring outputs are merged, so each layer works at a coarser scale). Cong, Choi and Lukin (2019) carried these ideas to circuits acting on an -qubit input state, such as an encoded image or the ground state of a spin chain. The resulting quantum convolutional neural network has depth and parameter count , and its gradients do not vanish exponentially.
Definition
Quantum convolutional neural network
Let qubits carry an input state , and let level act on an ordered list of active qubits , starting with all qubits. Each level consists of (i) a convolution layer: one two-qubit unitary on the even pairs , then on the odd pairs (a single pair when ); (ii) a pooling layer: each is measured, its neighbour is rotated by on outcome , and is discarded. After level one qubit is left; the output is and the predicted class . Cong et al. also insert a fully connected layer, a general unitary on the last few qubits; in the lab's model the final convolution on both remaining qubits plays this role.
The diagram shows the lab's model. Gates with the same colour share weights: the four first-layer convolution blocks use , the two first-layer pooling blocks . Pooled qubits are greyed out, and the Bloch vectors show the reduced states of the active qubits. Weight sharing is a symmetry statement:
A shared brick-wall layer commutes with translation by two sites
- Step 1:is the cyclic shift by two sites on the ring of active qubits (indices mod ), a permutation unitary. Conjugating a two-qubit gate on by a permutation moves it to the permuted qubits.
- Step 2:The even and odd sublayers of one convolution layer, all with the same . Inside a sublayer the pairs are disjoint, so the factors commute and their order is irrelevant.
- Step 3:Shifting by two maps the set of even pairs onto itself and the set of odd pairs onto itself (indices mod ). Because the weights are shared, every shifted factor is again a factor of the same product.
- Step 4:Insert between the two sublayers. The whole convolution layer commutes with , and so does a pooling layer on the pairs , by the same argument.
- Step 5:A one-site shift exchanges the sublayers: the layer is translation invariant with a two-site unit cell, like a convolution with stride .
Result
Pooling: measurement, conditioned rotation, partial trace#
Pooling measures a qubit and uses the outcome to rotate a neighbour . Hardware with mid-circuit measurement and feed-forward can do this literally; a simulator can instead apply a controlled rotation and never look at again. The deferred-measurement principle from the teleportation lesson says the two agree. We need the precise statement for an arbitrary entangled, mixed input with discarded afterwards; the tools are the block decomposition of a density matrix and the partial trace.
Measurement-based pooling equals a controlled rotation followed by the partial trace
Let be a density operator on qubits and (and possibly further qubits , on which everything below acts as the identity), and let be unitaries on . Write for the blocks. Procedure M: measure in the computational basis, apply to on outcome , discard , and forget . Procedure D: apply and trace out . Both procedures produce the state and measuring after reproduces the outcome probabilities and the conditional states of procedure M. The lab's pooling uses and .
Proof (10 steps)
- Step 1:Insert on both sides of on qubit . With the more significant qubit, this is the matrix cut into blocks; hermiticity of gives .
- Step 2:A controlled operation with the two branch unitaries and is block diagonal in the control basis.
- Step 3:Block matrix multiplication: the block of is .
- Step 4:Definition of the partial trace over from the partial-trace lesson: the sum of the diagonal blocks.
- Step 5:Apply the previous line to the matrix of line three. The coherences between the two control values sit in off-diagonal blocks and drop out.
- Step 6:Born rule and Lüders update for the projective measurement of : selects the block.
- Step 7:Procedure M on outcome : rotate by , then discard . The trace of is .
- Step 8:Forgetting the outcome averages the conditional states with their probabilities (outcomes with contribute ). The result is the state of line five.
- Step 9:Measuring after gives the same probabilities, because is unitary, and the same conditional states. This is the deferred-measurement principle: the measurement commutes with gates that use only as a control.
- Step 10:With further qubits the blocks act on and every step holds verbatim, as needed inside a QCNN.
∎
The lab pooling block as a controlled pair of rotations
- Step 1:The time-ordered gates , , , written as one matrix product, last gate leftmost.
- Step 2:and : sandwiching between two gates makes the rotation fire on control value .
- Step 3:Multiply out; the cross terms contain .
- Step 4:The explicit matrix in the basis , using and .
- Step 5:The form of the theorem: once is ignored, the gates implement "measure ; if apply to , if apply ".
Pooling as a channel and its Heisenberg dual
- Step 1:Rewrite the pooled state of the theorem with the operators , .
- Step 2:Completeness of the Kraus operators: is trace preserving, and a map of Kraus form is completely positive. Pooling is a quantum channel from two qubits to one.
- Step 3:Cyclicity of the trace defines the dual (Heisenberg-picture) map, which pulls an observable on back to an observable on .
- Step 4:With : , using and . commutes with .
- Step 5:Insert and . The angle has dropped out.
- Step 6:In the lab, the last pooling is followed directly by the measurement of , so the output does not depend on at all. Only of the weights matter. A rotation conditioned on the control is invisible to a measurement.
Quick check
Before a pooling block the pair is in the Bell state (order ). With , what is after pooling?
After the first pooling layer, qubits and are greyed out: by the theorem they may simply be traced out. The Bloch vectors of qubits and are the reduced states , generally mixed (shorter than ) because the pooled qubits were entangled with them.
Logarithmically many parameters#
Parameter count with and without weight sharing
Let . In a QCNN whose convolution block has parameters and whose pooling block has , sharing one convolution block and one pooling block per level gives parameters, e.g. (the lab), , . Giving every block its own parameters gives , e.g. and . In both cases the circuit has gates and depth at most .
Proof (6 steps)
- Step 1:Each pooling layer discards one qubit of every pair, so the number of active qubits halves. Level starts with two qubits and ends with one.
- Step 2:With sharing, each level contributes one convolution block ( weights) and one pooling block ( weights), however many qubits it acts on.
- Step 3:Without sharing, the ring of qubits has even and odd pairs, each with its own weights, and pooling pairs with weights each. The last level has one pair of each kind.
- Step 4:Geometric sum with ratio and terms; .
- Step 5:Add the two contributions. For : ; for : .
- Step 6:The block count is the same geometric sum. One encoding layer, two convolution sublayers of depth (, CNOT, , CNOT) and a pooling layer of depth per level bound the depth; for the gate count is .
∎
Sharing builds translation invariance into the model and reduces the number of training examples it needs. The eight-qubit structure has three levels with eight, four and one convolution blocks, but only distinct weights.
Quick check
How many trainable parameters does the shared-weight QCNN of this lesson have on qubits?
QCNNs as MERA read in reverse#
The multiscale entanglement renormalisation ansatz (MERA, Vidal 2008) is a tensor network for ground states of critical spin chains. Read from the top, it is a circuit that repeatedly doubles the number of qubits with isometries (a fresh qubit in entangled with an existing one) and disentanglers (two-qubit unitaries on neighbouring pairs). A QCNN has the shape of a MERA read from the bottom.
From MERA to coarse-graining channels
- Step 1:One MERA layer maps a state on sites to a state on sites. Each isometry is a unitary acting on an ancilla in and an existing qubit, and is a brick-wall layer of disentanglers.
- Step 2:is unitary and . Read in reverse, a layer first applies the unitaries on neighbouring pairs, which is a convolution layer, and then on each pair. For states in the MERA's image the ancilla returns exactly to .
- Step 3:For a general input the ancillas are not exactly . Discarding them is a partial trace, so each reversed layer is a channel from to qubits: a convolution followed by pooling. QCNN pooling is more general than plain discarding, because the conditioned rotation lets the discarded qubit correct its neighbour, the error-correction step of Cong et al.
- Step 4:Coarse-grained states on qubits; in the Heisenberg picture the readout is pulled back through the dual maps to an -qubit observable measured on the input.
- Step 5:If, in addition, the same weights are used at every level, the network iterates one coarse-graining map: a discrete renormalisation-group (RG) flow. States in the same phase flow to the same fixed point, so a readout that distinguishes fixed points classifies phases. The lab's model uses different weights at its two levels, so it is a general multiscale network rather than a scale-invariant one.
Trainability: no barren plateaus#
Deep random circuits have exponentially vanishing gradients, (barren-plateau lesson). A QCNN has a local cost (one measured qubit) and logarithmic depth, and Pesah et al. (2021) proved that this suffices.
Theorem (Pesah, Cerezo, Wang, Volkoff, Sornborger and Coles, 2021). Consider a QCNN on qubits whose convolution and pooling blocks are drawn independently from distributions that form local unitary -designs, and a cost that is linear in the output states , with a Hermitian operator on the output qubit. Then for every trainable parameter , and
Their proof, a graph-based recursion over the random blocks, is not reproduced here. We prove the geometric fact behind it: the influence of any gate reaches the readout through a narrow cone only levels long.
Light cones in a QCNN
Let and let be any block of the QCNN of the definition. Define its forward light cone as the smallest set of qubits that contains the qubits of and also contains all qubits of every later block that touches the set. Then (a) at the start of every later level, the cone contains at most active qubits, which form a contiguous arc of the ring; (b) the cone contains at most blocks of each level, hence at most blocks in total; (c) is separated from the readout by at most levels, i.e. by circuit depth at most .
Proof (6 steps)
- Step 1:Track the cone at the start of a level as an arc of consecutive positions in the list of active qubits; the cone of a single block starts as an arc of length .
- Step 2:The pairs of one sublayer are disjoint pairs of adjacent positions, so the pairs that touch an arc extend it by at most one position at each end. Two sublayers extend it by at most two at each end.
- Step 3:A pooling pair that touches the arc adds at most one position at each end. A position added on the left is even and is discarded, so only the right end can gain a survivor, and the survivors lie in an arc of length . Only odd positions survive, an arc of length contains at most of them, and they are consecutive in the next level's list.
- Step 4:Induction over levels. The level that contains itself leaves at most survivors, since at most one further sublayer follows . Every later level maps to . This proves (a).
- Step 5:Disjoint adjacent pairs meeting an arc of length number at most . The arc has length , and when the even sublayer, the odd sublayer and the pooling layer act, giving at most , and blocks per level. This proves (b).
- Step 6:Every level has depth at most (the bound of the parameter-count proposition), and the readout follows level . This proves (c).
∎
Why logarithmic depth gives polynomial variance
- Step 1:Assumption (intuition, not a proof): for a local cost, each of the layers of -design blocks between and the readout reduces the variance by at most a constant factor ; Cerezo et al. (2021) prove bounds of this type for local costs in layered circuits.
- Step 2:Part (c) of the light-cone lemma. In a QCNN every parameter is close to the output, because pooling halves the register at every level.
- Step 3:Exponential decay in a depth that is logarithmic in is polynomial decay in ; this is the identity .
- Step 4:The heuristic reproduces the scaling of the theorem. A deep hardware-efficient ansatz with depth would instead give , an exponential plateau.
- Step 5:Locality matters too: a global observable has a plateau at any depth, while the QCNN measures one qubit through a narrow light cone (part (a)).
Quick check
Which pair of properties does the light-cone argument for QCNN trainability rely on?
The lab model, gate by gate#
The 4-qubit QCNN of lab-qcnn-bars
- Step 1:Angle encoding of the four pixels (data parameters
x0tox3). An off pixel () gives and an on pixel () gives . - Step 2:The convolution block as a matrix product. In time order it is , , , , , : six gates with four weights.
- Step 3:Layer 1 on the ring pairs in the time order , all with the shared weights : the even sublayer, then the odd one.
- Step 4:Pooling layer 1 with the shared weights , each block made of the four gates , , , . Qubits and are not used again, so by the deferred-measurement theorem they are measured and discarded.
- Step 5:Level 2 on the active qubits . The single convolution acts on all remaining qubits, which makes it the fully connected layer.
- Step 6:The output (Pauli word
IIIZ), exactly what the lab's grader evaluates. - Step 7:Gate count and the number of gates in which each weight occurs; these numbers determine the cost of the gradient below.
Circuit · 4 qubits
The lab QCNN with the horizontal-bar image encoded and the trained weights (rounded to four decimals) bound to numbers. The probability of measuring qubit in is , so the image is classified as horizontal ().
- |0000⟩0.0001
- |0001⟩0.0045
- |0010⟩0.0001
- |0011⟩0.0006
- |0100⟩0.013
- |0101⟩0.014
- |0110⟩0.0001
- |0111⟩0.0001
- |1000⟩0.0677
- |1001⟩0.0023
- |1010⟩0.022
- |1011⟩0.003
- |1100⟩0.8657
- |1101⟩0.0009
- |1110⟩0.0057
- |1111⟩0.0002
With all weights zero the network computes cos(pi x1) cos(pi x3)
- Step 1:All rotations become identities; only the CNOT pairs of the convolution blocks remain.
- Step 2:Heisenberg rule for a CNOT, which is its own inverse: on the gate maps the target to , so picks up the sign of the control.
- Step 3:Pull back through , last gate first.
- Step 4:Through : maps ; then maps and fixes , and .
- Step 5:Through : , then and .
- Step 6:Through : , then and .
- Step 7:Through , the first block in time: , then and .
- Step 8:The encoded state is a product state, so the expectation value factorises into .
- Step 9:The pixel ranges of the bars dataset.
- Step 10:In a horizontal bar exactly one of the pixels is on, so the product is negative. In a vertical bar both or neither are on, so it is positive. Its magnitude is at least . Zero weights therefore classify every image with the wrong sign (accuracy ), and training must essentially flip this sign.
Shift rules for the pooling weights
Let be the angle of one pooling gate , , of the lab QCNN. (a) Its generator has the spectrum , so for a general circuit contains the frequencies and , and the four-term rule , , is exact. The engine applies this rule to every controlled rotation. (b) In the QCNN the gate-isolated observable commutes with , since is afterwards used only as a control; the frequency- part vanishes and the two-term rule is exact as well. (c) Summing over the occurrences of each shared weight, one full gradient costs shifted evaluations with the four-term rule for the pooling gates and with the two-term rule.
Proof (7 steps)
- Step 1:The generator is block diagonal. The control- block contributes the eigenvalue twice, and the control- block contributes the eigenvalues of .
- Step 2:The spectrum theorem for controlled rotations from the parameter-shift lesson: the frequencies are the eigenvalue differences , with and .
- Step 3:Exactness on both frequencies, for and , gives this system (derived in the parameter-shift lesson). This proves (a).
- Step 4:After , the only later gates on are , and the remaining gates and form an observable that does not act on . After only touches . In both cases commutes with .
- Step 5:lies in the control- block and in the control- block. Moving the projector through produces the product of orthogonal projectors. In the same way .
- Step 6:Only the frequency with survives. The general shift rule with then gives the two-term rule exactly, which proves (b). This is the gradient counterpart of the deferred-measurement theorem: coherences between the two control values never reach the output. The rule fails as soon as is used again, for example by followed by , as the TypeScript cell shows.
- Step 7:Chain rule for shared weights. In the first count, the occurrences of cost evaluations each; the pooling occurrences of cost each; cost each; and cost each. The second count uses evaluations per pooling occurrence. This proves (c).
∎
Quick check
The engine computes of the lab QCNN for one image, using the two-term rule for gates and the four-term rule for controlled rotations, plus one unshifted evaluation for the value . How many circuit evaluations does one call make in total?
The TypeScript cell evaluates the trained model, prints the engine gradient (, as the dual channel predicts) and applies the four-term and two-term rules by hand to the pooling weights. They agree, as part (b) predicts, until the pooled qubit is used again.
import { FOUR_TERM_C_MINUS, FOUR_TERM_C_PLUS, expectationValue, parameterShiftGradient } from '@/lib/quantum-simulator';
import { barsDataset, qcnnParameterCount, qcnnPredict, qcnnTemplate } from '@/lib/qml';
// Trained weights of the lab's reference solution, rounded to 4 decimals.
const p: Record<string, number> = {
p0: 0.0778, p1: 6.1613, p2: 1.7979, p3: 4.7243, p4: 3.7777, p5: 3.14,
p6: -0.1153, p7: 3.9739, p8: 0.0467, p9: 3.5536, p10: 4.3858, p11: 3.4631,
};
const names = Object.keys(p);
const template = qcnnTemplate();
const Z3 = [{ coeff: 1, ops: 'IIIZ' }];
const horizontal = [0.9, 0.95, 0.1, 0.05];
const vertical = [0.9, 0.1, 0.95, 0.05];
console.log('<Z3> horizontal ' + qcnnPredict(p, horizontal).toFixed(10) + ', vertical ' + qcnnPredict(p, vertical).toFixed(10));
console.log('gates ' + template.ops.length + ', shared weights P(4) = ' + qcnnParameterCount(4) + ', P(8) = ' + qcnnParameterCount(8) + ', P(16) = ' + qcnnParameterCount(16));
// Exact gradient from the engine: two-term rule for the RY weights, four-term rule for the CRZ/CRX weights.
const bindings: Record<string, number> = { x0: 0.9, x1: 0.95, x2: 0.1, x3: 0.05, ...p };
const g = parameterShiftGradient(template, Z3, { bindings, params: names });
console.log('evaluations ' + g.evaluations + ' (1 unshifted + 64 shifted)');
console.log('gradient ' + names.map((n) => n + ' ' + g.gradient[n].toFixed(6)).join(', '));
// By hand: shift one gate occurrence of weight w at a time and sum over the occurrences (chain rule).
function rules(circuit: any, w: string): string {
const value = (gate: number, s: number) => {
const c = { ...circuit, ops: circuit.ops.map((op: any, k: number) => (k === gate ? { ...op, params: [{ ...op.params[0], offset: s }] } : op)) };
return expectationValue(c, Z3, bindings);
};
const diff = (gate: number, s: number) => value(gate, s) - value(gate, -s);
const gates: number[] = circuit.ops.flatMap((op: any, k: number) => (op.params?.[0]?.param === w ? [k] : []));
const four = gates.reduce((sum, k) => sum + FOUR_TERM_C_PLUS * diff(k, Math.PI / 2) - FOUR_TERM_C_MINUS * diff(k, 1.5 * Math.PI), 0);
const two = gates.reduce((sum, k) => sum + 0.5 * diff(k, Math.PI / 2), 0);
return w + ' (gates ' + gates.join(', ') + '): four-term ' + four.toFixed(6) + ', two-term ' + two.toFixed(6);
}
for (const w of ['p4', 'p5', 'p11']) console.log('QCNN ' + rules(template, w));
// The same weight when the pooled qubit 0 is used again afterwards: H(0), CNOT(0, 3) appended.
const reused = { ...template, ops: [...template.ops, { kind: 'gate', gate: 'H', targets: [0] }, { kind: 'gate', gate: 'CNOT', targets: [0, 3] }] };
console.log('reused ctrl ' + rules(reused, 'p4'));
const test = barsDataset(12, 100);
const correct = test.X.filter((x, m) => Math.sign(qcnnPredict(p, x)) === test.y[m]).length;
console.log('held-out accuracy ' + (correct / test.X.length).toFixed(2));Expected output
<Z3> horizontal 0.9487576298, vertical -0.9026268265 gates 46, shared weights P(4) = 12, P(8) = 18, P(16) = 24 evaluations 65 (1 unshifted + 64 shifted) gradient p0 0.298714, p1 0.234418, p2 0.071498, p3 -0.034939, p4 -0.005194, p5 -0.004013, p6 0.014123, p7 -0.013223, p8 0.012624, p9 0.015969, p10 0.000000, p11 -0.036193 QCNN p4 (gates 28, 32): four-term -0.005194, two-term -0.005194 QCNN p5 (gates 30, 34): four-term -0.004013, two-term -0.004013 QCNN p11 (gates 44): four-term -0.036193, two-term -0.036193 reused ctrl p4 (gates 28, 32): four-term -0.040768, two-term -0.058111 held-out accuracy 1.00
The NumPy cell rebuilds the network from explicit matrices, reproduces to ten digits, confirms , checks the pooling theorem on a random mixed state and regenerates the held-out images with a port of mulberry32.
import numpy as np
# The lab's 4-qubit QCNN with dense 16 x 16 matrices (qubit 0 = most significant bit).
I2 = np.eye(2, dtype=complex)
X = np.array([[0, 1], [1, 0]], dtype=complex)
Z = np.diag([1.0 + 0j, -1.0])
P0, P1 = np.diag([1.0 + 0j, 0.0]), np.diag([0.0 + 0j, 1.0])
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 rx(t):
return np.array([[np.cos(t / 2), -1j * np.sin(t / 2)], [-1j * np.sin(t / 2), np.cos(t / 2)]])
def rz(t):
return np.diag([np.exp(-0.5j * t), np.exp(0.5j * t)])
def on(U, q, n=4): # U on qubit q, identity on the others
out = np.eye(1, dtype=complex)
for k in range(n):
out = np.kron(out, U if k == q else I2)
return out
def ctrl(c, t, U, n=4): # |0><0|_c (x) I + |1><1|_c (x) U_t
return on(P0, c, n) + on(P1, c, n) @ on(U, t, n)
def conv(i, j, a): # C_ij(a0, a1, a2, a3), gates in time order
return [on(ry(a[0]), i), on(ry(a[1]), j), ctrl(i, j, X), on(ry(a[2]), i), on(ry(a[3]), j), ctrl(j, i, X)]
def pool(c, t, b): # P_{c->t}(b0, b1) = CRZ(c,t,b0) X(c) CRX(c,t,b1) X(c)
return [ctrl(c, t, rz(b[0])), on(X, c), ctrl(c, t, rx(b[1])), on(X, c)]
def qcnn(x, p):
gates = [on(ry(np.pi * x[q]), q) for q in range(4)]
for i, j in [(0, 1), (2, 3), (1, 2), (3, 0)]:
gates += conv(i, j, p[0:4])
gates += pool(0, 1, p[4:6]) + pool(2, 3, p[4:6]) + conv(1, 3, p[6:10]) + pool(1, 3, p[10:12])
psi = np.zeros(16, dtype=complex)
psi[0] = 1
for G in gates:
psi = G @ psi
return np.real(np.vdot(psi, on(Z, 3) @ psi))
p = np.array([0.0778, 6.1613, 1.7979, 4.7243, 3.7777, 3.14, -0.1153, 3.9739, 0.0467, 3.5536, 4.3858, 3.4631])
for name, x in (("horizontal [0.9, 0.95, 0.1, 0.05]", [0.9, 0.95, 0.1, 0.05]), ("vertical [0.9, 0.1, 0.95, 0.05]", [0.9, 0.1, 0.95, 0.05])):
f = qcnn(x, p)
print(f"{name}: <Z3> = {f:+.10f}, prediction {int(np.sign(f)):+d}")
# All weights zero: <Z3> = cos(pi x1) cos(pi x3).
x = [0.9, 0.95, 0.1, 0.05]
print(f"zero weights: <Z3> = {qcnn(x, np.zeros(12)):+.10f}, cos(pi x1) cos(pi x3) = {np.cos(np.pi * x[1]) * np.cos(np.pi * x[3]):+.10f}")
# Pooling = measure c, rotate t by V_m, discard c (deferred measurement), on a random two-qubit density matrix.
rng = np.random.default_rng(53)
A = rng.normal(size=(4, 4)) + 1j * rng.normal(size=(4, 4))
rho = A @ A.conj().T
rho /= np.trace(rho)
b0, b1 = 0.7, -1.3
U = on(X, 0, 2) @ ctrl(0, 1, rx(b1), 2) @ on(X, 0, 2) @ ctrl(0, 1, rz(b0), 2)
sigma = U @ rho @ U.conj().T
deferred = sigma[:2, :2] + sigma[2:, 2:] # Tr_c: sum of the diagonal 2 x 2 blocks
measured = rx(b1) @ rho[:2, :2] @ rx(b1).conj().T + rz(b0) @ rho[2:, 2:] @ rz(b0).conj().T
print("pooling: Tr_c(U rho U^dag) equals the measured-and-rotated state:", bool(np.max(np.abs(deferred - measured)) < 1e-12))
# The 100 held-out images of the lab: port of mulberry32 and barsDataset(12, 100).
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
def bars(seed, count):
r = mulberry32(seed)
data = []
for _ in range(count):
y = 1 if r() < 0.5 else -1
k = 0 if r() < 0.5 else 1
pattern = ("1100", "0011")[k] if y == 1 else ("1010", "0101")[k]
data.append(([0.75 + 0.25 * r() if c == "1" else 0.25 * r() for c in pattern], y))
return data
test = bars(12, 100)
correct = sum(int(np.sign(qcnn(x, p)) == y) for x, y in test)
print(f"held-out images: {len(test)}, first {np.round(test[0][0], 4).tolist()} (label {test[0][1]:+d}), accuracy {correct / len(test):.2f}")Expected output
horizontal [0.9, 0.95, 0.1, 0.05]: <Z3> = +0.9487576298, prediction +1 vertical [0.9, 0.1, 0.95, 0.05]: <Z3> = -0.9026268265, prediction -1 zero weights: <Z3> = -0.9755282581, cos(pi x1) cos(pi x3) = -0.9755282581 pooling: Tr_c(U rho U^dag) equals the measured-and-rotated state: True held-out images: 100, first [0.895, 0.9853, 0.0382, 0.0034] (label +1), accuracy 1.00
Training. The lab's reference solution starts from random weights ( from mulberry32(9); held-out accuracy) and runs full-batch Adam steps (learning rate ) on the mean squared error . The loss falls from at the first step to at the thirtieth, and all held-out images are classified correctly; plain gradient descent with learning rate from the same start reaches a training loss of after steps and after . The task is easy because the label is the sign of , which the CNOT skeleton already measures. The weight never changes under gradient descent: its gradient is identically zero.
References
- I. Cong, S. Choi and M. D. Lukin, Quantum convolutional neural networks, Nature Physics 15, 1273–1278 (2019).doi:10.1038/s41567-019-0648-8
- A. Pesah, M. Cerezo, S. Wang, T. Volkoff, A. T. Sornborger and P. J. Coles, Absence of barren plateaus in quantum convolutional neural networks, Physical Review X 11, 041011 (2021).doi:10.1103/PhysRevX.11.041011
- T. Hur, L. Kim and D. K. Park, Quantum convolutional neural network for classical data classification, Quantum Machine Intelligence 4, 3 (2022).doi:10.1007/s42484-021-00061-x
- I. MacCormack, C. Delaney, A. Galda, N. Aggarwal and P. Narang, Branching quantum convolutional neural networks, arXiv:2012.14439 (2020).arxiv.org
- G. Vidal, Class of quantum many-body states that can be efficiently simulated, Physical Review Letters 101, 110501 (2008).doi:10.1103/PhysRevLett.101.110501
- M. Cerezo, A. Sone, T. Volkoff, L. Cincio and P. J. Coles, Cost function dependent barren plateaus in shallow parametrized quantum circuits, Nature Communications 12, 1791 (2021).doi:10.1038/s41467-021-21728-w
Hands-on labs
Train a QCNN to tell horizontal from vertical bars
1 step · auto-gradedOpen labTrain the 4-qubit quantum convolutional neural network of the lesson, with shared weights, on images of horizontal and vertical bars. Your TypeScript function receives training images and returns the weights
p0top11. You write the loss, the gradient and the optimiser. For the gradient, the engine'sparameterShiftGradientapplies the two-term rule to the weights and the four-term rule to the / pooling weights. The grader binds your weights into the fixed QCNN circuit and classifies held-out images by ; at least must be correct.