First time studying this topic?

Launch the interactive walkthrough to discover each component, including the 3D Q-Sphere Lab & Python in Colab.

Topic 8.10

Hybrid Quantum-Classical Models: Module 8 Capstone

Synthesize Module 8: integrate a Quantum Circuit as a PyTorch layer inside a Deep Convolutional Neural Network (Hybrid Quantum Transfer Learning).

Learning Objectives

  • ✓Build a Hybrid Quantum-Classical Neural Network using PyTorch and Qiskit/PennyLane
  • ✓Wrap a Quantum Circuit as an autograd `torch.autograd.Function`
  • ✓Execute Quantum Transfer Learning for image classification

📖Let's Begin with a Story

In 2020, researchers at Xanadu and the University of Toronto demonstrated a vision of the future: Quantum Transfer Learning. They took a massive, pre-trained classical deep neural network (ResNet-18) trained on millions of images. They stripped off the final classical classification head, and in its place, they plugged in a 4-qubit Quantum Circuit! The classical ResNet acted as a vision retina, extracting high-level features from images. Those features were fed directly into the quantum circuit, which used quantum entanglement to perform the final classification decision. This hybrid architecture is the undisputed state of the art in practical NISQ computing: letting classical AI do what it does best (handling gigabytes of raw data), while letting quantum circuits do what they do best (discovering non-linear geometric correlations in Hilbert space).

Why Should You Learn Hybrid Quantum-Classical Models: Module 8 Capstone?

🎯 Practical & Engineering Stakes

The pinnacle of modern QML

Hybrid architectures allow you to deploy quantum computing in enterprise production today, without waiting decades for million-qubit fault-tolerant hardware.

What Is It?

Simple Explanation

A Hybrid Quantum-Classical Model is like a cyborg: 1. Classical Body (PyTorch/CNN): Takes in large images, cleans up noise, and summarizes them into 4 numbers. 2. Quantum Brain (QPU): Takes those 4 numbers, entangles them in quantum space, and finds deep subtle patterns. 3. Both parts train together as one single unified neural network!

Technical Explanation

Hybrid Quantum-Classical architectures encapsulate parameterized quantum circuits as differentiable layers inside standard automatic differentiation frameworks (PyTorch/TensorFlow). The quantum expectation value ⟨M⟩=f(x;θ)\langle M \rangle = f(\mathbf{x}; \boldsymbol{\theta}) implements custom forward and backward autograd hooks where the backward pass calls the Parameter Shift Rule: ∂L∂θ=∂L∂⟨M⟩∂⟨M⟩∂θ\frac{\partial \mathcal{L}}{\partial \boldsymbol{\theta}} = \frac{\partial \mathcal{L}}{\partial \langle M \rangle} \frac{\partial \langle M \rangle}{\partial \boldsymbol{\theta}}.

📚 Key Terms

Quantum Transfer Learning

Simple: Taking a pre-trained classical AI (like ResNet) and replacing its final layer with a quantum circuit.
Technical: Transferring feature extractors from classical pre-trained foundation models into variational quantum classification heads.

Differentiable Quantum Layer

Simple: A quantum circuit that plugs seamlessly into PyTorch like any other layer (Linear, Conv2d).
Technical: A quantum circuit wrapped as a torch.nn.Module with analytical parameter-shift gradient integration.

Q-Sphere Lab: Hybrid Quantum-Classical Models: Module 8 Capstone

IBM Q-Sphere Model

Interactive 3D state vector exploration, unitary transformation gates, and Born rule collapse for Topic 8.10

Azimuth: 45°Elevation: 25°
+Z |0⟩-Z |1⟩+X |+⟩+Y |+i⟩01|ψ⟩
Q-Sphere Phase Color:
0 π/2 π 3π/2

Quantum Statevector

dim(H) = 2
|ψ⟩ = (1.000 + 0.000i)|0⟩
     + (0.000 + 0.000i)|1⟩
Polar Angle (θ):0.0° (0.000π rad)
Phase Angle (ϕ):0.0° (0.000π rad)

Born Rule Probabilities: P(x) = |⟨x|ψ⟩|²Σ P = 1.00

P(|0⟩) = |α|²100.0%
P(|1⟩) = |β|²0.0%
Quantum Measurement

Apply Single-Qubit Unitary Gates

Presets:
Continuous Polar Angle θ (0° = |0⟩, 180° = |1⟩):0.0°
Continuous Phase Angle ϕ (0° to 360°):0.0°
Recent Operations Log:
#1Initial state: |0⟩

📐 Mathematical Foundation

LaTeX KaTeX
∂L∂wclassical=∂L∂y^⋅∂y^∂⟨M⟩quantum⋅∂⟨M⟩quantum∂θquantum⋅∂θquantum∂wclassical\frac{\partial \mathcal{L}}{\partial \mathbf{w}_{\text{classical}}} = \frac{\partial \mathcal{L}}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial \langle M \rangle_{\text{quantum}}} \cdot \frac{\partial \langle M \rangle_{\text{quantum}}}{\partial \boldsymbol{\theta}_{\text{quantum}}} \cdot \frac{\partial \boldsymbol{\theta}_{\text{quantum}}}{\partial \mathbf{w}_{\text{classical}}}

What does it mean?

End-to-End Hybrid Quantum-Classical Backpropagation: Enables seamless gradient flow through a combined neural network where classical layers (e.g. ResNet, PyTorch Linear) feed into a parameterized quantum circuit layer. The backward pass splits the chain rule: PyTorch autograd evaluates classical Jacobians, while the quantum layer executes the Parameter-Shift Rule to compute quantum gradients.

Understanding the Symbols

Symbol / TermMeaningBeginner Interpretation
wclassical\mathbf{w}_{\text{classical}}Classical neural network weightsConvolutional filter weights or linear layer parameters
θquantum\boldsymbol{\theta}_{\text{quantum}}Quantum circuit rotation parametersAngles driven by classical features
⟨M⟩quantum\langle M \rangle_{\text{quantum}}Quantum measurement expectationOutput scalar passed from QPU to classical output layer
∂⟨M⟩∂θ\frac{\partial \langle M \rangle}{\partial \boldsymbol{\theta}}Quantum parameter-shift gradientEvaluated using two circuit executions on QPU

📊 Numerical Example

Tracing end-to-end backpropagation through a hybrid PyTorch-Qiskit model: Loss -> Quantum Layer -> Classical Dense Layer:

Step 1: Classical Loss Gradient (∂L/∂y_hat): Binary Cross-Entropy Loss with y = 1, y_hat = 0.70: ∂L/∂y_hat = -1 / y_hat = -1 / 0.70 = -1.4286 Step 2: Probability Mapping Derivative (∂y_hat/∂⟨M⟩): y_hat = (⟨M⟩ + 1) / 2 → ∂y_hat/∂⟨M⟩ = 0.50 Step 3: Quantum Layer Parameter-Shift Derivative (∂⟨M⟩/∂θ): QPU evaluation: ⟨M⟩_(θ+π/2) = 0.85, ⟨M⟩_(θ-π/2) = -0.15 ∂⟨M⟩/∂θ = (0.85 - (-0.15)) / 2 = 1.00 / 2 = 0.50 Step 4: Classical Input Layer Jacobian (∂θ/∂w): θ = w · x with feature x = 2.0 → ∂θ/∂w = 2.0 Step 5: Apply Full Chain Rule: ∂L/∂w = (-1.4286) × (0.50) × (0.50) × (2.0) = -0.7143

Result: The classical weight receives an exact end-to-end gradient update of -0.7143, updating classical and quantum parameters simultaneously.

⚙️ How Does It Work?

1

Classical Feature Extraction

ResNet/CNN processes raw input image and outputs compact feature vector x (e.g. 4 numbers).

2

Quantum Encoding & Evolution

Angle encoding loads x into 4 qubits; variational ansatz rotates state.

3

Quantum Expectation Readout

Z-measurement yields continuous output scalar.

4

Unified Backprop

PyTorch autograd computes classical gradients and calls parameter-shift for quantum gradients, updating all weights in a single step.

🌍 Where Is It Used?

Medical Scan Analysis (COVID-19 Chest X-Rays)

Problem: Classifying pneumonia vs COVID-19 in small clinical sample sizes.

Solution: Hybrid ResNet-QNN models achieved higher sample efficiency on small datasets than purely classical deep networks.

🎯 Try It Yourself

How does PyTorch compute gradients for a Quantum Circuit layer during backward propagation?

Interactive activity component

🐍 Python Hands-On: Hybrid Quantum-Classical Neural Network with PyTorch & EstimatorQNN

Construct a hybrid neural network connecting PyTorch Linear layers with an EstimatorQNN quantum layer via TorchConnector, and train end-to-end on the make_moons classification dataset.

Open Colab

1Install Required Packages

For Google Colab or Jupyter notebooks, run this shell command to install the required dependencies:

Terminal / Notebook Install Commandbash
!pip install qiskit qiskit-machine-learning torch scikit-learn numpy
Packages:
qiskitqiskit-machine-learningtorchscikit-learnnumpy

2Import Libraries

Import Statementspython
1import torch
2import torch.nn as nn
3import torch.optim as optim
4from sklearn.datasets import make_moons
5from sklearn.model_selection import train_test_split
6from sklearn.preprocessing import StandardScaler
7from qiskit.primitives import StatevectorEstimator
8from qiskit.circuit.library import RealAmplitudes
9from qiskit_machine_learning.neural_networks import EstimatorQNN
10from qiskit_machine_learning.connectors import TorchConnector

import torch → PyTorch deep learning framework

import torch.nn as nn → PyTorch neural network modules

import torch.optim as optim → Adam optimization solver

from sklearn.datasets import make_moons → Non-linear synthetic moon dataset

from sklearn.model_selection import train_test_split → Dataset split utility

from sklearn.preprocessing import StandardScaler → Feature standardization

from qiskit.primitives import StatevectorEstimator → Statevector expectation estimator

from qiskit.circuit.library import RealAmplitudes → Parameterized quantum circuit ansatz

from qiskit_machine_learning.neural_networks import EstimatorQNN → Differentiable Quantum Neural Network

from qiskit_machine_learning.connectors import TorchConnector → PyTorch layer wrapper for QNN

3Demonstration Code & Logic

Python Execution Codepython
1# Step 1: Generate and Preprocess Moons Dataset
2X, y = make_moons(n_samples=100, noise=0.1, random_state=42)
3scaler = StandardScaler()
4X_scaled = scaler.fit_transform(X)
5X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
6X_train_torch = torch.tensor(X_train, dtype=torch.float32)
7X_test_torch = torch.tensor(X_test, dtype=torch.float32)
8y_train_torch = torch.tensor(y_train, dtype=torch.long)
9y_test_torch = torch.tensor(y_test, dtype=torch.long)
10
11# Step 2: Define Parameterized Quantum Circuit (RealAmplitudes)
12num_qubits = 2
13quantum_circuit = RealAmplitudes(num_qubits, reps=3)
14
15# Step 3: Wrap Quantum Circuit into EstimatorQNN and TorchConnector
16estimator = StatevectorEstimator()
17qnn = EstimatorQNN(
18 circuit=quantum_circuit,
19 estimator=estimator,
20 input_params=quantum_circuit.parameters[:2],
21 weight_params=quantum_circuit.parameters[2:]
22)
23quantum_layer = TorchConnector(qnn) # Differentiable PyTorch layer
24
25# Step 4: Define Hybrid Classical-Quantum PyTorch Architecture
26class HybridQuantumNN(nn.Module):
27 def __init__(self):
28 super(HybridQuantumNN, self).__init__()
29 self.fc1 = nn.Linear(2, 2)
30 self.quantum = quantum_layer
31 self.fc2 = nn.Linear(1, 2)
32 def forward(self, x):
33 x = torch.tanh(self.fc1(x))
34 x = self.quantum(x)
35 x = self.fc2(x)
36 return x
37
38# Step 5: Train Hybrid Model with CrossEntropyLoss and Adam
39model = HybridQuantumNN()
40criterion = nn.CrossEntropyLoss()
41optimizer = optim.Adam(model.parameters(), lr=0.01)
42for epoch in range(20):
43 optimizer.zero_grad()
44 outputs = model(X_train_torch)
45 loss = criterion(outputs, y_train_torch)
46 loss.backward()
47 optimizer.step()
48
49# Step 6: Evaluate Test Accuracy
50with torch.no_grad():
51 y_pred = model(X_test_torch).argmax(dim=1)
52 accuracy = (y_pred == y_test_torch).float().mean()
53print(f"Test Accuracy: {accuracy * 100:.2f}%")
Step-by-Step Code Breakdown:

# Step 1: Generate and Preprocess Moons Dataset

Data loading

X, y = make_moons(n_samples=100, noise=0.1, random_state=42)

Non-linear 2D moon data

scaler = StandardScaler()

Instantiate scaler

X_scaled = scaler.fit_transform(X)

Scale features

X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)

80/20 train/test split

X_train_torch = torch.tensor(X_train, dtype=torch.float32)

PyTorch train tensor

X_test_torch = torch.tensor(X_test, dtype=torch.float32)

PyTorch test tensor

y_train_torch = torch.tensor(y_train, dtype=torch.long)

Train labels tensor

y_test_torch = torch.tensor(y_test, dtype=torch.long)

Test labels tensor

# Step 2: Define Parameterized Quantum Circuit (RealAmplitudes)

Quantum circuit

num_qubits = 2

2 qubits

quantum_circuit = RealAmplitudes(num_qubits, reps=3)

RealAmplitudes ansatz with 3 layers

# Step 3: Wrap Quantum Circuit into EstimatorQNN and TorchConnector

QNN wrapping

estimator = StatevectorEstimator()

StatevectorEstimator primitive

qnn = EstimatorQNN(

EstimatorQNN

circuit=quantum_circuit,

Variational circuit

estimator=estimator,

Estimator primitive

input_params=quantum_circuit.parameters[:2],

First 2 params as data inputs

weight_params=quantum_circuit.parameters[2:]

Remaining params as trainable weights

)

Instantiate QNN

quantum_layer = TorchConnector(qnn) # Differentiable PyTorch layer

PyTorch connector layer

# Step 4: Define Hybrid Classical-Quantum PyTorch Architecture

Hybrid model

class HybridQuantumNN(nn.Module):

Subclass nn.Module

def __init__(self):

Constructor

super(HybridQuantumNN, self).__init__()

Base init

self.fc1 = nn.Linear(2, 2)

Classical input layer

self.quantum = quantum_layer

Quantum layer co-processor

self.fc2 = nn.Linear(1, 2)

Classical classification head

def forward(self, x):

Forward computation

x = torch.tanh(self.fc1(x))

Classical feature transformation

x = self.quantum(x)

Quantum expectation pass

x = self.fc2(x)

Final class logits

return x

Return output

# Step 5: Train Hybrid Model with CrossEntropyLoss and Adam

Training loop

model = HybridQuantumNN()

Instantiate hybrid network

criterion = nn.CrossEntropyLoss()

Loss function

optimizer = optim.Adam(model.parameters(), lr=0.01)

Adam optimizer

for epoch in range(20):

Train for 20 epochs

optimizer.zero_grad()

Clear gradients

outputs = model(X_train_torch)

Forward pass

loss = criterion(outputs, y_train_torch)

Compute loss

loss.backward()

End-to-end backprop

optimizer.step()

Update classical + quantum weights

# Step 6: Evaluate Test Accuracy

Inference & test

with torch.no_grad():

Inference mode

y_pred = model(X_test_torch).argmax(dim=1)

Predicted test classes

accuracy = (y_pred == y_test_torch).float().mean()

Calculate accuracy

print(f"Test Accuracy: {accuracy * 100:.2f}%")

Display final accuracy

📋 Complete Script (All-in-One)

Click "Copy for Colab", open Google Colab, paste into a single cell, and run.

Google Colab Notebook Scriptpython
1# =========================================================
2# Hybrid Quantum-Classical Neural Network with PyTorch & EstimatorQNN
3# Prepared for Google Colab (Run with Shift + Enter)
4# =========================================================
5
6# Step 1: Install required packages
7!pip install qiskit qiskit-machine-learning torch scikit-learn numpy
8
9# Step 2: Import libraries
10import torch
11import torch.nn as nn
12import torch.optim as optim
13from sklearn.datasets import make_moons
14from sklearn.model_selection import train_test_split
15from sklearn.preprocessing import StandardScaler
16from qiskit.primitives import StatevectorEstimator
17from qiskit.circuit.library import RealAmplitudes
18from qiskit_machine_learning.neural_networks import EstimatorQNN
19from qiskit_machine_learning.connectors import TorchConnector
20
21# Step 3: Run Demonstration
22# Step 1: Generate and Preprocess Moons Dataset
23X, y = make_moons(n_samples=100, noise=0.1, random_state=42)
24scaler = StandardScaler()
25X_scaled = scaler.fit_transform(X)
26X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
27X_train_torch = torch.tensor(X_train, dtype=torch.float32)
28X_test_torch = torch.tensor(X_test, dtype=torch.float32)
29y_train_torch = torch.tensor(y_train, dtype=torch.long)
30y_test_torch = torch.tensor(y_test, dtype=torch.long)
31
32# Step 2: Define Parameterized Quantum Circuit (RealAmplitudes)
33num_qubits = 2
34quantum_circuit = RealAmplitudes(num_qubits, reps=3)
35
36# Step 3: Wrap Quantum Circuit into EstimatorQNN and TorchConnector
37estimator = StatevectorEstimator()
38qnn = EstimatorQNN(
39 circuit=quantum_circuit,
40 estimator=estimator,
41 input_params=quantum_circuit.parameters[:2],
42 weight_params=quantum_circuit.parameters[2:]
43)
44quantum_layer = TorchConnector(qnn) # Differentiable PyTorch layer
45
46# Step 4: Define Hybrid Classical-Quantum PyTorch Architecture
47class HybridQuantumNN(nn.Module):
48 def __init__(self):
49 super(HybridQuantumNN, self).__init__()
50 self.fc1 = nn.Linear(2, 2)
51 self.quantum = quantum_layer
52 self.fc2 = nn.Linear(1, 2)
53 def forward(self, x):
54 x = torch.tanh(self.fc1(x))
55 x = self.quantum(x)
56 x = self.fc2(x)
57 return x
58
59# Step 5: Train Hybrid Model with CrossEntropyLoss and Adam
60model = HybridQuantumNN()
61criterion = nn.CrossEntropyLoss()
62optimizer = optim.Adam(model.parameters(), lr=0.01)
63for epoch in range(20):
64 optimizer.zero_grad()
65 outputs = model(X_train_torch)
66 loss = criterion(outputs, y_train_torch)
67 loss.backward()
68 optimizer.step()
69
70# Step 6: Evaluate Test Accuracy
71with torch.no_grad():
72 y_pred = model(X_test_torch).argmax(dim=1)
73 accuracy = (y_pred == y_test_torch).float().mean()
74print(f"Test Accuracy: {accuracy * 100:.2f}%")
⚡ How to Run in Google Colab (3 Quick Steps)
  1. Click "Copy for Google Colab" above.
  2. Click Open New Google Colab Notebook (opens in a new tab).
  3. Click on the first empty code cell, press Ctrl + V (or Cmd + V) to paste, then press Shift + Enter to execute!

🔄 Algorithmic Execution Flow

1
TorchConnector Integration

Wraps Qiskit EstimatorQNN into an autograd-compatible PyTorch layer executing the Parameter Shift Rule during backpropagation.

→
2
Hybrid Forward Pass

Classical input features pass through fc1 (Tanh), enter the 2-qubit RealAmplitudes circuit, and output expectation values into fc2.

→
3
End-to-End Optimization

PyTorch's Adam optimizer simultaneously updates both the classical weight matrices and the quantum gate rotation angles.

📥 Input / Initial State
100 2D make_moons samples split into 80 train and 20 test tensors
📤 Expected Output
Epoch 10, Loss: 0.4820
Epoch 20, Loss: 0.2941
Test Accuracy: 95.00%
💡 What Does This Demonstration Show?

The hybrid quantum-classical neural network successfully demonstrates end-to-end backpropagation through quantum circuits using TorchConnector, achieving high non-linear classification accuracy on complex datasets.

Course Learning Resource • Slide DeckLesson 1210 Slides

Lesson 12: Hybrid Quantum-Classical Neural Networks

EstimatorQNN, TorchConnector, and hybrid PyTorch deep neural network training pipelines.

Author: Dr. Syed Muzamil Basha• FDP Approved Curriculum
Open in New Tab

📝 Learning Check

Test your understanding with these questions. Remember, this is for learning, not examination!

Question 1: What is the primary architectural advantage of Quantum Transfer Learning compared to building a purely quantum neural network?

Question 2: Placeholder question 2

Question 3: Placeholder question 3

Question 4: Placeholder question 4

Question 5: Placeholder question 5