Skip to content

Quantum Machine Learning — QSVM and Quantum Neural Networks

DodaTech Updated 2026-06-21 13 min read

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
ℹ️ Info

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:

  1. Preprocess network traffic features (protocol type, service, flag)
  2. Design a quantum feature map that captures feature interactions
  3. Train a QSVM to classify normal vs attack traffic
  4. 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

Is Quantum Machine Learning better than classical?

For most current tasks, no. Classical ML with well-tuned models outperforms QML on near-term hardware. QML may offer advantages for specific problems (kernel methods, high-dimensional data) in the future.

When will QML be practical?

Likely requires fault-tolerant quantum computers with 1000+ logical qubits. Current noisy devices can demonstrate QML concepts but not achieve practical advantage.

What is the best quantum ML algorithm?

Quantum kernel methods are currently the most promising near-term approach. Quantum neural networks face barren plateau challenges. Quantum linear algebra (Harrod-Hassidim-Lloyd) requires fault tolerance.

Can I run QML on current hardware?

Yes, for small demonstrations (2-8 qubits). IBM Qiskit, Google Cirq, and PennyLane support QML. Xanadu's PennyLane is specifically designed for QML research.

What is PennyLane?

PennyLane is a QML framework by Xanadu that provides automatic differentiation of quantum circuits, integrating with PyTorch, TensorFlow, and JAX for hybrid classical-quantum ML.

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

Quantum Advantage Explained
Variational Quantum Algorithms
IBM Qiskit Guide

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