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.