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
.