Skip to content

Training#

This section describes how to use the model provided with this package, using a simple training scenario as an example.

We consider a Fourier series with n frequencies defined as follows:

f(x,θ)=ωΩcω(θ)eiωx=ωΩcω(θ)(cos(ωx)+isin(ωx))

Here, ωΩ are the frequencies in the spectrum with the Fourier coefficients cω(θ), parameterized by the set of trainable parameters θ.

As shown by Schuld et al. (2020), a quantum circuit, parametrised by θ and input x and is equivalent to the Fourier series representation. Such circuits must be of the following form: f(x,θ)=0|nU(x,θ)MU(x,θ)|0n

Therefore, training such a model on a Fourier series is a proof-of-concept which we want to demonstrate here.

Let's start with building our dataset. A Fourier series with 4 frequencies:

import pennylane.numpy as np
import matplotlib.pyplot as plt

domain = [-np.pi, np.pi]
omegas = np.array([1, 2, 3, 4])
coefficients = np.array([0.5, 0.5, 0.5, 0.5])

# Calculate the number of required samples to satisfy the Nyquist criterium
n_d = int(np.ceil(2 * np.max(np.abs(domain)) * np.max(omegas)))
# Sample the domain linearly
x = np.linspace(domain[0], domain[1], num=n_d)

# define our Fourier series f(x)
def f(x):
    return 1 / np.linalg.norm(omegas) * np.sum(coefficients * np.cos(omegas.T * x))

# evaluate f(x) on the domain samples
y = np.stack([f(sample) for sample in x])

plt.plot(x, y)
plt.xlabel("x")
plt.ylabel("f(x)")
plt.show()

Fourier Series Fourier Series

Note that we chose the coefficients to be all 0.5. Play around with those values to change the magnitude of each frequency component. Also note that we're using the Pennylane version of Numpy, which is required because of the optimizer that we will be using later. Now that we have our "dataset", let's move on and build a model:

from qml_essentials.model import Model

model = Model(
    n_qubits=4,
    n_layers=1,
    circuit_type="Circuit_19",
)

This is the minimal amout of information needed. According to the work referenced above, a model with 4 qubits should be capable of learning a Fourier series with 4 frequencies, considering single qubit Pauli encoding (which we have by default).

Now, let's train our model:

import pennylane as qml

opt = qml.AdamOptimizer(stepsize=0.01)

def cost_fct(params):
    y_hat = model(params=params, inputs=x, force_mean=True)

    return np.mean((y_hat - y) ** 2)

for epoch in range(1, 1001):
    model.params, cost_val = opt.step_and_cost(cost_fct, model.params)

    if epoch % 100 == 0:
        print(f"Epoch: {epoch}, Cost: {cost_val:.4f}")

plt.plot(x, y, label="True function")
plt.plot(x, model(params=model.params, inputs=x, force_mean=True), label="Model prediction")
plt.xlabel("x")
plt.ylabel("f(x)")
plt.legend()
plt.show()

Epoch: 100, Cost: 0.0081
Epoch: 200, Cost: 0.0073
Epoch: 300, Cost: 0.0051
Epoch: 400, Cost: 0.0043
Epoch: 500, Cost: 0.0036
Epoch: 600, Cost: 0.0022
Epoch: 700, Cost: 0.0014
Epoch: 800, Cost: 0.0008
Epoch: 900, Cost: 0.0006
Epoch: 1000, Cost: 0.0001

Ground Truth and Prediction Ground Truth and Prediction

As you can see, the model is able to learn the Fourier series with the 4 frequencies.

Btw. if you're in a hurry, we have a Jupyter notebook with the exact same example here 🙃.

Wondering what to do next? You can try a few different models, and see how they perform. If you're curious, checkout how this correlates with the Entanglement and Expressibility of the model.