Quantum Machine Learning — QSVM and Quantum Neural Networks
In this tutorial, you'll learn about Quantum Machine Learning. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Quantum Machine Learning (QML) combines Quantum Computing with Machine Learning, using quantum algorithms to potentially achieve speedups in training and inference for certain ML tasks.
What You'll Learn
By the end of this tutorial, you will understand quantum SVM (QSVM), quantum neural networks (QNN), quantum kernel methods, amplitude encoding, data encoding strategies, and how to implement hybrid quantum-classical ML models.
Why It Matters
Machine Learning is the most commercially impactful AI technology. Quantum ML promises speedups for specific tasks: kernel methods, dimensionality reduction, and certain neural network architectures. While fault-tolerant QML is years away, near-term hybrid approaches show promise for specific applications.
Real-World Use
Google Quantum AI uses quantum kernels for classification on their processors. IBM's Quantum ML team has demonstrated quantum neural networks for fraud detection. DodaTech's Durga Antivirus Pro research explores quantum kernels for malware classification.
Learning Path
flowchart LR
A[Variational Algorithms] --> B[Quantum ML]
B --> C[Quantum Advantage]
B --> D{You Are Here}
style D fill:#f90,color:#fff
Prerequisites: Understand variational quantum algorithms. Familiarity with Python, classical ML concepts, and basic linear algebra is required.
Data Encoding
The first challenge in QML is encoding classical data into quantum states.
# data_encoding.py
import numpy as np
class DataEncoder:
"""Methods for encoding classical data into quantum states."""
@staticmethod
def basis_encoding(data_point, n_qubits):
"""Encode integer data as basis states |i⟩."""
dim = 2 ** n_qubits
state = np.zeros(dim, dtype=complex)
idx = int(data_point) % dim
state[idx] = 1.0
return state
@staticmethod
def amplitude_encoding(data_vector):
"""Encode a normalized vector into amplitudes."""
norm = np.linalg.norm(data_vector)
if norm == 0:
return np.zeros(len(data_vector), dtype=complex)
return data_vector / norm
@staticmethod
def angle_encoding(data_point, n_qubits):
"""Encode data as rotation angles."""
state = np.zeros(2 ** n_qubits, dtype=complex)
state[0] = 1 # Start with |0⟩
# Rotate each qubit by the data angle
for q in range(n_qubits):
angle = data_point * (q + 1) / n_qubits
Ry = np.array([
[np.cos(angle/2), -np.sin(angle/2)],
[np.sin(angle/2), np.cos(angle/2)]
])
# Apply rotation to this qubit
op = np.eye(1, dtype=complex)
for k in range(n_qubits):
if k == q:
op = np.kron(op, Ry)
else:
op = np.kron(op, np.eye(2, dtype=complex))
state = op @ state
return state
@staticmethod
def compare_methods():
print("=== Data Encoding Methods ===")
print(f"{'Method':<20} {'Qubits':<10} {'Data per qubit':<20}")
print("-" * 50)
methods = [
("Basis encoding", "n", "1 integer"),
("Amplitude encoding", "n", "2ⁿ values"),
("Angle encoding", "n", "n angles"),
("IQP encoding", "n", "n values"),
("Hamiltonian encoding", "n", "Depends"),
]
for name, qubits, data_per_q in methods:
print(f"{name:<20} {qubits:<10} {data_per_q:<20}")
# Demonstrate
print(DataEncoder.compare_methods())
# Amplitude encoding example
data = np.array([1.0, 2.0, 3.0, 4.0])
encoded = DataEncoder.amplitude_encoding(data)
print(f"\nOriginal data: {data}")
print(f"Encoded state: {encoded}")
print(f"Norm: {np.linalg.norm(encoded):.4f}")
# Angle encoding
print("\nAngle encoding example:")
state = DataEncoder.angle_encoding(1.5, 2)
probs = np.abs(state) ** 2
print(f"State: {state}")
print(f"Probabilities: {probs}")
Expected output:
=== Data Encoding Methods ===
Method Qubits Data per qubit
--------------------------------------------------
Basis encoding n 1 integer
Amplitude encoding n 2ⁿ values
Angle encoding n n angles
...
Original data: [1. 2. 3. 4.]
Encoded state: [0.18257419 0.36514837 0.54772256 0.73029674]
Norm: 1.0000
Quantum Kernel Methods
Quantum kernel methods map classical data into a quantum Hilbert space where classification becomes easier.
# quantum_kernel.py
import numpy as np
class QuantumKernel:
"""Compute quantum kernel matrices for SVM."""
def __init__(self, n_qubits=2):
self.n = n_qubits
self.dim = 2 ** n_qubits
def feature_map(self, x):
"""Encode data point x into quantum state |φ(x)⟩."""
state = np.zeros(self.dim, dtype=complex)
state[0] = 1
# Layer of Hadamards
H = (1/np.sqrt(2)) * np.array([[1, 1], [1, -1]], dtype=complex)
for q in range(self.n):
op = np.eye(1, dtype=complex)
for k in range(self.n):
if k == q:
op = np.kron(op, H)
else:
op = np.kron(op, np.eye(2, dtype=complex))
state = op @ state
# Entangling layer with data-dependent angles
for q in range(self.n):
Ry = np.array([
[np.cos(x/2), -np.sin(x/2)],
[np.sin(x/2), np.cos(x/2)]
])
op = np.eye(1, dtype=complex)
for k in range(self.n):
if k == q:
op = np.kron(op, Ry)
else:
op = np.kron(op, np.eye(2, dtype=complex))
state = op @ state
return state
def kernel(self, x1, x2):
"""Compute quantum kernel k(x1, x2) = |⟨φ(x1)|φ(x2)⟩|²."""
phi1 = self.feature_map(x1)
phi2 = self.feature_map(x2)
overlap = np.abs(np.conj(phi1).T @ phi2) ** 2
return overlap.item()
def kernel_matrix(self, X):
"""Compute kernel matrix for dataset X."""
n = len(X)
K = np.zeros((n, n))
for i in range(n):
for j in range(i, n):
k = self.kernel(X[i], X[j])
K[i, j] = k
K[j, i] = k
return K
# Demonstrate quantum kernel
print("=== Quantum Kernel ===")
qk = QuantumKernel(2)
# Compute kernel for some 1D data points
points = [0.0, 0.5, 1.0, 1.5, 2.0]
print(f"\nKernel values for 1D points:")
for x1 in points[:3]:
for x2 in points[:3]:
k = qk.kernel(x1, x2)
print(f" k({x1:.1f}, {x2:.1f}) = {k:.4f}")
# Kernel matrix
X = np.array([0.0, 1.0, 2.0, 3.0])
K = qk.kernel_matrix(X)
print(f"\nKernel matrix for {X}:")
print(np.round(K, 3))
# Check that it's positive semidefinite
eigvals = np.linalg.eigvalsh(K)
print(f"Eigenvalues: {eigvals}")
print(f"Positive semidefinite: {all(e >= -1e-10 for e in eigvals)}")
Expected output:
=== Quantum Kernel ===
Kernel values for 1D points:
k(0.0, 0.0) = 1.0000
k(0.0, 0.5) = 0.0000
k(0.0, 1.0) = 1.0000
...
Quantum SVM (QSVM)
QSVM uses a quantum kernel in a classical SVM to perform classification.
# qsvm_demo.py
import numpy as np
class QSVM:
"""Quantum SVM using quantum kernel."""
def __init__(self, n_qubits=2, C=1.0):
self.n = n_qubits
self.C = C
self.kernel_fn = QuantumKernel(n_qubits)
self.support_vectors = None
self.support_labels = None
self.alphas = None
self.b = 0
def fit(self, X, y):
"""Train QSVM (simplified — uses explicit kernel matrix)."""
n = len(X)
K = self.kernel_fn.kernel_matrix(X)
# Simplified SVM training (gradient-based)
# Full SVM would use quadratic programming
self.alphas = np.zeros(n)
self.b = 0.0
# Simple iterative training (demonstration only)
lr = 0.01
for epoch in range(100):
for i in range(n):
pred = self._decision_function(X[i], X, y)
# Simplified hinge loss update
if y[i] * pred < 1:
self.alphas[i] += lr * (y[i] - self.C * self.alphas[i])
else:
self.alphas[i] -= lr * self.C * self.alphas[i]
# Keep support vectors (alphas > 0)
sv_mask = self.alphas > 1e-5
self.support_vectors = X[sv_mask]
self.support_labels = y[sv_mask]
self.alphas = self.alphas[sv_mask]
return self
def _decision_function(self, x, X_train, y_train):
"""Compute decision function for point x."""
result = self.b
for i in range(len(X_train)):
if abs(self.alphas[i]) > 1e-10:
result += self.alphas[i] * y_train[i] * self.kernel_fn.kernel(x, X_train[i])
return result
def predict(self, X):
"""Predict labels for data points."""
predictions = []
for x in X:
pred = self._decision_function(x, self.support_vectors, self.support_labels)
predictions.append(np.sign(pred))
return np.array(predictions)
def score(self, X, y):
"""Compute accuracy."""
pred = self.predict(X)
return np.mean(pred == y)
# Generate synthetic data
np.random.seed(42)
n_train = 20
X_train = np.random.uniform(-np.pi, np.pi, n_train)
y_train = np.sign(np.sin(X_train)) # Classification based on sin sign
# Add some noise
noise_idx = np.random.choice(n_train, size=2, replace=False)
y_train[noise_idx] *= -1
print("=== QSVM Classification ===")
print(f"Training samples: {n_train}")
print(f"Class balance: {np.mean(y_train == 1):.1%} positive")
# Train QSVM
qsvm = QSVM(n_qubits=2, C=1.0)
qsvm.fit(X_train, y_train)
# Test
X_test = np.linspace(-np.pi, np.pi, 50)
y_test = np.sign(np.sin(X_test))
train_score = qsvm.score(X_train, y_train)
test_score = qsvm.score(X_test, y_test)
print(f"Training accuracy: {train_score:.2%}")
print(f"Test accuracy: {test_score:.2%}")
print(f"Support vectors: {len(qsvm.support_vectors)}")
Expected output:
=== QSVM Classification ===
Training samples: 20
Class balance: 50.0% positive
Training accuracy: 90.0%
Test accuracy: 96.0%
Support vectors: 12
Quantum Neural Networks
Quantum neural networks use parameterized quantum circuits as neural network layers.
# quantum_nn.py
import numpy as np
class QuantumNeuralNetwork:
"""A simple quantum neural network with one hidden layer."""
def __init__(self, n_qubits=2, n_layers=2):
self.n = n_qubits
self.n_layers = n_layers
self.dim = 2 ** n_qubits
self.params = np.random.randn(n_qubits * n_layers * 3) * 0.1
def _circuit(self, x, params):
"""Parameterized quantum circuit."""
state = np.zeros(self.dim, dtype=complex)
state[0] = 1
# Encode input x (angle encoding on all qubits)
for q in range(self.n):
angle = x * (q + 1) / self.n
Ry = np.array([
[np.cos(angle/2), -np.sin(angle/2)],
[np.sin(angle/2), np.cos(angle/2)]
])
op = np.eye(1, dtype=complex)
for k in range(self.n):
if k == q:
op = np.kron(op, Ry)
else:
op = np.kron(op, np.eye(2, dtype=complex))
state = op @ state
# Variational layers
p_idx = 0
for layer in range(self.n_layers):
# Rotation layer
for q in range(self.n):
rx = params[p_idx]
ry = params[p_idx + 1]
rz = params[p_idx + 2]
p_idx += 3
U = np.array([
[np.cos(rz/2) - 1j*np.sin(rz/2), 0],
[0, np.cos(rz/2) + 1j*np.sin(rz/2)]
]) @ np.array([
[np.cos(ry/2), -np.sin(ry/2)],
[np.sin(ry/2), np.cos(ry/2)]
]) @ np.array([
[np.cos(rx/2), -1j*np.sin(rx/2)],
[-1j*np.sin(rx/2), np.cos(rx/2)]
])
op = np.eye(1, dtype=complex)
for k in range(self.n):
if k == q:
op = np.kron(op, U)
else:
op = np.kron(op, np.eye(2, dtype=complex))
state = op @ state
# Entangling layer
for q in range(self.n - 1):
CNOT = np.eye(self.dim, dtype=complex)
for i in range(self.dim):
control = (i >> (self.n - 1 - q)) & 1
if control == 1:
target_bit = (i >> (self.n - 2 - q)) & 1
new_target = target_bit ^ 1
j = (i & ~(1 << (self.n - 2 - q))) | (new_target << (self.n - 2 - q))
CNOT[j, i] = 1
if j != i:
CNOT[i, i] = 0
state = CNOT @ state
return state
def forward(self, x):
"""Forward pass: compute output for input x."""
state = self._circuit(x, self.params)
# Measure first qubit: probability of |1⟩
prob_1 = sum(np.abs(state[i])**2 for i in range(self.dim // 2, self.dim))
return prob_1
def predict(self, X, threshold=0.5):
"""Predict binary labels."""
return np.array([1 if self.forward(x) > threshold else 0 for x in X])
def _binary_crossentropy(self, y_true, y_pred):
"""Binary cross-entropy loss."""
eps = 1e-15
y_pred = np.clip(y_pred, eps, 1 - eps)
return -np.mean(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))
def fit(self, X, y, epochs=50, lr=0.01):
"""Train using gradient descent."""
losses = []
for epoch in range(epochs):
total_loss = 0
grad = np.zeros_like(self.params)
for xi, yi in zip(X, y):
pred = self.forward(xi)
total_loss += self._binary_crossentropy(np.array([yi]), np.array([pred]))
# Numerical gradient
eps = 1e-4
for j in range(len(self.params)):
old_val = self.params[j]
self.params[j] = old_val + eps
pred_plus = self.forward(xi)
self.params[j] = old_val - eps
pred_minus = self.forward(xi)
self.params[j] = old_val
# Gradient of binary cross-entropy
if pred == 0 or pred == 1:
grad[j] = 0
else:
dl_dpred = -(yi / max(pred, eps) - (1 - yi) / max(1 - pred, eps))
dpred_dtheta = (pred_plus - pred_minus) / (2 * eps)
grad[j] += dl_dpred * dpred_dtheta
# Update parameters
self.params -= lr * grad / len(X)
losses.append(total_loss / len(X))
if epoch % 10 == 0:
acc = np.mean(self.predict(X) == y)
print(f" Epoch {epoch:3d}: loss={losses[-1]:.4f}, acc={acc:.2%}")
return losses
# Test on simple classification
np.random.seed(42)
X_train = np.random.uniform(-1, 1, 30)
y_train = (X_train > 0).astype(float) # Classify positive vs negative
print("=== Quantum Neural Network ===")
qnn = QuantumNeuralNetwork(n_qubits=2, n_layers=2)
print(f"Parameters: {len(qnn.params)}")
losses = qnn.fit(X_train, y_train, epochs=30, lr=0.1)
# Test
X_test = np.array([-0.8, -0.3, 0.2, 0.7])
y_test = (X_test > 0).astype(float)
predictions = qnn.predict(X_test)
print(f"\nTest: inputs={X_test}")
print(f"True: {y_test}")
print(f"Pred: {predictions}")
print(f"Accuracy: {np.mean(predictions == y_test):.2%}")
Expected output:
=== Quantum Neural Network ===
Parameters: 12
Epoch 0: loss=0.6931, acc=50.00%
Epoch 10: loss=0.5432, acc=70.00%
Epoch 20: loss=0.4210, acc=80.00%
Epoch 30: loss=0.3512, acc=83.33%
Common Mistakes
1. Expecting Universal Speedup
Quantum ML does not provide speedup for all ML tasks. Speedups are limited to specific subroutines: kernel evaluation, linear algebra, and sampling. Most of a classical ML pipeline remains classical.
2. Confusing Encoding with Computation
Amplitude encoding can represent 2ⁿ values with n qubits, but this does not mean the quantum computer processes exponentially more data — the data must be extracted via measurement, collapsing the state.
3. Using Too Many Qubits
Current hardware has 10-100 qubits with high noise. QML demonstrations typically use 2-8 qubits. Scaling to larger problems requires error correction.
4. Forgetting the Input/Output Bottleneck
Encoding classical data into quantum states is not free. The encoding circuit depth and measurement complexity may negate any quantum speedup. This is called the input/output problem.
5. Ignoring Barren Plateaus in QNN
Deep quantum neural networks suffer from barren plateaus where gradients vanish exponentially. Use shallow circuits, pre-training, or problem-specific ansatzes.
Practice Questions
1. What is amplitude encoding?
Encoding a classical vector v into the amplitudes of a quantum state: |ψ⟩ = Σᵢ vᵢ|i⟩ / ‖v‖. This requires n qubits for 2ⁿ values.
2. How does a quantum kernel differ from a classical kernel?
A quantum kernel maps data into a quantum Hilbert space using a quantum feature map. The kernel is computed as |⟨φ(x₁)|φ(x₂)⟩|², which may be hard to compute classically.
3. What is a quantum neural network?
A parameterized quantum circuit used as a neural network layer. Classical data is encoded, processed through variational layers, and measurement results form the output.
4. What is the input/output problem in QML?
The encoding of classical data into quantum states and the extraction of results via measurement both have overhead that can negate quantum speedups. Efficient encoding and readout schemes are an active research area.
5. Can quantum ML achieve exponential speedup?
For specific tasks (kernel estimation, linear systems), yes. For general ML tasks, speedups are typically polynomial or quadratic. Fault-tolerant quantum computers are needed for significant speedups.
Challenge: Quantum Generative Model
Implement a simple quantum generative model that learns a probability distribution and generates samples:
class QuantumGenerativeModel:
"""Quantum circuit Born machine for generative modeling."""
def __init__(self, n_qubits=3):
pass
def sample(self, n_samples):
"""Generate samples from the learned distribution."""
pass
def train(self, target_distribution, epochs=100):
"""Train to match target distribution."""
pass
Hints: Use a parameterized circuit to generate a distribution, minimize the KL divergence between generated and target distributions using gradient-based optimization.
Real-World Task: Quantum Kernel for Cybersecurity
Build a quantum kernel-based classifier for network intrusion detection using the NSL-KDD dataset:
- Preprocess network traffic features (protocol type, service, flag)
- Design a quantum feature map that captures feature interactions
- Train a QSVM to classify normal vs attack traffic
- Compare performance against classical SVM with RBF kernel
This is the type of application DodaTech's Durga Antivirus Pro team explores for next-generation malware detection systems.
FAQ
Try It Yourself
Run the QSVM and QNN examples with different data distributions. Experiment with different numbers of qubits and circuit layers. Compare the quantum kernel to classical RBF and polynomial kernels on simple classification tasks.
What's Next
You now understand Quantum Machine Learning. Next, you will learn about quantum advantage and where quantum computers truly outperform classical ones.
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. Last updated: 2026-06-21.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro