This project trains a CNN on Fashion-MNIST, uses its penultimate dense layer as a feature extractor, compresses features with PCA to n_qubits, and feeds them to a variational quantum classifier (VQC) built with PennyLane. Originally built with TensorFlow + Keras + PennyLane, the project was migrated entirely to PyTorch due to the deprecation of TensorFlow support in newer PennyLane versions.
This migration enables smoother integration, stable gradient computation, and full control of training through PyTorch’s flexible API.
Default dataset in the notebook is
tf.keras.datasets.fashion_mnist
- Dataset: Fashion-MNIST from
torchvision.datasets. - The model can be trained on:
- 3-class subset: (T-shirt, Dress, Shirt), or
- Full 10-class dataset: (all Fashion-MNIST categories).
- Images are normalized to the range [0, 1] for stable training.
A Convolutional Neural Network extracts compact feature vectors from 28×28 grayscale images:
Conv2D(16, 3×3, ReLU, L2=0.001)
→ MaxPool(2×2)
→ Conv2D(32, 3×3, ReLU, L2=0.001)
→ MaxPool(2×2)
→ Flatten → Dropout(0.3)
→ Dense(64, ReLU)
→ Dense(output_classes)
- The penultimate 64-dimensional layer is used as a feature representation for quantum processing.
- CNN features are standardized using
StandardScaler. - Principal Component Analysis (PCA) reduces features to a smaller space
(e.g., 4 components → 4 qubits). - PCA outputs are then scaled to [-π, π] for quantum angle encoding.
- Device:
default.qubit(orlightning.qubitfor faster CPU simulation) - Each input feature vector (of size
n_qubits) is encoded using AngleEmbedding. - Variational layers are applied using StronglyEntanglingLayers.
- Each qubit’s measurement ⟨Z⟩ forms part of the output feature vector.
@qml.qnode(dev, interface="torch", diff_method="backprop")
def quantum_circuit(inputs, weights):
qml.AngleEmbedding(inputs, wires=range(n_qubits))
qml.templates.StronglyEntanglingLayers(weights, wires=range(n_qubits))
return [qml.expval(qml.PauliZ(i)) for i in range(n_qubits)]The quantum outputs are passed through a small classical head for classification:
QuantumLayer → Dropout(0.3) → Linear(n_qubits → output_classes)Training Configuration:
Loss: CrossEntropyLoss
Optimizer: Adam (lr = 1e-4)
Early Stopping: patience = 5, with best-weight restoration
CNN
- Conv filters: 16 → 32
- Dense(64), Dropout(0.3), L2=1e-3
- batch_size=64, epochs=20, patience=3
PCA / Quantum
n_qubits (default 4) — trades off dimension vs circuit depth
n_layers (default 4) — more layers increase expressivity
Hybrid training
lr=1e-4, batch_size=8, epochs=20, patience=5
Baseline
Hidden units: 32, Dropout(0.5), epochs=10, batch_size=32