Skip to content

QML Binary Classifier ​

In this tutorial, you'll build a Quantum Machine Learning (QML) binary classifier from scratch. By the end, you'll have a variational quantum circuit that learns to classify 2D points using gradient descent.

What You'll Learn ​

  • How to encode classical data into quantum states
  • How to build a parameterized (variational) quantum circuit
  • How to measure quantum observables for classification
  • How to train quantum circuits using the parameter shift rule
  • How to put it all together into a working classifier

Prerequisites ​

The Problem ​

We want to classify 2D points as either above or below the line x + y = 1:

xy11+1 (above)βˆ’1 (below)x+y=1

Points above the line get label +1, points below get -1. Our quantum circuit will learn to make this distinction.

Part 1: Training Data ​

Let's start with a simple dataset of four labeled points:

Each point is a tuple of (x, y, label). We use inline destructuring to extract components: (x, y, label) = point.

Part 2: Encoding Data into Qubits ​

The first step in any QML algorithm is encoding classical data into quantum states. We'll use angle encoding: each coordinate becomes a rotation angle.

The ry(theta) gate rotates a qubit's state. When x = 0, the qubit stays in |0⟩. When x = 1, it rotates fully to |1⟩. Values in between create superpositions.

Why Angle Encoding?

Angle encoding maps continuous values to quantum amplitudes naturally. It's simple and works well for low-dimensional data. For high-dimensional data, other encodings (amplitude encoding, basis encoding) may be more efficient.

Part 3: The Variational Ansatz ​

A variational ansatz is a parameterized quantum circuit. The parameters are what we'll train. Our ansatz has four parameters controlling rotations:

The structure is:

  1. RY rotations - control the "amount" of |0⟩ vs |1⟩
  2. RZ rotations - control the phase (important for interference)
  3. CNOT gate - entangles the two qubits

Why Entanglement?

Entanglement allows the circuit to capture correlations between features (x and y). Without it, the circuit could only process each coordinate independently.

Part 4: Getting Continuous Output with expect_z ​

Regular measurement gives 0 or 1, but we want a continuous value for classification. The expect_z function returns the expectation value of the Z observable:

  • Result = +1 means the qubit is definitely in |0⟩
  • Result = -1 means the qubit is definitely in |1⟩
  • Values between indicate superposition

This maps perfectly to our labels: +1 for above the line, -1 for below.

Part 5: The Complete Classifier ​

Now we can put it together: encode β†’ ansatz β†’ measure:

With random parameters, the classifier makes random predictions. We need to train the parameters to make correct predictions.

Part 6: The Cost Function ​

To train, we need a way to measure "how wrong" our predictions are. We'll use mean squared error (MSE):

How to read this formula
  • Cost = the total error we're trying to minimize
  • n = number of training points (4 in our case)
  • Ξ£ (sigma) = "sum over all points"
  • (prediction - label)Β² = squared difference between what we predicted and the true label
  • Dividing by n gives the average error

Lower cost = better predictions. Our goal is to find parameters that minimize the cost.

Notice how we use map and sumf instead of a manual loopβ€”this is more functional and concise.

Part 7: Computing Gradients ​

To minimize the cost, we need to know which direction to adjust each parameter. The parameter shift rule computes exact gradients for quantum circuits:

How to read this formula
  • βˆ‚f/βˆ‚ΞΈ = "how much does f change when ΞΈ changes?" (the gradient)
  • ΞΈ (theta) = a parameter we're optimizing
  • Ο€/2 = 90 degrees (about 1.57)
  • We evaluate the cost at ΞΈ+Ο€/2 and ΞΈ-Ο€/2, then take the difference divided by 2
  • This gives us the exact gradient for quantum rotation gates

This works because quantum gates are periodic. We evaluate the cost with the parameter shifted by Β±Ο€/2 and take the difference.

First, we need a helper to create parameter lists with one value changed. We use zip to pair indices with values:

Part 8: Training with Gradient Descent ​

Finally, we put everything together into a training loop:

  1. Compute the gradient for each parameter
  2. Update parameters: new_param = old_param - learning_rate * gradient
  3. Repeat

How It Works ​

Let's trace through what happens during training:

  1. Forward pass: For each training point, the classifier:

    • Encodes (x, y) into qubit rotations
    • Applies the parameterized ansatz
    • Measures the expectation value
  2. Cost calculation: Squared difference between predictions and labels

  3. Gradient computation: For each parameter:

    • Evaluate cost with parameter + Ο€/2
    • Evaluate cost with parameter - Ο€/2
    • Gradient = (cost+ - cost-) / 2
  4. Parameter update: Move each parameter in the direction that reduces cost

After enough steps, the circuit learns to output positive values for points above the line and negative values for points below.

Next Steps ​

  • Try adding more training data
  • Experiment with different ansatz structures (more layers, different gates)
  • Try different learning rates
  • Extend to multi-class classification

Full Example ​

The complete example is available at examples/qml_classifier.ket in the Kettle repository. Run it with:

bash
kettle run examples/qml_classifier.ket