Kernel based training demonstration

I am new to kernel methods and so I was trying to run the demonstration on my local notebook. Here’s the code:

import numpy as np
import torch
from torch.nn.functional import relu

from sklearn.svm import SVC
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

import pennylane as qml
from pennylane.templates import AngleEmbedding, StronglyEntanglingLayers, AmplitudeEmbedding
from pennylane.operation import Tensor

import matplotlib.pyplot as plt

np.random.seed(42)


X, y = load_iris(return_X_y=True)

# pick inputs and labels from the first two classes only,
# corresponding to the first 100 samples
X = X[:100]
y = y[:100]

# scaling the inputs is important since the embedding we use is periodic
scaler = StandardScaler().fit(X)
X_scaled = scaler.transform(X)

# scaling the labels to -1, 1 is important for the SVM and the
# definition of a hinge loss
y_scaled = 2 * (y - 0.5)

X_train, X_test, y_train, y_test = train_test_split(X_scaled, y_scaled)

n_qubits = len(X_train[0])
n_qubits

dev_kernel = qml.device("default.qubit", wires=n_qubits, shots=None)

projector = np.zeros((2**n_qubits, 2**n_qubits))
projector[0, 0] = 1

@qml.qnode(dev_kernel)
def kernel(x1, x2):
    """The quantum kernel."""
    AngleEmbedding(x1, wires=range(n_qubits))
    qml.inv(AngleEmbedding(x2, wires=range(n_qubits)))
    return qml.expval(qml.Hermitian(projector, wires=range(n_qubits)))


kernel(X_train[0], X_train[0])

Here’s the output I get:

tensor(0.15190944, requires_grad=True)

The output must be close to 1 and I don’t get that for some reason. On returning qml.state I notice that performing AngleEmbedding twice or performing AngleEmbedding followed by qml.inv(AngleEmbedding) gives the same state with return qml.state. Meaning that the inverse is not being evaluated and instead there is an additional angle embedding layer. In other words,

def kernel(x1, x2):
"""The quantum kernel."""
AngleEmbedding(x1, wires=range(n_qubits))
AngleEmbedding(x2, wires=range(n_qubits))
return qml.state()

and

def kernel(x1, x2):
"""The quantum kernel."""
AngleEmbedding(x1, wires=range(n_qubits))
 qml.inv(AngleEmbedding(x2, wires=range(n_qubits)))
return qml.state()

gives me back the same state when I run kernel(X_train[0], X_train[0]). I am not sure why this is happening. Please let me know what I might be missing. I am on Pennylane v0.15.

Hey @kabirkhanna85!

You discovered a bug that sneaked into our last release, in which the inverse function was not working for templates any more. To fix it, we already released PennyLane version 0.15.1.

Would you mind updating your PL version to see if this fixes the issue?

Works like a charm! Thank you @Maria_Schuld :slight_smile: